---
title: Checkout Status
api: GET /auth/checkout/{session_id}/status
description: "Poll for Stripe checkout completion. Response shape depends on whether the session was started in anonymous or authenticated mode."
---

> **For AI agents:** the complete documentation index is at [llms.txt](https://docs.boringmarketing.com/llms.txt). Append `.md` to any page URL for its markdown version.

Polls for completion of a checkout session started with [`POST /auth/checkout`](https://docs.boringmarketing.com/api-reference/auth/checkout). No authentication required — the opaque `session_id` from the checkout response is the correlator.

<Warning>
**This endpoint never returns an API key.** In an earlier version of the API, the poll endpoint returned `api_key` directly via a claim-once pattern. That path was closed because it let any caller who obtained a `session_id` claim the key after payment. Anonymous signups now retrieve their key via the dashboard with a magic-link login.
</Warning>

## Path parameters

<ParamField path="session_id" type="string" required>
  The `session_id` returned from `POST /auth/checkout`. An opaque `bmc_` correlator — the format does not leak account state.
</ParamField>

## Response shapes

The response depends on the session's server-recorded `auth_mode` and `session_kind`. There are four terminal states.

### 1. Pending

Payment has not completed. Poll again in 3-5 seconds.

```json
{ "status": "pending" }
```

### 2. Completed — anonymous checkout

```json
{
  "status": "completed",
  "dashboard_url": "https://dashboard.boringmarketing.com"
}
```

Stripe payment landed and the user's account was created or reactivated. **There is no `api_key` field.** To retrieve the key:

1. Open `dashboard_url` in a browser.
2. Enter the email used during checkout → receive a magic-link.
3. Click the link → land in the dashboard.
4. Copy the key from **Settings → API Access**.

<Note>
**Path split.** The steps above require a browser and an email inbox.

**If you're a human:** follow the list.

**If you're an agent running unattended:** you cannot complete anonymous-mode signup alone — hand `dashboard_url` to your human operator and wait for them to paste the key back. Agents that authenticated the original `POST /auth/checkout` get shape #3 below instead and already hold their key.
</Note>

### 3. Completed — authenticated checkout

```json
{
  "status": "completed",
  "tier": "studio",
  "calls_per_day": 5000,
  "brand_limit": 3
}
```

Stripe payment landed and the caller's tier was upgraded. The caller already has an API key (they authenticated on the original `POST /auth/checkout`), so this response just confirms the subscription update. No key is returned.

### 4. Portal opened

```json
{
  "status": "portal_opened",
  "dashboard_url": "https://dashboard.boringmarketing.com"
}
```

Terminal state for sessions where the "checkout URL" was actually a billing portal URL. This happens whenever the email already has an `active` subscription — both authenticated callers (who passed a matching `X-API-Key`) **and** anonymous callers whose email maps to an active account get a billing portal session instead of a fresh checkout. Billing portal sessions have no webhook-completable state, so this is a one-shot "stop polling" signal on the first call.

### 5. Session not found (404)

There is no `expired` status. If a session has been reaped by the checkout session reaper (expired sessions are cleaned up on each API process startup) or the `session_id` is otherwise unknown, the endpoint responds with:

```json
{ "detail": "Checkout session not found." }
```

with HTTP status `404`. Start a new session with `POST /auth/checkout`.

## Example — anonymous flow

```bash
SESSION_ID="bmc_k7f3..."

# Poll until completed
while true; do
  RESP=$(curl -sw "\n%{http_code}" "https://api.boringmarketing.com/auth/checkout/$SESSION_ID/status")
  BODY=$(echo "$RESP" | head -n1)
  CODE=$(echo "$RESP" | tail -n1)
  if [ "$CODE" = "404" ]; then
    echo "Session not found (reaped or invalid) — restart with POST /auth/checkout"
    exit 1
  fi
  STATUS=$(echo "$BODY" | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
  if [ "$STATUS" = "completed" ]; then
    DASHBOARD_URL=$(echo "$BODY" | python3 -c "import sys,json; print(json.load(sys.stdin)['dashboard_url'])")
    echo "Payment confirmed. Sign into $DASHBOARD_URL with a magic link to retrieve your API key."
    break
  fi
  sleep 5
done
```
