> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.tabs.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.tabs.com/_mcp/server.

# Create usage-based billing

This guide walks through implementing usage-based billing using the Tabs API.
Usage-based billing meters consumption events and generates Invoices based on actual usage.
You'll create an event type, set up a customer and contract, attach a usage-based billing term, mark the contract as processed, send usage events, and then send the invoice.

## Step 1: Create an event type

An event type defines the unit of consumption that Tabs meters. Event types are global to your merchant account—create one per distinct metric you want to track.

```bash
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"
  }'
```

Save the returned `id` as `{eventTypeId}`.

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

## Step 2: Create the customer

A customer in Tabs represents the business you're billing. If the customer already exists in Tabs, skip to Step 4 and use their existing `id`.

```bash
curl -X POST \
  https://integrators.prod.api.tabsplatform.com/v3/customers \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp",
    "primaryBillingContactEmail": "billing@acme.com",
    "billingAddress": {
      "line1": "123 Main Street",
      "city": "San Francisco",
      "state": "CA",
      "postalCode": "94105",
      "country": "US"
    }
  }'
```

Save the `id` as `{customerId}`.

## Step 3: Create the contract

A Contract defines the billing arrangement with the customer and serves as the container for the billing terms you attach later. Every billing relationship in Tabs starts with a contract.

```bash
curl -X POST \
  https://integrators.prod.api.tabsplatform.com/v3/contracts \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp — Services Agreement 2025",
    "customerId": "{customerId}"
  }'
```

Tabs returns the created Contract object. Save the `id` as `{contractId}`.

### Upload the contract file

If you have the signed contract document, you can optionally upload it as a PDF after creating the Contract object:

```bash
curl -X POST \
  https://integrators.prod.api.tabsplatform.com/v3/contracts/{contractId}/file \
  -H "Authorization: YOUR_API_KEY" \
  -F "file=@/path/to/agreement.pdf"
```

## Step 4: Set up items

Items help Tabs route billing data to the right places in your accounting system and reporting dashboards.

### Look up an item

An item maps a billing term to an account in your ERP. Items are created in the Tabs app or synced from your ERP—they cannot be created via the API.

List your available items to find the one to use for this billing term:

```bash
curl https://integrators.prod.api.tabsplatform.com/v3/items \
  -H "Authorization: YOUR_API_KEY"
```

Save the `id` of the item you want to use as `{itemId}`.

## Step 5: Add a usage-based billing term

A billing term defines what you're charging, how much it costs, and when. For usage-based billing, set `billingType` to `UNIT` and associate the billing term with the event type you created in Step 1 using the `eventTypeId` field.

If you uploaded a contract file in Step 3, do not create billing terms manually. Instead, coordinate with your Implementation Manager to set up automated contract processing (ACP), which extracts billing details from the uploaded document and creates billing terms automatically.

Pass the `itemId` from Step 4 to link this billing term to your ERP.

The following example configures monthly billing at \$0.01 per API call, billed in arrears:

```bash
curl -X POST \
  https://integrators.prod.api.tabsplatform.com/v3/contracts/{contractId}/billing-terms \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "API Calls — Monthly Usage",
    "description": "Metered API call charges",
    "billingStartDate": "2025-01-01",
    "isRecurring": true,
    "interval": "MONTH",
    "intervalFrequency": 1,
    "duration": 12,
    "invoiceDateStrategy": "ARREARS",
    "netPaymentTerms": 30,
    "quantity": 0,
    "billingType": "UNIT",
    "pricingType": "SIMPLE",
    "eventTypeId": "{eventTypeId}",
    "itemId": "{itemId}",
    "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 the created billing term. Because this billing term uses the `ARREARS` strategy, Tabs generates the Invoice after the service period ends.

Use `ARREARS` for usage-based billing so Tabs collects all events before generating the Invoice. `LAST_OF_PERIOD` is also valid when the Invoice date is within the same month as usage, which is a common pattern for revenue recognition.

## Step 6: Mark the contract as processed

Marking a contract as processed tells Tabs to generate invoices for all of its billing terms and surface the billing and revenue data in the app.

```bash
curl -X POST \
  "https://integrators.prod.api.tabsplatform.com/v3/contracts/{contractId}/actions" \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "MARK_AS_PROCESSED"
  }'
```

Tabs generates a draft invoice for each billing term on the contract.

## Step 7: Create a commitment (optional)

If the customer has committed to a minimum spend or prepaid amount against their usage, create a commitment on the contract. Commitments are common in usage-based deals where the customer commits to a minimum spend in exchange for a discounted rate.

Retrieve the billing term IDs from the contract using `GET /v3/contracts/{contractId}/billing-terms`, then create the commitment:

```bash
curl -X POST \
  https://integrators.prod.api.tabsplatform.com/v3/commitments \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contractId": "{contractId}",
    "commitments": [
      {
        "commitmentValue": 10000,
        "commitmentUnitType": "DOLLARS",
        "prepaidEnabled": true,
        "prepaidValue": 10000,
        "billingTermIds": ["{billingTermId}"],
        "commitmentStartDate": "2025-01-01",
        "commitmentEndDate": "2025-12-31",
        "commitmentInterval": "QUARTERLY",
        "revenueRecognitionPattern": "recognize-as-consumed"
      }
    ]
  }'
```

If `prepaidEnabled` is `true`, Tabs generates a prepayment invoice for the committed amount. As the customer consumes usage, the prepaid balance draws down. If consumption exceeds the commitment, overage charges apply at the rates defined on the billing term.

## Step 8: Send usage events

With the contract processed, send usage events as they occur. Each event represents a single unit of consumption tied to a customer.

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

Each event requires a unique `idempotencyKey`. Tabs deduplicates events 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 any billing term's service period are ingested but do not appear on an invoice.

Tabs recalculates usage-based invoices every hour.

## Step 9: Send the invoice

Fetch the generated invoice to review it, then send it to the customer.

Fetch the invoice:

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

Send the invoice:

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

Tabs emails the invoice to the customer's billing contact and syncs it to your connected ERP.

Set `sendToCustomer` to `false` to record the invoice in Tabs without emailing it, or `sendToErp` to `false` to skip the ERP sync. At least one of the two must be `true`.

## Check async job status

Some Tabs operations complete asynchronously. When an operation returns a `jobId`, poll it to check completion:

```bash
curl "https://integrators.prod.api.tabsplatform.com/v3/jobs/{jobId}" \
  -H "Authorization: YOUR_API_KEY"
```

Poll until `status` is `SUCCESS` or `FAILURE`.

## Next steps

* [Collect payments](/collect-payments)
* [Set up tiered usage pricing](/bill-customers/custom)