Create Stripe Setup Intent
const url = 'https://example.com/api/billing/stripe/setup-intent?organization_id=2489E9AD-2EE2-8E00-8EC9-32D5F69181C0';const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url 'https://example.com/api/billing/stripe/setup-intent?organization_id=2489E9AD-2EE2-8E00-8EC9-32D5F69181C0' \ --header 'Authorization: Bearer <token>'Mint a Stripe SetupIntent so the console can tokenize a card.
The client secret is the only thing that crosses the wire; the card itself goes browser → Stripe and never touches this server (PCI SAQ-A, §5).
SetupIntent is deliberately not on PaymentGatewayAdapter: the ABC
covers the five subscription-lifecycle calls every gateway has, and a
standalone setup intent is a Stripe-shaped concept with no Razorpay/PayPal
counterpart. Adding it there would make the interface describe Stripe
rather than the domain, so this route talks to the SDK directly — under
the same stripe.api_key discipline stripe_adapter.py documents (a
process-wide module global, reassigned immediately before the call so a
key rotated in settings is never shadowed).
Card-only, deliberately. automatic_payment_methods offers whatever the
account has configured — the console was rendering Pix, Klarna, Naver Pay
and Kakao Pay alongside Card — but the rest of this pipeline can only
charge a card: StripeAdapter.create_subscription pins the tokenized
method as invoice_settings.default_payment_method and bills it
off-session every period. Letting a customer set up a method that cannot
be charged that way buys them a subscription that fails on its first
renewal, so the restriction belongs on the intent (the only place that can
impose it — Elements derives its method list from the intent, and cannot
narrow it client-side).
Authorizations
Section titled “ Authorizations ”Parameters
Section titled “ Parameters ”Query Parameters
Section titled “ Query Parameters ”Responses
Section titled “ Responses ”Successful Response
POST /api/billing/stripe/setup-intent — what Stripe Elements needs.
Only the client secret crosses the wire. The gateway customer id it was minted against stays server-side, Fernet-encrypted in payment_references.provider_customer_id.
object
Example generated
{ "client_secret": "example"}Validation Error
object
object
object
Example generated
{ "detail": [ { "ctx": {}, "input": "example", "loc": [ "example" ], "msg": "example", "type": "example" } ]}