post__credits_packs_buy
POST /credits/packs/buy
Buy a Credit Pack
Initiates a Stripe Checkout session to purchase a credit pack for the authenticated user's organization. The request body must include the pack ID (from GET /credits/packs). The organization must have a paid subscription (Starter or above); Free tier cannot buy packs. A per-pack-type limit per billing cycle applies (e.g. 3 of each pack per cycle). On success, the response includes a checkout URL and session ID; the user is redirected to Stripe to complete payment. Credits are added to the organization when the payment succeeds (via webhook).
TypeScript Client Library
public buyCreditsPack = async (body: BuyCreditsPackRequest): Promise<BuyCreditsPackResponse> => {
return this.makeRequest<BuyCreditsPackResponse>('credits/packs/buy', 'POST', body);
};Code Samples
curl -X POST https://backend.flashback.tech/credits/packs/buy \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {access-token}' \
-d '{"packId": "pack-1"}'POST https://backend.flashback.tech/credits/packs/buy HTTP/1.1
Host: backend.flashback.tech
Accept: application/json
Content-Type: application/json
Authorization: Bearer {access-token}
{"packId": "pack-1"}const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer {access-token}'
};
const body = { packId: 'pack-1' };
fetch('https://backend.flashback.tech/credits/packs/buy', {
method: 'POST',
headers,
body: JSON.stringify(body)
})
.then(res => res.json())
.then(data => {
if (data.success && data.checkoutUrl) window.location.href = data.checkoutUrl;
});Example responses
200 Response
{
"success": true,
"checkoutUrl": "https://checkout.stripe.com/c/pay/cs_xxx",
"sessionId": "cs_xxx"
}400 Response (credits not enabled)
403 Response (not authorized / Free tier)
403 Response (no billing permission)
404 Response (pack not found)
429 Response (pack limit reached)
500 Response
Request Body
» packId
string
true
Credit pack ID (from GET /credits/packs)
Responses
200
OK
Checkout URL and session ID
Inline
400
Bad Request
Credits not enabled, no org, or pack not configured
Inline
403
Forbidden
No billing permission or Free tier
Inline
404
Not Found
User, org, or pack not found
Inline
429
Too Many Requests
Pack limit reached for this billing cycle
Inline
500
Internal Server Error
Server error
Inline
Response Schema (200)
» success
boolean
false
Whether the request succeeded
» checkoutUrl
string | null
false
Stripe Checkout URL; redirect user here to pay
» sessionId
string
false
Stripe Checkout Session ID
» error_code
string
false
Set on error
» message
string
false
Error or status message
» nextAvailableAt
string (date-time)
false
When limit reached: next date a pack of this type can be bought
Security
BearerAuth: Bearer token required.
Organization: Purchase is for the user's organization.
Role / subscription: User must have billing permission; organization must have a paid subscription (Starter or above).
Notes
Redirect the user to
checkoutUrlto complete payment. After payment, Stripe redirects back to the app (success/cancel URLs are set by the backend).Credits are added to the organization when the Stripe webhook receives the successful payment; no need to poll from the client.
Limit is per pack type per billing cycle (e.g. 3× Pack 1, 3× Pack 2, 3× Pack 3 in the same cycle). Billing cycle is based on "day X" from the org's subscription start date.
If the pack has no Stripe price configured, the backend returns 400 with
STRIPE_NOT_CONFIGURED.
Last updated
Was this helpful?