Checkout
Create Stripe Checkout sessions through BillStack
Create Checkout Session
POST /api/billstack/teams/{teamId}/projects/{projectId}/checkoutCreates a Stripe Checkout session for a BillStack customer. The customer is redirected to Stripe's hosted checkout page to complete payment.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
customerId | string | Yes | BillStack customer ID (pc_...) |
priceId | string | Yes | BillStack price ID (pri_...) |
quantity | number | No | Quantity (default: 1) |
successUrl | string | Yes | URL to redirect to after successful payment |
cancelUrl | string | Yes | URL to redirect to if checkout is canceled |
mode | string | No | subscription (default) or payment |
trialDays | number | No | Number of free trial days |
metadata | object | No | Arbitrary key-value pairs passed to Stripe |
Example:
curl -X POST "https://your-billstack.com/.../checkout" \
-H "Authorization: Bearer bs_..." \
-H "Content-Type: application/json" \
-d '{
"customerId": "pc_a1b2c3d4",
"priceId": "pri_i9j0k1l2",
"quantity": 1,
"successUrl": "https://myapp.com/success?session_id={CHECKOUT_SESSION_ID}",
"cancelUrl": "https://myapp.com/pricing",
"mode": "subscription",
"trialDays": 14
}'Response (201):
{
"sessionId": "cs_xxx",
"url": "https://checkout.stripe.com/c/pay/cs_xxx..."
}Redirect the customer to url to complete payment.
Auth: Write access (session or API key with subscriptions:write).
How It Works
- BillStack resolves the
customerIdandpriceIdto their Stripe equivalents - Creates a Stripe Checkout Session with:
- The customer's Stripe ID
- The price's Stripe ID
- Your success/cancel URLs
- Optional trial period
- BillStack metadata for project routing
- Returns the session ID and checkout URL
- After the customer completes checkout, Stripe sends a
checkout.session.completedwebhook - BillStack processes the webhook and creates the subscription record
Integration Pattern
// Server-side: create the checkout session
export async function POST(req: Request) {
const { priceId } = await req.json();
const user = await getAuthenticatedUser(req);
const response = await fetch(`${BILLSTACK_URL}/.../checkout`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
customerId: user.billstackCustomerId,
priceId,
successUrl: `${APP_URL}/dashboard?checkout=success`,
cancelUrl: `${APP_URL}/pricing`,
}),
});
const { url } = await response.json();
return Response.json({ url });
}// Client-side: redirect to checkout
async function handleSubscribe(priceId: string) {
const res = await fetch('/api/subscribe', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ priceId }),
});
const { url } = await res.json();
window.location.href = url;
}Notes
- Use BillStack IDs (
pc_,pri_), not Stripe IDs — BillStack resolves them internally - The
{CHECKOUT_SESSION_ID}template variable insuccessUrlis replaced by Stripe with the actual session ID - For one-time payments, set
modetopayment - Trial periods only apply to
subscriptionmode