# The client_secret

What it is, how long it lives, and how to use it safely.

# The client_secret

Each Checkout Session returns a `client_secret` alongside its `id`:

```json
{
  "id": "cs_01H…",
  "client_secret": "cs_01H…_secret_a7f9…",
  "checkout_url": "https://payments.southbill.com/c/cs_01H…?cs=cs_01H…_secret_a7f9…",
  "embed_url":    "https://payments.southbill.com/embed/cs_01H…?cs=cs_01H…_secret_a7f9…"
}
```

## What it does

The `client_secret` authorises **one specific browser session** to load the hosted checkout for that session. It is scoped to a single `cs_…` id and cannot be used to create, modify, refund, or list anything.

It is safe to send to the browser (embed page, redirect URL, iframe `src`). It is **not** safe to log publicly or share across users — anyone with the value can open that particular checkout.

## Lifetime

| Event | Effect on `client_secret` |
|---|---|
| Session created | Valid for **24 hours** or until session `status` changes. |
| Session `complete` / `expired` / `canceled` | Immediately invalid — loading the checkout returns `session_expired`. |
| Session paid via async method (SEPA, Klarna) | Immediately invalid; buyer is redirected to `success_url`. |

There is no way to renew a `client_secret`. If it expires, create a new Checkout Session and redirect to the new `checkout_url`.

## Correct usage

**Backend (your server):**

```ts
const session = await fetch("https://api.southbill.com/v1/checkout/sessions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SOUTHBILL_SECRET_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": `order_${orderId}`,
  },
  body: JSON.stringify({ amount: 4990, currency: "eur", customer_name, customer_email }),
}).then(r => r.json());

// Redirect the buyer:
res.redirect(303, session.checkout_url);

// OR return only what the browser needs:
res.json({ embed_url: session.embed_url });
```

**Frontend:**

```html
<iframe src="{embed_url}" allow="payment" width="100%" height="720"></iframe>
```

Never send `sk_live_…` or `sk_test_…` to the browser. The browser only ever sees `client_secret` / `checkout_url` / `embed_url`.

## Security notes

- Treat the `client_secret` like a one-time link: don't email it, don't index it, don't put it in shared logs.
- If a buyer abandons a session, you can call `POST /v1/checkout/sessions/{id}/expire` to invalidate its `client_secret` early.

