Billing API v2
Billing API v2 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
| Environment | Base URL |
|---|---|
| Mainnet | https://api.stendly.com |
| Devnet | https://api-devnet.stendly.com |
Permissions
Use a v2 billing API key with these scopes for full website checkout examples:
billing:write,billing:read,payments:write,payments:read
Read-only dashboards and sync jobs can use billing:read.
Billing modes
| Mode | Meaning |
|---|---|
one_time | Single hosted checkout payment. |
balance_top_up | Prepaid credit or balance purchase. |
subscription | Recurring product access. Renewal payments are customer-confirmed unless you implement a balance-based flow. |
Overview
Get billing overview
GET /api/v2/billing/overview
Returns project-scoped billing objects for the merchant: projects, API keys, roles, products, prices, customers, checkout sessions, invoices, subscriptions, portal sessions, webhook deliveries, and usage summaries.
Projects
| Operation | Method | Path |
|---|---|---|
| List projects | GET | /api/v2/projects |
| Retrieve project | GET | /api/v2/projects/{projectId} |
| Create project | POST | /api/v2/projects |
| Update project | PATCH | /api/v2/projects/{projectId} |
| Delete project | DELETE | /api/v2/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
| Operation | Method | Path |
|---|---|---|
| List customers | GET | /api/v2/customers |
| Retrieve customer | GET | /api/v2/customers/{customerId} |
| Create customer | POST | /api/v2/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.
| Operation | Method | Path |
|---|---|---|
| List products | GET | /api/v2/products |
| Retrieve product | GET | /api/v2/products/{productId} |
| Create product | POST | /api/v2/products |
| Update product | PATCH | /api/v2/products/{productId} |
| List prices | GET | /api/v2/prices |
| Retrieve price | GET | /api/v2/prices/{priceId} |
| Create price | POST | /api/v2/prices |
| Update price | PATCH | /api/v2/prices/{priceId} |
Product request
{
"projectId": "project_uuid",
"name": "AI token pack",
"description": "Prepaid AI credits"
}
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 monthly",
"unitAmountCents": 2900,
"currency": "USD",
"billingMode": "subscription",
"recurringInterval": "month"
}
Checkout sessions
| Operation | Method | Path |
|---|---|---|
| List checkout sessions | GET | /api/v2/checkout-sessions |
| Retrieve checkout session | GET | /api/v2/checkout-sessions/{sessionId} |
| Create checkout session | POST | /api/v2/checkout-sessions |
{
"projectId": "project_uuid",
"priceId": "price_uuid",
"mode": "one_time",
"merchantReference": "order_1001",
"successUrl": "https://example.com/success",
"cancelUrl": "https://example.com/cancel"
}
You can also create a custom-amount checkout without priceId:
{
"projectId": "project_uuid",
"mode": "one_time",
"amountCents": 2500,
"currency": "USD",
"merchantReference": "invoice_1001"
}
Response includes checkoutUrl. Redirect the customer to that hosted URL.
Invoices
| Operation | Method | Path |
|---|---|---|
| List invoices | GET | /api/v2/invoices |
| Retrieve invoice | GET | /api/v2/invoices/{invoiceId} |
Invoices are billable records created by checkout and subscription renewal flows.
Subscriptions
| Operation | Method | Path |
|---|---|---|
| List subscriptions | GET | /api/v2/subscriptions |
| Retrieve subscription | GET | /api/v2/subscriptions/{subscriptionId} |
| Update subscription | PATCH | /api/v2/subscriptions/{subscriptionId} |
| Cancel subscription | POST | /api/v2/subscriptions/{subscriptionId}/cancel |
| Preview change | POST | /api/v2/subscriptions/{subscriptionId}/preview-change |
Cancel subscription
{
"atPeriodEnd": true
}
Usage
| Operation | Method | Path |
|---|---|---|
| List usage summaries | GET | /api/v2/usage |
| Record usage | POST | /api/v2/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
| Operation | Method | Path |
|---|---|---|
| Create portal session | POST | /api/v2/portal-sessions |
{
"projectId": "project_uuid",
"customerId": "customer_uuid",
"returnUrl": "https://example.com/account"
}
Webhook deliveries
| Operation | Method | Path |
|---|---|---|
| List deliveries | GET | /api/v2/webhook-deliveries |
| Retrieve delivery | GET | /api/v2/webhook-deliveries/{deliveryId} |
| Resend delivery | POST | /api/v2/webhook-deliveries/{deliveryId}/resend |
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 v2 event families:
checkout.session.*invoice.*subscription.*customer.balance_*payment_intent.*
Production handlers should branch on event type and object status before fulfilling access.