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

# Sessions

> Core concept: session lifecycle, statuses, and credential model

A **session** represents a single deposit attempt. It tracks the full lifecycle from creation through delivery.

## Session lifecycle

```mermaid theme={null}
stateDiagram-v2
    [*] --> requires_payment_method: Create session
    requires_payment_method --> waiting_payment: Set payment method
    waiting_payment --> processing: Deposit detected
    processing --> succeeded: Funds delivered
    processing --> bounced: Delivery failed
    requires_payment_method --> expired: Timeout
    waiting_payment --> expired: Timeout
```

### Statuses

| Status                    | Description                                                                     |
| ------------------------- | ------------------------------------------------------------------------------- |
| `requires_payment_method` | Session created, waiting for the user to choose how to pay                      |
| `waiting_payment`         | Payment method set, waiting for the user's deposit transaction                  |
| `processing`              | Deposit detected, funds are being routed to the destination                     |
| `succeeded`               | Funds delivered to the destination address                                      |
| `bounced`                 | Delivery failed (e.g. contract call reverted), funds returned to refund address |
| `expired`                 | Session timed out before a deposit was received                                 |

Terminal statuses: `succeeded`, `bounced`, `expired`. Once terminal, a session cannot change status.

## Credential model

Daimo uses two types of credentials:

### API key

Your account-wide API key. Use it **server-side only** for operations that require full access:

* Creating sessions
* Retrieving full session details (including `clientSecret` and `metadata`)

Pass it as a Bearer token:

```
Authorization: Bearer <your API key>
```

### Client secret

A per-session token returned when you create a session. It grants limited access to that single session:

* Setting the payment method
* Checking session status

The client secret is safe to expose in browser code. Pass it in the request body (or query string for GET requests):

```json theme={null}
{ "clientSecret": "d7a8f3b2..." }
```

## Session object

When retrieved with an API key, the full session includes:

| Field           | Type             | Description                                          |
| --------------- | ---------------- | ---------------------------------------------------- |
| `sessionId`     | `string`         | Unique 32-character hex ID                           |
| `status`        | `string`         | One of the statuses above                            |
| `destination`   | `object`         | Where funds are delivered (see below)                |
| `display`       | `object`         | UI metadata: `title`, `verb`, optional `themeCssUrl` |
| `paymentMethod` | `object \| null` | How the user is paying (see below)                   |
| `metadata`      | `object \| null` | Key-value pairs set at creation                      |
| `clientSecret`  | `string`         | Per-session client credential                        |
| `createdAt`     | `number`         | Unix timestamp (seconds)                             |
| `expiresAt`     | `number`         | Unix timestamp (seconds)                             |

Without an API key, `metadata` and `clientSecret` are omitted (returns `SessionPublicInfo`).

### Destination

```typescript theme={null}
{
  type: "evm",
  address: "0x...",       // destination address
  chainId: 8453,          // e.g. Base
  chainName: "Base",
  tokenAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",  // e.g. USDC
  tokenSymbol: "USDC",
  amountUnits: "10.00",   // requested amount (optional)
  delivery: {             // set once funds are delivered
    txHash: "0x...",
    receivedUnits: "10.00"
  }
}
```

Deposits can also be delivered to **Solana** (USDC only):

```typescript theme={null}
{
  type: "solana",
  address: "7xKX...",     // base58 destination address
  tokenAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",  // USDC mint
  tokenSymbol: "USDC",
  amountUnits: "10.00",   // requested amount (optional)
  delivery: {             // set once funds are delivered
    txHash: "5Uu...",     // Solana transaction signature
    receivedUnits: "10.00"
  }
}
```

A Solana destination uses the token mint as `tokenAddress`, omits `chainId`, `chainName`, and `calldata`, and its `delivery.txHash` is a Solana transaction signature.

### Payment methods

To collect a deposit, you first set a payment method on the session by calling `POST /v1/sessions/{id}/paymentMethods`. This transitions the session to `waiting_payment` and returns the information needed to complete the deposit.

Four types, depending on the source:

#### EVM

Deposit from any of our [supported EVM chains](/supported-chains#destination-chains). The response includes a single-use `receiverAddress` in `session.paymentMethod`. Display this address so the user can send funds to it.

```json theme={null}
{ "type": "evm", "receiverAddress": "0x...", "createdAt": 1700000000 }
```

#### Tron

Deposit USDT from Tron. The response includes a `tron.receiverAddress`, a single-use Tron address where the user sends USDT. It can also include `tron.deeplinks.trustWallet`, a Trust Wallet send link for the same address and amount.

```json theme={null}
{ "type": "tron", "receiverAddress": "T...", "createdAt": 1700000000 }
```

#### Solana

Deposit from Solana. The response includes `solana.serializedTx`, a hex-encoded serialized transaction for the wallet to sign and submit.

This preserves a one-click wallet flow on Solana by bundling actions into one signed transaction.

```json theme={null}
{ "type": "solana", "createdAt": 1700000000 }
```

#### Fiat

Hosted fiat deposit. The user pays in local currency via one of the fiat rails enabled for your org (e.g. Interac in Canada, ACH and Apple Pay in the US, or SEPA in Europe), and Daimo delivers the stablecoin to your destination — same session lifecycle as any other payment method.

The response includes `fiat.hostedUrl`, a URL to a Daimo-hosted page that handles identity verification and the fiat transfer. Open it in a native [WebView](/guides/webview) or a new browser tab; the user returns to your app after completing the flow.

```json theme={null}
{ "type": "fiat", "fiatMethod": "interac", "createdAt": 1700000000 }
```

```json theme={null}
{
  "fiat": {
    "hostedUrl": "https://daimo.com/webview?session=...&cs=...",
    "fiatMethod": "interac"
  }
}
```

Pass `paymentMethod.fiatMethod` (one of `interac`, `ach`, `sepa`, `apple_pay`) to pin the hosted flow to one rail. If omitted, the hosted page lists every fiat method enabled for the org.

The `hostedUrl` is returned only once from `createPaymentMethod` — store it on the client. It is not included when retrieving the session later.

<Info>
  Fiat rails are enabled per-org. To request access, [contact
  us](mailto:support@daimo.com).
</Info>

Each payment method gains a `source` object once the user's deposit transaction is detected, containing chain info, token details, and the source transaction hash.

See [Create Payment Method](/api-reference/create-payment-method) for full request/response details.

## Customization

Use the Daimo dashboard to match the modal and hosted WebView to your brand. The org theme applies automatically through `display.themeCssUrl`.

See [Customization](/guides/customization) for the dashboard flow, JSON format, and per-session CSS override.

## Polling for status

Use `PUT /v1/sessions/{id}/check` with the client secret to poll for status updates after the user has paid. This is how the modal tracks deposit progress, and how custom integrations can monitor sessions from the client side.

For most integrations, the modal handles polling automatically.
