Skip to main content

Billing API

Billing API is the current API for merchant checkout and billing. All endpoints use bearer API-key authentication.

Authorization: Bearer st_live_or_dev_key
Content-Type: application/json

For create requests, send an Idempotency-Key header. SDKs also accept an idempotency key in the request object and generate one when needed.

Idempotency-Key: checkout-order-1001

Servers

EnvironmentBase URL
Mainnethttps://api.stendly.com
Devnethttps://api-devnet.stendly.com

Billing modes

ModeWhat it meansTypical use
one_timeA single hosted payment request. Can use a catalog price or a custom amountCents.Online order, license purchase, setup fee.
balance_top_upPrepaid credit purchase that credits the customer balance ledger after payment.AI credits, account balance, metered usage prep.
subscriptionManaged renewal billing. Stendly creates renewal invoices; customers confirm each renewal payment unless you build a balance-based flow.SaaS plans, memberships, renewal billing.
  1. Create a project.
  2. For the simplest no-code or low-code sale, create a Payment Link from the dashboard or POST /api/payment-links/setup.
  3. For a custom one-time payment, create a checkout session with amountCents.
  4. For reusable catalog items, balance top-ups, or managed subscriptions, create a product and price.
  5. Redirect the customer to a Payment Link URL or to the returned checkout session checkoutUrl.
  6. Fulfill access after webhook confirmation.

Projects

Billing overview

GET /api/billing/overview

Returns projects, API keys, roles, products, prices, customers, checkouts, invoices, subscriptions, portal sessions, webhook deliveries, and usage summaries for the current merchant.

OperationMethodPath
List projectsGET/api/projects
Retrieve projectGET/api/projects/{projectId}
Create projectPOST/api/projects
Update projectPATCH/api/projects/{projectId}
Delete projectDELETE/api/projects/{projectId}

Create project

{
"name": "Production",
"environment": "live",
"payoutAddress": "E7g2wdh9Z7a5vZkpQmdRZaVJ5z9pK2P38a6GKxeJ2Hc8",
"monthlyVolumeLimitCents": 100000000,
"monthlyRequestLimit": 100000
}

monthlyVolumeLimitCents is stored in cents. For example, 100000000 means $1,000,000.00.

Customers

Customers are optional for one-time checkout. They are useful for subscriptions, invoices, usage, and customer portal sessions. Checkout can create a customer automatically from externalCustomerId, customerEmail, or customerName.

{
"projectId": "project_uuid",
"externalCustomerId": "telegram_123456",
"email": "customer@example.com",
"name": "Customer Name"
}

Catalog

Products define what you sell. Prices define how you charge. Catalog is optional for custom one-time payment requests, but required when Stendly needs product semantics such as balance credits or managed subscription renewals.

One-time price

{
"projectId": "project_uuid",
"productId": "product_uuid",
"name": "Online order",
"unitAmountCents": 4999,
"currency": "USD",
"billingMode": "one_time"
}

Balance top-up price

{
"projectId": "project_uuid",
"productId": "product_uuid",
"name": "10,000 AI credits",
"unitAmountCents": 1000,
"currency": "USD",
"billingMode": "balance_top_up",
"creditAmount": 10000
}

Subscription price

{
"projectId": "project_uuid",
"productId": "product_uuid",
"name": "Pro semiannual",
"unitAmountCents": 24900,
"currency": "USD",
"billingMode": "subscription",
"recurringInterval": "month",
"recurringIntervalCount": 6
}

recurringInterval must be day, week, month, or year. recurringIntervalCount defaults to 1; use 6 with month for semiannual billing.

Payment Links are reusable public checkout entry points for a fixed project and price. Opening a Payment Link does not create a checkout session, invoice, payment intent, customer, API key, or webhook. A checkout session is created only when the buyer confirms checkout.

OperationMethodPath
List payment linksGET/api/payment-links
Retrieve payment linkGET/api/payment-links/{paymentLinkId}
Create payment linkPOST/api/payment-links
One-step setupPOST/api/payment-links/setup
Update payment linkPATCH/api/payment-links/{paymentLinkId}
Delete inactive payment linkDELETE/api/payment-links/{paymentLinkId}

One-step setup

Use setup for onboarding. It creates a product, price, and reusable Payment Link atomically. It does not create a checkout session, invoice, payment intent, customer, API key, or webhook.

{
"projectId": "project_uuid",
"productName": "VPN Pro",
"billingMode": "subscription",
"unitAmountCents": 1000,
"currency": "USD",
"recurringInterval": "month",
"requireClientReferenceId": true,
"collectCustomerEmail": true
}

The response includes paymentLink.url, for example:

https://app.stendly.com/p/pl_example

You can append a buyer reference when linking from your app:

https://app.stendly.com/p/pl_example?client_reference_id=user_8472

client_reference_id is returned on checkout/webhook records as a reconciliation label. It is controlled by the browser URL and must not be treated as identity proof. Use backend-created checkout sessions with trusted externalCustomerId or merchantReference when entitlement security depends on verified server-side identity.

These endpoints do not require an API key.

OperationMethodPath
Read public linkGET/api/payment-links/{publicToken}
Start checkoutPOST/api/payment-links/{publicToken}/checkout

GET /api/payment-links/{publicToken} is read-only. POST /checkout accepts only clientReferenceId, customerEmail, customerName, and idempotencyKey; it cannot change project, price, amount, billing mode, payout, redirects, or scopes.

Checkout sessions

OperationMethodPath
List checkout sessionsGET/api/checkout-sessions
Retrieve checkout sessionGET/api/checkout-sessions/{sessionId}
Create checkout sessionPOST/api/checkout-sessions

Custom one-time checkout

Use this when your application already owns the cart, order, or entitlement model.

{
"projectId": "project_uuid",
"amountCents": 4999,
"mode": "one_time",
"merchantReference": "order_1001",
"successUrl": "https://example.com/success",
"cancelUrl": "https://example.com/cancel"
}

Catalog checkout

{
"projectId": "project_uuid",
"priceId": "price_uuid",
"mode": "one_time",
"merchantReference": "order_1001",
"successUrl": "https://example.com/success",
"cancelUrl": "https://example.com/cancel"
}

Balance top-up checkout

{
"projectId": "project_uuid",
"priceId": "price_uuid",
"mode": "balance_top_up",
"merchantReference": "topup_1001",
"successUrl": "https://example.com/success",
"cancelUrl": "https://example.com/cancel"
}

Subscription checkout

{
"projectId": "project_uuid",
"priceId": "price_uuid",
"mode": "subscription",
"externalCustomerId": "telegram_123456",
"customerEmail": "customer@example.com",
"customerName": "Website Customer",
"merchantReference": "sub_1001",
"successUrl": "https://example.com/success",
"cancelUrl": "https://example.com/cancel"
}

Response includes checkoutUrl. Redirect the customer to that hosted URL.

Invoices

Invoices are internal billable records created by checkout and subscription renewal flows. Most integrations create checkout sessions, then read invoice status and webhook events for reconciliation.

Subscriptions

OperationMethodPath
List subscriptionsGET/api/subscriptions
Retrieve subscriptionGET/api/subscriptions/{subscriptionId}
Update subscriptionPATCH/api/subscriptions/{subscriptionId}
Cancel subscriptionPOST/api/subscriptions/{subscriptionId}/cancel
Preview changePOST/api/subscriptions/{subscriptionId}/preview-change

Cancel subscription

{
"atPeriodEnd": true
}

Subscription renewal does not silently debit a non-custodial wallet. Stendly creates the next invoice and checkout session; the customer confirms payment, then webhooks tell your server to keep or update access.

Usage

Usage records are stored for metered billing and reporting. Use idempotency keys that identify one usage event or message.

{
"projectId": "project_uuid",
"metric": "tokens",
"quantity": 1200,
"customerId": "customer_uuid",
"subscriptionId": "subscription_uuid",
"idempotencyKey": "usage-message-123"
}

Customer portal sessions

{
"projectId": "project_uuid",
"customerId": "customer_uuid",
"returnUrl": "https://example.com/account"
}

Webhook deliveries

Use delivery logs to inspect failed webhooks and replay failed deliveries after fixing your endpoint.

Webhook events

Verify every webhook with X-Stendly-Signature.

Common billing event families:

  • checkout.session.*
  • invoice.*
  • subscription.*
  • customer.balance_*
  • payment_intent.*

Production handlers should branch on event type and object status before fulfilling access.