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_secretlike 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}/expireto invalidate itsclient_secretearly.