Checkout

Accept a payment for an amount you specify, server-to-server — Blitz handles the buyer-facing payment flow, then notifies you by webhook once it completes.

Create a checkout

POST/api/commerce/integration/checkout

Requires an API key with the checkout:write scope.

create-checkout.sh
curl -X POST https://api.nest.useblitz.co/api/commerce/integration/checkout \
  -H "Authorization: Bearer bk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amountMinorUnits": "2500",
    "currency": "USD",
    "provider": "STRIPE",
    "returnUrl": "https://yourstore.com/orders/123/confirmation",
    "checkoutMode": "REDIRECT",
    "externalOrderRef": "your-internal-order-id",
    "idempotencyKey": "unique-per-order"
  }'

Response (shown here as just the data portion — see Responses & Errors for the full envelope every endpoint wraps this in):

response.json
{
  "orderId": "pay_...",
  "provider": "STRIPE",
  "checkoutMode": "REDIRECT",
  "redirectUrl": "https://checkout.stripe.com/..."
}

Redirect vs. embedded

checkoutMode: "REDIRECT" (the default) returns a redirectUrl — send the buyer there to complete payment; they land back on your returnUrl with ?order={orderId} appended. checkoutMode: "EMBEDDED" (Stripe only — rejected for PayPal) instead returns a clientSecret for Stripe Elements, and no redirect happens unless the payment method itself requires one (e.g. 3DS).

Embedding the hosted checkout page

This is a separate option from checkoutModeabove, and doesn't require the integration API at all. If you have a Blitz-hosted checkout link (e.g. a product checkout link from your merchant dashboard, of the form https://useblitz.co/checkout/{slug}), you can drop that page directly into an <iframe> by appending ?embed=trueto the URL. The embedded version renders without Blitz's page chrome and is served with frame-ancestors *, so it can be framed from any origin. Without ?embed=true, the same page refuses to be framed at all.

Use this when you want Blitz's full hosted checkout UI inline on your page with no integration work. Use checkoutMode: "EMBEDDED" instead when you want to build your own checkout UI around Stripe Elements.

Fields

  • amountMinorUnits — positive integer string, in minor units (cents for USD).
  • provider — STRIPE or PAYPAL.
  • returnUrl — required, HTTPS. Your own order-confirmation page — reaching it is not itself proof of payment; check real status via the status endpoint below or a webhook.
  • idempotencyKey — strongly recommended. Retrying with the same key returns the existing order instead of creating a duplicate.
  • subscriptionIntervalUnit — optional, "MONTHLY" or "YEARLY". Opts this checkout into recurring billing — see Recurring charges below.

Recurring charges (subscriptions)

Add subscriptionIntervalUnit to the same create call above to opt the order into recurring billing — Stripe only, a request with provider: "PAYPAL" is rejected with a 422. There's no separate "create subscription" call: the first checkout is both the purchase and the subscription setup, and it saves the card for off-session renewal charges.

create-checkout-subscription.sh
curl -X POST https://api.nest.useblitz.co/api/commerce/integration/checkout \
  -H "Authorization: Bearer bk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amountMinorUnits": "2500",
    "currency": "USD",
    "provider": "STRIPE",
    "returnUrl": "https://yourstore.com/orders/123/confirmation",
    "idempotencyKey": "unique-per-order",
    "subscriptionIntervalUnit": "MONTHLY"
  }'
  • We bill the saved card automatically on each renewal date — no action needed from you to trigger it.
  • Every successful charge (the founding order and every renewal) fires the same checkout.completed webhook. A renewal delivery is distinguishable from the founding order by carrying a subscriptionIdfield — the founding order's payload doesn't have one:
renewal-webhook-payload.json
{
  "payoutId": "pay_...",
  "amount": "2500",
  "currency": "USD",
  "provider": "STRIPE",
  "subscriptionId": "cks_..."
}
  • After 3 consecutive declines the subscription is automatically cancelled — there's no paused/past-due state, and no dunning emails are sent to the buyer.
  • There's no proration or plan-change support: cancelling and creating a fresh checkout is the only way to move a buyer to a different interval or amount.

Buyer self-service — unauthenticated, no API key. Possession of the subscriptionId is the credential, same trust model as the order-status endpoint below. cancel is idempotent — cancelling an already-cancelled subscription just returns its current state:

subscription-self-service.txt
GET  https://api.nest.useblitz.co/api/commerce/checkout/subscriptions/:subscriptionId
POST https://api.nest.useblitz.co/api/commerce/checkout/subscriptions/:subscriptionId/cancel
subscriptionIntervalUnit is only valid with provider: "STRIPE" — PayPal has no saved-card off-session charging in this integration, so a PayPal request with a subscription opt-in is rejected outright (422).

Check order status

GET/api/commerce/checkout/orders/:orderId/status

Public — no API key required. Poll this from your returnUrl, or use a webhook instead.

Returns { status, amountMinorUnits, currency, subscriptionId }. status reaches PAIDonce the payment is confirmed — that's the only signal that should trigger fulfillment on your side, not the redirect itself. subscriptionIdis set once a subscription opt-in on this order has been fulfilled — use it to show the buyer a "manage your subscription" link on your confirmation page.