Payments
Create Payment Intent
Create a payment intent for embedded checkout.
POST
Intro
Create a payment intent tied to a product in your Khaime catalog. Returns aclient_secret (Stripe) for an embedded checkout on your own page, or an authorization_url (Paystack) for Paystack’s flow, plus a ready-made hosted-checkout payment_url as a redirect fallback if you’d rather not embed.
Context
Use this endpoint (or its/payments/intents alias) for a catalog-backed, embedded checkout. If your product lives outside Khaime’s catalog — e.g. WooCommerce or a custom platform — use Create Charge instead, which needs no product_id. Like Create Charge, the resulting payment is routed by currency (see Gateway Routing), can be made recurring via subscription_frequency_key (see Subscriptions), and its outcome is confirmed over webhooks — Get Session does not currently work as a status check for intents created here.
Hows
Request body
integer
required
ID of an existing, published Khaime product owned by your business. Must match your API key’s environment (a sandbox key can only resolve sandbox products, a live key only live products) — otherwise
404.The Joi schema also accepts
product_name as a fallback lookup field, but the controller currently rejects any request missing product_id before that fallback runs — product_name-only requests always fail with a “Missing required fields” error today. Always pass product_id.string
required
3-letter ISO currency code the customer pays in.
integer
Override amount in smallest currency unit. If omitted, the product’s catalog price is used.
object
required
string
Force a specific gateway instead of Khaime’s automatic currency-based routing. Only
stripe or paystack are accepted — you cannot force startbutton or flutterwave through this field.string
Set to make this a recurring payment (e.g.
monthly, yearly). Presence of this field (or subscription_plan_key) is what makes the intent a subscription — there is no separate boolean flag. See Subscriptions for the full list of valid keys.Recurring billing here is handled by Khaime’s own billing system —
subscription_id fields in the response are always null since renewals are managed internally.string
Alternative to
subscription_frequency_key when the product has named plans configured. If the plan has exactly one frequency option, it’s auto-selected.string
Where the customer lands after paying via Paystack’s redirect flow. Threaded into Paystack’s
callback_url so the buyer returns to your confirmation page directly.string
Redirect URL if the customer abandons a Paystack redirect payment.
object
Custom key-value pairs. No scalar-type enforcement is applied server-side — unlike Create Charge, you can pass nested values here, but avoid it: nested metadata can still fail downstream if the selected gateway’s API rejects non-string values.
Response
client_secret + publishable_key to mount the embedded payment element on your own page. For Paystack, use authorization_url (present instead of client_secret when payment_gateway resolves to paystack). Or simply redirect the customer to payment_url — Khaime’s own hosted checkout page — if you don’t want to embed anything.
Response fields
Error codes
Checking payment status
Get Session does not work as a status check for intents created through this route. This response has notransaction_id yet — that only exists once payment completes. Use webhooks (payment.succeeded / payment.failed) to learn the transaction id and confirm payment status; from then on you can also call Get Transaction to check status on demand.
Whys
/payments/sessions and /payments/intents are kept as aliases of the same handler rather than split into two endpoints because they answer the same question — “start a checkout for this catalog product” — and existing partner integrations reference both names from earlier iterations of this API. product_id is validated against your API key’s live/sandbox environment (not just ownership) so a sandbox key can never accidentally create a live-money intent against a live product.
Why nots
- This is not the endpoint for products that don’t exist in Khaime’s catalog — use Create Charge for that.
- It does not create a real Stripe Checkout Session — despite the endpoint name, there is no
checkout.stripe.comURL in the response. product_name-only lookup does not work today, despite being accepted by the validation schema — always sendproduct_id.- There is no way to poll status using the intent itself — Get Session doesn’t work here. Rely on webhooks to learn the transaction id, then Get Transaction if you also want on-demand polling after that.
