> ## Documentation Index
> Fetch the complete documentation index at: https://docs.straddle.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Python SDK for Straddle

> Install and configure the official Straddle Python SDK. Authenticate, make API calls, handle errors, and integrate ACH payments into your Python application.

The Straddle Python SDK provides convenient access to the Straddle API from any Python application. The SDK includes type definitions and offers both synchronous and asynchronous clients powered by httpx.

<Info>
  The SDK supports Python 3.8+ and provides comprehensive type hints through TypedDict and Pydantic models.
</Info>

## Installation

Install the SDK using pip:

```bash theme={null}
pip install straddle
```

For development environments, we recommend using [python-dotenv](https://pypi.org/project/python-dotenv/) to manage your API keys:

```bash theme={null}
pip install python-dotenv
```

## Setup and Configuration

<Steps>
  <Step title="Import the SDK" icon="file-import">
    Import the appropriate client based on your needs:

    ```python theme={null}
    from straddle import AsyncStraddle
    ```
  </Step>

  <Step title="Initialize the Client" icon="gear">
    Create a new instance of the Straddle client:

    ```python theme={null}
    client = AsyncStraddle(
        api_key=os.environ.get("STRADDLE_API_KEY"),
        environment="sandbox", # or "production"
    )
    ```

    <Warning>
      Never hardcode your API key directly in your code. Use environment variables or a secure configuration
      management system.
    </Warning>
  </Step>
</Steps>

## Implementation Examples

<Tabs>
  <Tab title="Straddle Account Customers">
    For account customers (non-platform), the flow is simpler as the account context is inferred from the API key:

    ```python theme={null}
    import asyncio
    from straddle import AsyncStraddle
    from pydantic.v1.datetime_parse import parse_date
    from straddle.types import DeviceUnmaskedV1Param

    async def account_flow():
        client = AsyncStraddle(
            api_key=os.environ.get("STRADDLE_API_KEY"),
            environment="sandbox"
        )

        # 1. Create a customer
        customer_response = await client.customers.create(
            device=DeviceUnmaskedV1Param(ip_address="192.168.0.1"),
            email="customer@example.com",
            name="Customer Name",
            phone="+15555555555",
            type="individual"
        )
        customer = customer_response.data

        # 2. Link a bank account
        paykey_response = await client.bridge.link.bank_account(
            customer_id=customer.id,
            routing_number="011000028",
            account_number="000123456789",
            account_type="checking"
        )
        paykey = paykey_response.data

        # 3. Create a charge
        charge = await client.charges.create(
            amount=1,
            config={"balance_check": "required"},
            consent_type="internet",
            currency="USD",
            description="Monthly subscription fee",
            device={"ip_address": "192.168.1.1"},
            external_id="external_id",
            paykey=paykey.paykey,
            payment_date=parse_date("2025-01-30")
        )
        print(charge.data)

    if __name__ == '__main__':
        asyncio.run(account_flow())
    ```
  </Tab>

  <Tab title="Embed Customers">
    This example demonstrates the complete flow for Embed customers using the async client:

    ```python theme={null}
    import asyncio
    from straddle import AsyncStraddle
    from pydantic.v1.datetime_parse import parse_date
    from straddle.types import DeviceUnmaskedV1Param
    from straddle.types.embed import BusinessProfileV1Param

    async def embed_flow():
        client = AsyncStraddle(
            api_key=os.environ.get("STRADDLE_API_KEY"),
            environment="sandbox"
        )

        # 1. Create an organization
        org_response = await client.embed.organizations.create(
            name="SDK Test Organization in Sandbox",
        )
        organization = org_response.data

        # 2. Create an account for the organization
        account_response = await client.embed.accounts.create(
            organization_id=organization.id,
            account_type="business",
            business_profile=BusinessProfileV1Param(
                name="SDK Test",
                website="straddle.com"
            ),
            access_level="standard"
        )
        account = account_response.data

        # 3. Create a customer
        customer_response = await client.customers.create(
            straddle_account_id=account.id,
            device=DeviceUnmaskedV1Param(ip_address="192.168.0.1"),
            email="customer@example.com",
            name="Customer Name",
            phone="+15555555555",
            type="individual"
        )
        customer = customer_response.data

        # 4. Link a bank account
        paykey_response = await client.bridge.link.bank_account(
            straddle_account_id=account.id,
            customer_id=customer.id,
            routing_number="011000028",
            account_number="000123456789",
            account_type="checking"
        )
        paykey = paykey_response.data

        # 5. Create a charge
        charge = await client.charges.create(
            straddle_account_id=account.id,
            amount=1,
            config={"balance_check": "required"},
            consent_type="internet",
            currency="USD",
            description="Monthly subscription fee",
            device={"ip_address": "192.168.1.1"},
            external_id="external_id",
            paykey=paykey.paykey,
            payment_date=parse_date("2025-01-30"),
        )
        print(charge.data)

    if __name__ == '__main__':
        asyncio.run(embed_flow())
    ```
  </Tab>
</Tabs>

## Key Features

<CardGroup cols={2}>
  <Card title="Type Safety" icon="shield-check">
    Built-in type hints with TypedDict for requests and Pydantic models for responses, providing excellent IDE
    support and catch errors early.
  </Card>

  <Card title="Async Support" icon="bolt">
    First-class async/await support through the AsyncStraddle client, perfect for high-performance applications.
  </Card>

  <Card title="Automatic Pagination" icon="list-tree">
    Built-in support for automatic pagination, making it easy to handle large result sets.
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation">
    Comprehensive error types and helpful error messages for better debugging and error recovery.
  </Card>
</CardGroup>

## Error Handling

The SDK provides specific exception types for different error cases:

<AccordionGroup>
  <Accordion icon="bug" title="Common Error Types">
    ```python theme={null}
    try:
    charge = await client.charges.create(
        amount=1000,
        currency="USD",
        # ... other required params
    )
    except straddle.APIConnectionError as e:
        print("Connection error:", e.__cause__)
    except straddle.RateLimitError as e:
        print("Rate limit exceeded:", e.status_code)
    except straddle.APIStatusError as e:
        print("API error:", e.status_code)
        print("Response:", e.response)
    ```

    Common error types include:

    * `BadRequestError` (400)
    * `UnprocessableEntityError` (422)
    * `AuthenticationError` (401)
    * `PermissionDeniedError` (403)
    * `NotFoundError` (404)
    * `RateLimitError` (429)
    * `InternalServerError` (>500)
  </Accordion>

  <Accordion icon="clock" title="Timeout Configuration">
    Configure request timeouts:

    ```python theme={null}
    import httpx

    # Simple timeout
    client = AsyncStraddle(timeout=20.0) # 20 seconds

    # Detailed timeout configuration
    client = AsyncStraddle(
        timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0)
    )
    ```
  </Accordion>
</AccordionGroup>

## SDK Requirements

<CardGroup cols={2}>
  <Card title="Python Version" icon="python">
    Python 3.8 or higher
  </Card>
</CardGroup>

For more detailed information about the SDK structure and usage, refer to our [Pypi Package](https://pypi.org/project/straddle/).
