BillStack Docs

Checkout

Create Stripe Checkout sessions through BillStack

Create Checkout Session

POST /api/billstack/teams/{teamId}/projects/{projectId}/checkout

Creates a Stripe Checkout session for a BillStack customer. The customer is redirected to Stripe's hosted checkout page to complete payment.

Request Body:

FieldTypeRequiredDescription
customerIdstringYesBillStack customer ID (pc_...)
priceIdstringYesBillStack price ID (pri_...)
quantitynumberNoQuantity (default: 1)
successUrlstringYesURL to redirect to after successful payment
cancelUrlstringYesURL to redirect to if checkout is canceled
modestringNosubscription (default) or payment
trialDaysnumberNoNumber of free trial days
metadataobjectNoArbitrary 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

  1. BillStack resolves the customerId and priceId to their Stripe equivalents
  2. 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
  3. Returns the session ID and checkout URL
  4. After the customer completes checkout, Stripe sends a checkout.session.completed webhook
  5. 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 in successUrl is replaced by Stripe with the actual session ID
  • For one-time payments, set mode to payment
  • Trial periods only apply to subscription mode

On this page