Billing
/v1/billing/subscriptionsCreate a Business's SaaS subscription
curl -X POST https://api.tbbnetwork.com/v1/billing/subscriptions \
-H "Authorization: Bearer <session access token>" \
-H "Idempotency-Key: 5f2f...b91" \
-H "Content-Type: application/json" \
-d '{
"businessId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"billingEmail": "you@example.com",
"tier": "SANDBOX"
}'Parameters
Request body
| Field | Type | Required |
|---|---|---|
| businessId | string (uuid) | yes |
| billingEmail | string (email) | — |
| tier | SANDBOX | STARTER | GROWTH | ENTERPRISE | PAY_AS_YOU_GO | yes |
Response (201)
| Field | Type | Required |
|---|---|---|
| id | string (uuid) | — |
| businessId | string (uuid) | — |
| tier | SANDBOX | STARTER | GROWTH | ENTERPRISE | PAY_AS_YOU_GO | — |
| stripeSubscriptionId | stringnull | — |
| stripeCustomerId | stringnull | — |
| status | string | — |
| currentPeriodStart | string,null (date-time) | — |
| currentPeriodEnd | string,null (date-time) | — |
| stripePaymentMethodId | stringnull | — |
| paymentMethodSetupAt | string,null (date-time) | — |
| lastWeeklyChargeAt | string,null (date-time) | — |
| waivedUntil | string,null (date-time) | — |
| waivedReason | stringnull | — |
{
"id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"businessId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"tier": "SANDBOX",
"stripeSubscriptionId": null,
"stripeCustomerId": null,
"status": "status",
"currentPeriodStart": "2026-07-01T12:00:00Z",
"currentPeriodEnd": "2026-07-01T12:00:00Z",
"stripePaymentMethodId": null,
"paymentMethodSetupAt": "2026-07-01T12:00:00Z",
"lastWeeklyChargeAt": "2026-07-01T12:00:00Z",
"waivedUntil": "2026-07-01T12:00:00Z",
"waivedReason": null
}Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/billing/subscriptions/{businessId}Get a Business's current active SaaS subscription
curl -X GET https://api.tbbnetwork.com/v1/billing/subscriptions/{businessId} \
-H "Authorization: Bearer <session access token>" \Parameters
| businessId | path | required |
Response (200)
| Field | Type | Required |
|---|---|---|
| id | string (uuid) | — |
| businessId | string (uuid) | — |
| tier | SANDBOX | STARTER | GROWTH | ENTERPRISE | PAY_AS_YOU_GO | — |
| stripeSubscriptionId | stringnull | — |
| stripeCustomerId | stringnull | — |
| status | string | — |
| currentPeriodStart | string,null (date-time) | — |
| currentPeriodEnd | string,null (date-time) | — |
| stripePaymentMethodId | stringnull | — |
| paymentMethodSetupAt | string,null (date-time) | — |
| lastWeeklyChargeAt | string,null (date-time) | — |
| waivedUntil | string,null (date-time) | — |
| waivedReason | stringnull | — |
{
"id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"businessId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"tier": "SANDBOX",
"stripeSubscriptionId": null,
"stripeCustomerId": null,
"status": "status",
"currentPeriodStart": "2026-07-01T12:00:00Z",
"currentPeriodEnd": "2026-07-01T12:00:00Z",
"stripePaymentMethodId": null,
"paymentMethodSetupAt": "2026-07-01T12:00:00Z",
"lastWeeklyChargeAt": "2026-07-01T12:00:00Z",
"waivedUntil": "2026-07-01T12:00:00Z",
"waivedReason": null
}Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/billing/subscriptions/{businessId}/change-tierChange a Business's subscription tier
curl -X POST https://api.tbbnetwork.com/v1/billing/subscriptions/{businessId}/change-tier \
-H "Authorization: Bearer <session access token>" \
-H "Idempotency-Key: 5f2f...b91" \
-H "Content-Type: application/json" \
-d '{
"tier": "SANDBOX"
}'Parameters
| businessId | path | required |
Request body
| Field | Type | Required |
|---|---|---|
| tier | SANDBOX | STARTER | GROWTH | ENTERPRISE | PAY_AS_YOU_GO | yes |
Response (201)
| Field | Type | Required |
|---|---|---|
| id | string (uuid) | — |
| businessId | string (uuid) | — |
| tier | SANDBOX | STARTER | GROWTH | ENTERPRISE | PAY_AS_YOU_GO | — |
| stripeSubscriptionId | stringnull | — |
| stripeCustomerId | stringnull | — |
| status | string | — |
| currentPeriodStart | string,null (date-time) | — |
| currentPeriodEnd | string,null (date-time) | — |
| stripePaymentMethodId | stringnull | — |
| paymentMethodSetupAt | string,null (date-time) | — |
| lastWeeklyChargeAt | string,null (date-time) | — |
| waivedUntil | string,null (date-time) | — |
| waivedReason | stringnull | — |
{
"id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"businessId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"tier": "SANDBOX",
"stripeSubscriptionId": null,
"stripeCustomerId": null,
"status": "status",
"currentPeriodStart": "2026-07-01T12:00:00Z",
"currentPeriodEnd": "2026-07-01T12:00:00Z",
"stripePaymentMethodId": null,
"paymentMethodSetupAt": "2026-07-01T12:00:00Z",
"lastWeeklyChargeAt": "2026-07-01T12:00:00Z",
"waivedUntil": "2026-07-01T12:00:00Z",
"waivedReason": null
}Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/billing/subscriptions/{businessId}/cancelCancel a Business's subscription
curl -X POST https://api.tbbnetwork.com/v1/billing/subscriptions/{businessId}/cancel \
-H "Authorization: Bearer <session access token>" \
-H "Idempotency-Key: 5f2f...b91" \Parameters
| businessId | path | required |
Response (201)
| Field | Type | Required |
|---|---|---|
| id | string (uuid) | — |
| businessId | string (uuid) | — |
| tier | SANDBOX | STARTER | GROWTH | ENTERPRISE | PAY_AS_YOU_GO | — |
| stripeSubscriptionId | stringnull | — |
| stripeCustomerId | stringnull | — |
| status | string | — |
| currentPeriodStart | string,null (date-time) | — |
| currentPeriodEnd | string,null (date-time) | — |
| stripePaymentMethodId | stringnull | — |
| paymentMethodSetupAt | string,null (date-time) | — |
| lastWeeklyChargeAt | string,null (date-time) | — |
| waivedUntil | string,null (date-time) | — |
| waivedReason | stringnull | — |
{
"id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"businessId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"tier": "SANDBOX",
"stripeSubscriptionId": null,
"stripeCustomerId": null,
"status": "status",
"currentPeriodStart": "2026-07-01T12:00:00Z",
"currentPeriodEnd": "2026-07-01T12:00:00Z",
"stripePaymentMethodId": null,
"paymentMethodSetupAt": "2026-07-01T12:00:00Z",
"lastWeeklyChargeAt": "2026-07-01T12:00:00Z",
"waivedUntil": "2026-07-01T12:00:00Z",
"waivedReason": null
}Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/billing/subscriptions/{businessId}/confirm-payment-methodPay-As-You-Go card capture, step 2 — save the payment method Stripe.js resolved the SetupIntent to
curl -X POST https://api.tbbnetwork.com/v1/billing/subscriptions/{businessId}/confirm-payment-method \
-H "Authorization: Bearer <session access token>" \
-H "Idempotency-Key: 5f2f...b91" \
-H "Content-Type: application/json" \
-d '{
"stripePaymentMethodId": "stripePaymentMethodId"
}'Parameters
| businessId | path | required |
Request body
| Field | Type | Required |
|---|---|---|
| stripePaymentMethodId | string | yes |
Response (201)
| Field | Type | Required |
|---|---|---|
| id | string (uuid) | — |
| businessId | string (uuid) | — |
| tier | SANDBOX | STARTER | GROWTH | ENTERPRISE | PAY_AS_YOU_GO | — |
| stripeSubscriptionId | stringnull | — |
| stripeCustomerId | stringnull | — |
| status | string | — |
| currentPeriodStart | string,null (date-time) | — |
| currentPeriodEnd | string,null (date-time) | — |
| stripePaymentMethodId | stringnull | — |
| paymentMethodSetupAt | string,null (date-time) | — |
| lastWeeklyChargeAt | string,null (date-time) | — |
| waivedUntil | string,null (date-time) | — |
| waivedReason | stringnull | — |
{
"id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"businessId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"tier": "SANDBOX",
"stripeSubscriptionId": null,
"stripeCustomerId": null,
"status": "status",
"currentPeriodStart": "2026-07-01T12:00:00Z",
"currentPeriodEnd": "2026-07-01T12:00:00Z",
"stripePaymentMethodId": null,
"paymentMethodSetupAt": "2026-07-01T12:00:00Z",
"lastWeeklyChargeAt": "2026-07-01T12:00:00Z",
"waivedUntil": "2026-07-01T12:00:00Z",
"waivedReason": null
}Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/billing/pricing/{businessId}What TBBN charges this Business, in its billing currency
curl -X GET https://api.tbbnetwork.com/v1/billing/pricing/{businessId} \
-H "Authorization: Bearer <session access token>" \Parameters
| businessId | path | required |
Response (200)
| Field | Type | Required |
|---|---|---|
| country | stringnull | — |
| currency | string | — |
| local | boolean | — |
| currencyFixed | boolean | — |
| prices | object | — |
{
"country": null,
"currency": "USD",
"local": false,
"currencyFixed": false,
"prices": null
}Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/billing/merchant/summaryYour Merchant's plan — its Business's — and this period's usage: for each service, your own count (rawCount), your Business's total across its Merchants (businessCount, what the allowance is measured against) and the plan's allowance (included; null means unlimited). Works with an API key or a merchant dashboard session whose role can see billing or analytics. Without a paid plan, the tier is SANDBOX and the period is the calendar month.
curl -X GET https://api.tbbnetwork.com/v1/billing/merchant/summary \
-H "Authorization: Bearer sk_sandbox_..." \Response (200)
| Field | Type | Required |
|---|---|---|
| merchantId | string (uuid) | — |
| businessId | string,null (uuid) | — |
| businessName | stringnull | — |
| currency | string | — |
| tier | SANDBOX | STARTER | GROWTH | PAY_AS_YOU_GO | ENTERPRISE | — |
| billingInterval | MONTH | YEAR | | — |
| status | stringnull | — |
| basePriceUsd | numbernull | — |
| windowStart | string (date-time) | — |
| windowEnd | string (date-time) | — |
| lineItems | object[] | — |
{
"merchantId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"businessId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"businessName": null,
"currency": "USD",
"tier": "SANDBOX",
"billingInterval": "MONTH",
"status": null,
"basePriceUsd": null,
"windowStart": "2026-07-01T12:00:00Z",
"windowEnd": "2026-07-01T12:00:00Z",
"lineItems": [
{
"eventType": "eventType",
"rawCount": 1,
"businessCount": 1,
"included": null,
"overageCost": 1
}
]
}Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/billing/usage/{businessId}A Business's current (or specified) billing-period metered usage, aggregated across every Merchant linked to it, including the cross-merchant multiplier breakdown and priced overage per event type. See the Pricing reference.
curl -X GET https://api.tbbnetwork.com/v1/billing/usage/{businessId} \
-H "Authorization: Bearer <session access token>" \Parameters
| businessId | path | required |
| billingPeriodRef | query | optional |
Response (200)
| Field | Type | Required |
|---|---|---|
| businessId | string (uuid) | — |
| merchantIds | string[] | — |
| tier | SANDBOX | STARTER | GROWTH | ENTERPRISE | PAY_AS_YOU_GO | — |
| billingPeriodRef | string | — |
| basePriceUsd | numbernull | — |
| lineItems | object[] | — |
| totalOverageUsd | number | — |
| waived | boolean | — |
| waivedUntil | string,null (date-time) | — |
| amountDueUsd | number | — |
{
"businessId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"merchantIds": [
"a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
],
"tier": "SANDBOX",
"billingPeriodRef": "billingPeriodRef",
"basePriceUsd": null,
"lineItems": [
{
"eventType": "LISTING_SYNC",
"rawCount": 1,
"meteredUnits": 1,
"included": null,
"overageUnits": 1,
"overageCost": 1
}
],
"totalOverageUsd": 1,
"waived": false,
"waivedUntil": "2026-07-01T12:00:00Z",
"amountDueUsd": 1
}Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/billing/invoices/{businessId}A Business's invoices
curl -X GET https://api.tbbnetwork.com/v1/billing/invoices/{businessId} \
-H "Authorization: Bearer <session access token>" \Parameters
| businessId | path | required |
| status | query | optional |
| kind | query | optional |
| from | query | optional |
| to | query | optional |
| cursor | query | optional |
| limit | query | optional |
Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}/v1/billing/statements/{businessId}Consolidated Business billing statement — merchantPlan (owed) and spaceEarnings (already paid out, net of commission) as two separate sections, never merged into one number.
curl -X GET https://api.tbbnetwork.com/v1/billing/statements/{businessId} \
-H "Authorization: Bearer <session access token>" \Parameters
| businessId | path | required |
| billingPeriodRef | query | optional |
Response (200)
| Field | Type | Required |
|---|---|---|
| businessId | string (uuid) | — |
| merchantPlan | UsageSummary | — |
| spaceEarnings | object | — |
{
"businessId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"merchantPlan": {
"businessId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"merchantIds": [
"a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
],
"tier": "SANDBOX",
"billingPeriodRef": "billingPeriodRef",
"basePriceUsd": null,
"lineItems": [
{
"eventType": "LISTING_SYNC",
"rawCount": 1,
"meteredUnits": 1,
"included": null,
"overageUnits": 1,
"overageCost": 1
}
],
"totalOverageUsd": 1,
"waived": false,
"waivedUntil": "2026-07-01T12:00:00Z",
"amountDueUsd": 1
},
"spaceEarnings": {
"currency": "USD",
"totalPaidOut": 1,
"byBranch": [
{
"branchId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"branchName": "branchName",
"totalPaidOut": 1,
"payoutCount": 1
}
]
}
}Possible errors
Any other failure (validation, auth, rate limiting, a resource that doesn't exist) returns this same envelope with a non-2xx status — error.code is stable and safe to branch on; error.requestId is worth logging and including in a support request.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A human-readable description of what went wrong.",
"requestId": "req_01hxyz..."
}
}