> This page is for version 2024-10-01 (default).
> For other versions, use one of these documentation indexes:
> - 2024-10-01 (default): https://docs.getkard.com/2024-10-01/llms.txt
> - Legacy: https://docs.getkard.com/legacy/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.getkard.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.getkard.com/_mcp/server.

# Getting Started

This guide walks you through installing the [**Kard Python SDK**](https://github.com/KardFinancial/kard-python-sdk/), authenticating with the Kard API, and making your first request.

## Prerequisites
- **Python 3.8+**
- **`KARD_CLIENT_ID` and `KARD_CLIENT_SECRET`**
- **Package manager:** `pip`

## Install the SDK
```bash
pip install kard-financial-sdk
```

## Create a Client
Import and instantiate the `KardApi` client using your credentials.

This SDK supports two authentication methods:

**OAuth Client Credentials**
```python
from kard import KardApi

client = KardApi(
    ..., client_id="your-client-id", client_secret="your-client-secret"
)
```
**Bearer Token Authentication**
```python
from kard import KardApi

client = KardApi(..., token="my-pre-generated-bearer-token")
```

The client automatically handles **authentication, retries, and timeouts**.

## Make Your First API Calls

**1.** [Creating a User](https://docs.getkard.com/api/users/create):
```python
from kard import KardApi
from kard.users import UserRequestAttributes, UserRequestDataUnion_User

client = KardApi(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
)

client.users.create(
    organization_id="organization-123",
    data=[
        UserRequestDataUnion_User(
            id="1234567890",
            attributes=UserRequestAttributes(
                zip_code="11238",
                enrolled_rewards=["CARDLINKED"],
            ),
        )
    ],
)
```

To enhance offer targeting and attribution, you can include a **hashed email (HEM)** when creating users. The SDK includes a built-in `generate_hem` utility that normalizes and hashes email addresses:

```python
from kard import KardApi
from kard.hem import generate_hem
from kard.users import UserRequestAttributes, UserRequestDataUnion_User

client = KardApi(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
)

hashed_email = generate_hem("Jane.Doe+work@gmail.com")

client.users.create(
    organization_id="organization-123",
    data=[
        UserRequestDataUnion_User(
            id="1234567890",
            attributes=UserRequestAttributes(
                enrolled_rewards=["CARDLINKED"],
                hashed_email=hashed_email,
            ),
        )
    ],
)
```

The function normalizes the email before hashing (removes whitespace, lowercases, and handles Gmail-specific rules like dot and `+` suffix removal). It raises a `ValueError` for invalid inputs.

**2.** [Fetching Offers for User with Extended API](https://docs.getkard.com/api/rewards/offers):
```python
from kard import KardApi

client = KardApi(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
)

client.users.rewards.offers(
    organization_id="organization-123",
    user_id="1234567890",
    page_size=1,
    filter_is_targeted=True,
    sort="-startDate",
    supported_components=[
        "shortDescription",
        "longDescription",
        "cta",
        "tags",
        "detailTags",
        "baseReward",
    ],
)
```

**3.** [Submitting Transaction for User](https://docs.getkard.com/api/transactions/create):
```python
import datetime
from kard import KardApi
from kard.transactions import (
    Merchant,
    Transactions_Transaction,
    TransactionsAttributes,
)

client = KardApi(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
)

client.transactions.create(
    organization_id="organization-123",
    data=[
        Transactions_Transaction(
            id="12345610",
            attributes=TransactionsAttributes(
                user_id="1234567890",
                amount=1000,
                subtotal=800,
                status="APPROVED",
                currency="USD",
                description="ADVANCEAUTO",
                authorization_date=datetime.datetime.fromisoformat(
                    "2021-07-02 17:47:06+00:00",
                ),
                payment_type="CARD",
                direction="DEBIT",
                merchant=Merchant(
                    id="12345678901234567",
                    name="ADVANCEAUTO",
                    addr_street="125 Main St",
                    addr_city="Philadelphia",
                    addr_state="PA",
                    addr_zipcode="19147",
                    addr_country="United States",
                    latitude="37.9419429",
                    longitude="-73.1446869",
                    storeId="12345",
                ),
                card_bin="123456",
                card_last_four="4321",
                authorization_code="123456",
                retrieval_reference_number="100804333919",
                system_trace_audit_number="333828",
                acquirer_reference_number="1234567890123456789012345678",
                transaction_id="12345611",
            ),
        )
    ],
)
```

All SDK methods return **typed responses and raise typed errors**.

## Async Client
The SDK also provides an async client for non-blocking API calls.

```python
import asyncio
from kard import AsyncKardApi
from kard.users import UserRequestAttributes, UserRequestDataUnion_User

client = AsyncKardApi(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
)

async def main() -> None:
    await client.users.create(
        organization_id="organization-123",
        data=[
            UserRequestDataUnion_User(
                id="1234567890",
                attributes=UserRequestAttributes(
                    zip_code="11238",
                    enrolled_rewards=["CARDLINKED"],
                ),
            )
        ],
    )

asyncio.run(main())
```

## Handling Errors
If an API request fails (4xx or 5xx), the SDK raises an `ApiError`.

```python
from kard.core.api_error import ApiError

try:
    client.users.create(...)
except ApiError as e:
    print("Status:", e.status_code)
    print("Body:", e.body)
```

## Common Configuration Options

### Configure Retries
Retries are enabled by default (max 2 attempts).

```python
client.users.create(
    ...,
    request_options={
        "max_retries": 1
    }
)
```

### Set a Timeout
The SDK defaults to a 60 second timeout. Timeouts can be configured at the client or request level.

```python
client = KardApi(
    ...,
    timeout=20.0,
)

client.users.create(..., request_options={
    "timeout_in_seconds": 1
})
```

## Access Raw HTTP Responses
To inspect headers or status codes, use `with_raw_response`.

```python
response = client.users.with_raw_response.create(...)

print(response.headers)
print(response.data)
```

## Custom HTTP Client
You can supply a custom `httpx.Client` to customize transports, proxies, or networking behavior.

```python
import httpx
from kard import KardApi

client = KardApi(
    ...,
    httpx_client=httpx.Client(
        proxy="http://my.test.proxy.example.com",
        transport=httpx.HTTPTransport(local_address="0.0.0.0"),
    ),
)
```