Usage-based billing quickstart

View as Markdown

Learn how to meter usage events and generate an invoice based on consumption using the Tabs API. In this guide you’ll create an event type, attach a usage-based billing term to an existing contract, send usage events, and verify the resulting invoice.

Get your API key

You can create an API key from the app. All requests require your key in the Authorization header.

Before you begin

This guide assumes you already have a customer and a processed contract in Tabs. If you don’t, follow the first two steps of the Invoice a Customer Quickstart to create them.

You’ll need:

  • A Customer ID (for example, cust_abc123)
  • A Contract ID (for example, cont_xyz789)

Step 1: Create an event type

An event type defines the unit of consumption that Tabs meters. Event types are global to your Tabs account—create one per distinct metric you want to track (for example, API calls, active users, or GB transferred).

Create an event type using the POST /v3/events/types endpoint:

$curl -X POST \
> https://integrators.prod.api.tabsplatform.com/v3/events/types \
> -H "Authorization: YOUR_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "name": "API Calls"
> }'

Tabs returns a response like:

1{
2 "id": "evt_type_abc123",
3 "name": "API Calls"
4}

Save the returned id—you’ll use it in the next steps.

You can also create and manage event types in the Tabs app on the usage events settings page.

Step 2: Create a usage-based billing term

A billing term defines the billing side of a contract — what you charge, how much it costs, and how frequently. For usage-based billing, set billingType to UNIT, quantity to 0, and link the billing term to the event type you created in Step 1 using the eventTypeId field.

Create the billing term on the contract by calling the POST /v3/contracts/{id}/billing-terms endpoint:

$curl -X POST \
> https://integrators.prod.api.tabsplatform.com/v3/contracts/cont_xyz789/billing-terms \
> -H "Authorization: YOUR_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "name": "API Calls — Monthly Usage",
> "description": "Metered API call charges, billed monthly in arrears",
> "billingStartDate": "2025-02-01",
> "isRecurring": true,
> "interval": "MONTH",
> "intervalFrequency": 1,
> "duration": 11,
> "invoiceDateStrategy": "ARREARS",
> "netPaymentTerms": 30,
> "quantity": 0,
> "billingType": "UNIT",
> "pricingType": "SIMPLE",
> "eventTypeId": "evt_type_abc123",
> "itemId": "item_abc123",
> "pricing": [
> {
> "tier": 1,
> "amount": 0.01,
> "amountType": "PER_ITEM",
> "tierMinimum": 0
> }
> ]
> }'

When you omit billingTermGroupId, Tabs automatically creates a billing term group and a corresponding billing term with a 1:1 mapping.

Tabs returns a response like:

1{
2 "payload": {
3 "name": "API Calls — Monthly Usage",
4 "description": "Metered API call charges, billed monthly in arrears",
5 "billingStartDate": "2025-02-01",
6 "isRecurring": true,
7 "interval": "MONTH",
8 "intervalFrequency": 1,
9 "duration": 11,
10 "netPaymentTerms": 30,
11 "quantity": 0,
12 "billingType": "UNIT",
13 "pricingType": "SIMPLE",
14 "eventTypeId": "evt_type_abc123",
15 "itemId": "item_abc123",
16 "billingTermGroupId": "btg_auto_123",
17 "id": "bt_def456",
18 "contractId": "cont_xyz789",
19 "billingEndDate": "2025-12-31",
20 "createdAt": "2025-01-15T10:00:00Z"
21 },
22 "success": true,
23 "message": "Billing term created",
24 "error": null
25}

The invoiceDateStrategy field controls when Tabs generates the invoice relative to the service period. For usage-based billing, ARREARS is the most common choice because Tabs needs to collect all usage events before generating the invoice. For pay-as-you-go and non-prepaid commitment billing terms, Tabs generates draft invoices for each billing period. Because this billing term uses the ARREARS strategy, the invoice for February usage has an issueDate of 2025-03-01 and a dueDate 30 days later (2025-03-31), based on the netPaymentTerms you specified. LAST_OF_PERIOD is also a valid choice for usage-based billing if the invoice date were to fall within the same month as usage, which is a common pattern for revenue recognition.

For tiered pricing (for example, volume discounts), set pricingType to TIERED and provide multiple entries in the pricing array with ascending tierMinimum values.

Step 3: Send usage events

With the event type and billing term in place, send usage events as they occur. Each event represents a single unit of consumption tied to a customer.

Submit an event using the POST /v1/events endpoint:

$curl -X POST \
> https://usage-events.prod.api.tabsplatform.com/v1/events \
> -H "Authorization: YOUR_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "customerId": "cust_abc123",
> "eventTypeId": "evt_type_abc123",
> "datetime": "2025-02-15T14:30:00Z",
> "value": 1,
> "idempotencyKey": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
> }'

Tabs returns a response like:

1{
2 "success": true,
3 "message": "Event created successfully",
4 "data": {
5 "events": {
6 "customerId": "cust_abc123",
7 "eventTypeId": "evt_type_abc123",
8 "datetime": "2025-02-15T14:30:00Z",
9 "idempotencyKey": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
10 "value": 1
11 }
12 }
13}

Each event requires a unique idempotencyKey. Tabs deduplicates events using the (manufacturerId, idempotencyKey) pair for 45 days.

Usage events can only be billed if a billing term exists with a service period that encompasses the event’s datetime. Events outside of any billing term’s service period are ingested but do not appear on an invoice and should be deleted.

Step 4: Verify the invoice

Tabs recalculates usage-based invoices every hour. After sending events, wait for the next hourly recalculation, then fetch the invoice to confirm the usage is reflected.

Use the Customer ID to look up invoices with the GET /v3/invoices endpoint:

$curl "https://integrators.prod.api.tabsplatform.com/v3/invoices?filter=customerId:eq:cust_abc123&page=1&limit=50" \
> -H "Authorization: YOUR_API_KEY"

Tabs returns a response like:

1{
2 "payload": {
3 "data": [
4 {
5 "id": "inv_ghi012",
6 "customerId": "cust_abc123",
7 "status": "DRAFT",
8 "issueDate": "2025-03-01",
9 "dueDate": "2025-03-31",
10 "total": 150.00,
11 "balanceRemaining": 150.00,
12 "lineItems": [
13 {
14 "id": "li_001",
15 "name": "API Calls — Monthly Usage",
16 "description": "Metered API call charges, billed monthly",
17 "quantity": 15000,
18 "subtotal": 150.00,
19 "discountTotal": 0,
20 "total": 150.00,
21 "salesTaxRate": "0",
22 "item": {
23 "id": "item_abc123",
24 "name": "API Calls",
25 "externalIds": []
26 }
27 }
28 ]
29 }
30 ],
31 "limit": 50,
32 "totalItems": 1,
33 "currentPage": 1
34 },
35 "success": true,
36 "message": "string",
37 "error": null
38}

The invoice reflects 15,000 API calls at $0.01 each for the February billing period. When you’re ready to send the invoice to the customer, transition it from DRAFT to SENT:

$curl -X POST \
> "https://integrators.prod.api.tabsplatform.com/v3/customers/cust_abc123/invoices/inv_ghi012/actions" \
> -H "Authorization: YOUR_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "action": "SEND",
> "sendToErp": true,
> "sendToCustomer": true
> }'

Tabs sends the invoice to the customer for payment.

Setting sendToErp to true also pushes the invoice to your connected ERP.

Next steps