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:

{
  "id": "cs_01H…",
  "client_secret": "cs_01H…_secret_a7f9…",
  "checkout_url": "https://payments.spuke.com/c/cs_01H…?cs=cs_01H…_secret_a7f9…",
  "embed_url":    "https://payments.spuke.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):

const session = await fetch("https://api.spuke.com/v1/checkout/sessions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SPUKE_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:

<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.