Develop with the Tabs API

View as Markdown

The Tabs API is a RESTful, JSON-based interface for managing your billing lifecycle programmatically. Use it to push Customers, Contracts, Billing Terms, and usage data into Tabs, and to pull Invoices, Payments, and reports back out. This page covers the mechanics of working with the API—authentication, request format, error handling, pagination, and rate limits.

Base URL

All production API requests use the following base URL:

https://integrators.prod.api.tabsplatform.com

The base URL above points to the Tabs production environment. To request access to a sandbox environment for development and testing, contact your Tabs Implementation Manager.

Authentication

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

Authorization: YOUR_API_KEY

API keys are scoped to a single Tabs entity. The key identifies which account the request operates on, and Tabs enforces access controls accordingly.

Keys can be revoked at any time. A revoked key returns 401 Unauthorized.

Request format

The API accepts and returns JSON. Include the Content-Type header on all requests with a body:

Content-Type: application/json

Here is a minimal example that creates a customer:

$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",
> "primaryBillingContactName": "Jordan Lee",
> "primaryBillingContactEmail": "jordan.lee@acme.com"
> }'

Response format

Every response is wrapped in a standard envelope with three fields:

1{
2 "payload": { ... },
3 "success": true,
4 "message": "Operation successful"
5}
FieldTypeDescription
payloadObject or ArrayThe requested data. For list endpoints, this contains pagination metadata and a data array.
successBooleanWhether the request succeeded.
messageStringA human-readable summary of the result.

Errors

When a request fails, the response includes an error object with a status code, message, and optional details:

1{
2 "payload": null,
3 "success": false,
4 "message": "Validation failed",
5 "error": {
6 "code": 400,
7 "message": "Validation failed",
8 "details": {
9 "name": ["name must be a string"]
10 }
11 }
12}

Common status codes

StatusMeaning
200 OKRequest succeeded
201 CreatedResource created successfully
400 Bad RequestInvalid JSON, missing required fields, or a validation rule was violated
401 UnauthorizedMissing, invalid, or revoked API key
404 Not FoundThe requested resource does not exist
429 Too Many RequestsRate limit exceeded. Back off and retry
503 Service UnavailableTransient failure

Pagination

List endpoints support offset-based pagination with page and limit query parameters:

GET /v3/customers?page=2&limit=25

The response wraps the results with pagination metadata:

1{
2 "payload": {
3 "currentPage": 2,
4 "limit": 25,
5 "totalItems": 142,
6 "data": [ ... ]
7 },
8 "success": true,
9 "message": "Operation successful"
10}
ParameterDefaultDescription
page1The page number (1-indexed).
limit50The maximum number of items per page.

Filtering

List endpoints support filtering with the filter query parameter. Each filter uses the format property:rule:value:

GET /v3/customers?filter=name:like:acme

To apply more than one filter, separate them with commas. Filters combine with AND—a customer must match every condition to be returned:

GET /v3/customers?filter=name:like:acme,lastUpdatedAt:gte:2026-01-01

The response is a standard paginated list containing only the customers that match your filters:

1{
2 "payload": {
3 "currentPage": 1,
4 "limit": 50,
5 "totalItems": 1,
6 "data": [
7 {
8 "id": "123e4567-e89b-12d3-a456-426614174000",
9 "name": "Acme Inc.",
10 "primaryBillingContactEmail": "john.doe@example.com",
11 "defaultCurrency": "USD",
12 "externalIds": [{ "type": "NETSUITE", "id": "CUST-1042" }],
13 "lastUpdatedAt": "2026-02-14T09:30:00.000Z"
14 }
15 ]
16 },
17 "success": true,
18 "message": "Operation successful"
19}

Supported rules:

RuleMeaning
eqEquals
neqDoes not equal
gtGreater than
gteGreater than or equal to
ltLess than
lteLess than or equal to
likeContains
nlikeDoes not contain (case-insensitive)
inMatches any
ninNone of a pipe-separated list
isnullValue is null (no value: name:isnull)
isnotnullValue is not null

Filterable fields on GET /v3/customers:

FieldDescription
nameThe customer’s name.
externalIds.externalIdAn external system identifier mapped to the customer.
lastUpdatedAtWhen the customer was last updated. Use date format YYYY-MM-DD.

Wrap values containing commas or spaces in double quotes (filter=name:eq:"Acme, Inc."). For in and nin, separate values with a pipe (filter=externalIds.externalId:in:cust_1|cust_2).

Rate limiting

The API generally enforces a rate limit of 10 requests per second per merchant. When the limit is exceeded, the API returns 429 Too Many Requests. Pause and retry.

The usage events endpoint (POST /v1/events) has a separate, higher limit of 10,000 requests per minute to support high-throughput ingestion workloads.

Next steps