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

# Get checkout session status

> Poll this public Minisend endpoint to track a checkout session from pending through settlement. Returns status, exchange rate, and receipt.

Public — no API key needed. Safe to call from a frontend.

On every call, this endpoint also expires stale `pending` sessions past their deadline and cross-checks `settling` sessions that have been in flight >2 minutes against the settlement provider.

## Endpoint

```text theme={null}
GET https://merchant.minisend.xyz/api/merchant/checkout/{session_id}
```

No auth.

## Path

<ParamField path="session_id" type="string" required>
  Returned from `POST /api/merchant/checkout`. Starts with `cs_`.
</ParamField>

## Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl https://merchant.minisend.xyz/api/merchant/checkout/cs_7f8a9b2c-1234-5678-abcd-ef0123456789
  ```

  ```javascript Node.js theme={null}
  const res = await fetch(
    `https://merchant.minisend.xyz/api/merchant/checkout/${sessionId}`
  );
  const session = await res.json();
  ```

  ```python Python theme={null}
  import requests

  res = requests.get(
      f"https://merchant.minisend.xyz/api/merchant/checkout/{session_id}"
  )
  session = res.json()
  ```
</CodeGroup>

## Response

```json theme={null}
{
  "session_id": "cs_7f8a9b2c-1234-5678-abcd-ef0123456789",
  "status": "completed",
  "amount_usdc": 25.00,
  "description": "Order #4821",
  "deposit_address": "0x1234567890abcdef1234567890abcdef12345678",
  "expires_at": "2026-04-13T14:30:00.000Z",
  "created_at": "2026-04-13T14:00:00.000Z",
  "amount_local": 3225.00,
  "exchange_rate": 129.00,
  "settlement_receipt": "SHQ1234ABC",
  "completed_at": "2026-04-13T14:08:22.000Z",
  "merchant": {
    "business_name": "My Store",
    "logo_url": null
  }
}
```

<ResponseField name="status" type="string" required>
  Current status. See [lifecycle](#status-lifecycle).
</ResponseField>

<ResponseField name="amount_usdc" type="number" required>
  USDC-equivalent. Customer may pay in USDC or USDT.
</ResponseField>

<ResponseField name="deposit_address" type="string" required>
  Accepts USDC (19 chains) and USDT (14 chains).
</ResponseField>

<ResponseField name="amount_local" type="number">
  Net local currency after the 1% fee. Present when `status` is `"completed"`.
</ResponseField>

<ResponseField name="exchange_rate" type="number">
  USDC → local rate at settlement. Present when `status` is `"completed"`.
</ResponseField>

<ResponseField name="settlement_receipt" type="string">
  Payout provider receipt (e.g., M-Pesa code). Present when `status` is `"completed"`.
</ResponseField>

<ResponseField name="completed_at" type="string">
  ISO 8601. Present when `status` is `"completed"`.
</ResponseField>

<ResponseField name="merchant" type="object" required>
  Display info.

  <Expandable title="properties">
    <ResponseField name="merchant.business_name" type="string" required />

    <ResponseField name="merchant.logo_url" type="string | null" required />
  </Expandable>
</ResponseField>

## Status lifecycle

```text theme={null}
pending → deposit_received → settling → completed
                                      → failed
pending → expired  (after 30 minutes)
```

| Status             | Meaning                                 |
| ------------------ | --------------------------------------- |
| `pending`          | Waiting for the customer to send        |
| `deposit_received` | Detected on-chain; settlement initiated |
| `settling`         | Conversion + payout in progress         |
| `completed`        | Payout delivered                        |
| `failed`           | Failed post-deposit — contact support   |
| `expired`          | No deposit within 30 minutes            |

## Polling

```javascript theme={null}
async function waitForPayment(sessionId, timeoutMs = 30 * 60 * 1000) {
  const deadline = Date.now() + timeoutMs;

  while (Date.now() < deadline) {
    const res = await fetch(
      `https://merchant.minisend.xyz/api/merchant/checkout/${sessionId}`
    );
    const session = await res.json();

    if (session.status === 'completed') return session;
    if (session.status === 'failed' || session.status === 'expired') {
      throw new Error(`Session ended: ${session.status}`);
    }

    await new Promise((r) => setTimeout(r, 3000));
  }

  throw new Error('Timed out');
}
```

<Note>
  Prefer webhooks over polling. Configure `webhook_url` in **Settings** to receive `checkout.completed`, `checkout.failed`, and `checkout.expired` events.
</Note>
