API REFERENCE
Create Credits Top-Up Session
On this page
/api/credits/sessionsTop up credits on the authenticated account.
Credits are integer micro-dollars (1,000,000 = $1.00, the same 6-decimal unit as USDC). The customer is charged the USD value of credits plus a Stripe processing fee (US card pricing: 2.9% + $0.30) — e.g. credits: 100000000 charges $103.30 total ($100.00 credits + $3.30 fee).
Two outcomes, distinguished by response shape:
- Auto-charged — if the account has a card on file (from a prior subscription or top-up), the card is charged immediately and the response is { paymentIntentId, creditsPurchased, totalCents }. Credits land in the account's balance asynchronously via Stripe webhook (typically within seconds). No human interaction required.
- Checkout required — if no card is on file, or the saved card requires 3-D Secure authentication, the response is { id, url } with a hosted Stripe Checkout URL. Redirect to that URL; credits land on successful payment.
Clients should discriminate on the presence of url (Checkout) vs paymentIntentId (auto-charged). Cards entered through the Checkout fallback are saved for future top-ups, so a customer's second top-up typically auto-charges.
Authentication
x-api-key in header
bearerAuth bearer
Request
curl --request POST \
--url 'https://api.recoupable.dev/api/credits/sessions' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"credits": 250
}'Request body required
Top-up parameters
application/json
successUrlstringThe URL to redirect the customer to after a successful Stripe Checkout payment. Only used when the response is a Checkout fallback (no card on file or 3-D Secure required) — ignored when the card on file is charged directly. Defaults to a generic Recoup success page if omitted.
format: uri
creditsintegerrequiredThe number of credits to purchase, in integer micro-dollars (1,000,000 = $1.00), so the value in USD is credits / 1000000. Example: 2500000 is $2.50 worth of credits (the customer is also charged a Stripe processing fee on top).
minimum: 1
accountIdstringUUID of the account to create the session for. Only applicable when the authenticated account has admin access to multiple accounts. If not provided, creates a session for the API key's own account.
format: uuid
Responses
200Top-up initiated successfully. Some fields are conditional on which path was taken — see each field's description.+
application/json
paymentIntentIdstringAuto-charge path only. The Stripe PaymentIntent ID for the off-session charge. Useful for reconciliation and support. Omitted on the Checkout fallback path.
creditsPurchasedintegerAuto-charge path only. The number of credits purchased, matching the credits request field. These credits are added to the account's balance asynchronously via Stripe webhook (typically within seconds). Omitted on the Checkout fallback path.
minimum: 1
totalCentsintegerAuto-charge path only. Total amount in cents charged to the saved card, equal to creditsPurchased plus the Stripe processing fee. Omitted on the Checkout fallback path.
minimum: 1
idstringCheckout fallback only. The Stripe Checkout Session ID. Omitted on the auto-charge path.
urlstringCheckout fallback only. The hosted Stripe Checkout URL — redirect the customer here to enter card details and complete payment. Omitted on the auto-charge path.
format: uri
400Bad request - missing or invalid parameters+
application/json
errorstringrequiredHuman-readable error message.
401Unauthorized - invalid or missing authentication+
application/json
errorstringrequiredHuman-readable error message.
Full specification
Download the OpenAPI file for complete schemas, constraints, and examples.
Download accounts.jsonView operation source
{
"description": "Top up credits on the authenticated account.\n\n**Credits are integer micro-dollars (1,000,000 = \\$1.00, the same 6-decimal unit as USDC).** The customer is charged the USD value of `credits` plus a Stripe processing fee (US card pricing: 2.9% + \\$0.30) — e.g. `credits: 100000000` charges \\$103.30 total (\\$100.00 credits + \\$3.30 fee).\n\n**Two outcomes, distinguished by response shape:**\n\n- **Auto-charged** — if the account has a card on file (from a prior subscription or top-up), the card is charged immediately and the response is `{ paymentIntentId, creditsPurchased, totalCents }`. Credits land in the account's balance asynchronously via Stripe webhook (typically within seconds). No human interaction required.\n\n- **Checkout required** — if no card is on file, or the saved card requires 3-D Secure authentication, the response is `{ id, url }` with a hosted Stripe Checkout URL. Redirect to that URL; credits land on successful payment.\n\nClients should discriminate on the presence of `url` (Checkout) vs `paymentIntentId` (auto-charged). Cards entered through the Checkout fallback are saved for future top-ups, so a customer's second top-up typically auto-charges.",
"security": [
{
"apiKeyAuth": []
},
{
"bearerAuth": []
}
],
"requestBody": {
"description": "Top-up parameters",
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateCreditsSessionRequest"
}
}
}
},
"responses": {
"200": {
"description": "Top-up initiated successfully. Some fields are conditional on which path was taken — see each field's description.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreditsTopupResponse"
}
}
}
},
"400": {
"description": "Bad request - missing or invalid parameters",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreditsSessionErrorResponse"
}
}
}
},
"401": {
"description": "Unauthorized - invalid or missing authentication",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreditsSessionErrorResponse"
}
}
}
}
}
}