Usage Events API Migration Guide
Last updated: May 20, 2026
Moving to the new Usage Events API.
A different host, a different contract, a few new rules. Here's everything that changes, why it changes, and how to flip the switch without setting your billing on fire.
Migration overview
Change | Impact |
|---|---|
New base host | Update API endpoint |
Client-side idempotency | Generate and persist UUIDv4 keys |
Hourly invoice recalculation | No more instant invoice reflection |
New validation rules | Customer ↔ eventType checks enforced |
Quick facts
Item | Value |
|---|---|
Rate limit | 10,000 requests/minute |
Breaking changes | 4 major |
New host |
|
Typical migration effort | ~½ day |
Four things you need to know
These are the load-bearing changes. Everything else is implementation detail.
1 — New base URL
Usage events now live on a dedicated service.
Old
integrators.prod.api.tabsplatform.com
New
usage-events.prod.api.tabsplatform.com
Authentication and conventions stay the same — only the host changes.
2 — You now provide the idempotency key
Every POST request now requires a client-generated idempotencyKey.
Requirements
Must be a valid UUIDv4
Generated client-side
Persisted alongside the source event
Reused on retries
Tabs deduplicates on:
(manufacturerId, idempotencyKey)
for 45 days.
Why this matters
Retries are now truly safe — but only if your integration stores and reuses the same key.
3 — Invoices recalculate hourly
Usage events no longer appear on invoices instantly.
Old behavior
POST event → immediately visible on invoice
New behavior
POST event → reflected at next top-of-hour recalculation
Important
Do not build flows that:
Post an event
Immediately fetch the invoice
Expect the event to already appear
It will not.
4 — Customer ↔ event validation
The API now validates that a customer is actually billable for the submitted event type.
Invalid example
customerId = customer_a
eventTypeId = api_calls
…but customer_a is not configured for api_calls billing
Result
400 Bad Request
This is a guardrail — but optimistic event posting is no longer possible.
Endpoint mapping
The bulk endpoints are gone.
Because the new rate limit is extremely high, batching is no longer necessary.
Endpoint changes
Legacy | New |
|---|---|
Bulk Create Events | Create event |
Bulk Delete Events | Delete event |
Create Event | Create event |
List Events | Get events |
Delete Event | Delete event |
New pattern
POST /v1/events
(one request per event)
Why batching was removed
10,000 requests/minute
≈ 166 requests/second
That throughput removes the need for bulk ingestion complexity.
Request shape changes
The request contract is stricter, but structurally familiar.
Legacy request
POST https://integrators.prod.api.tabsplatform.com/events
{
"customerId": "cust_8xK2",
"eventName": "api_call",
"timestamp": "2026-05-13T10:00:00Z",
"quantity": 1
}
Legacy behavior
✓ Instant invoice reflection
✓ ~10 req/sec rate limit
✓ Server-generated idempotency
New request
POST https://usage-events.prod.api.tabsplatform.com/v1/events
{
"idempotencyKey": "550e8400-e29b-41d4-a716-...",
"customerId": "550e8400-e29b-41d4-a716-...",
"eventTypeId": "api_call",
"datetime": "2026-05-13T10:00:00Z",
"value": 1
}
New behavior
✓ Hourly invoice reflection
✓ 10,000 req/min rate limit
✓ Client-managed idempotency
Field renames
Old field | New field |
|---|---|
|
|
|
|
|
|
Common migration pitfalls
These issues usually show up after deployment — not during implementation.
Persist your UUIDs
Correct
Generate UUIDv4 once
Store alongside event row
Reuse on retry
Incorrect
Generate a new UUID on every retry
If you regenerate keys, deduplication will fail and duplicate billing may occur.
Mind the 1-hour recalculation window
The hourly invoice job only sweeps recent events.
Important nuance
Backfilled historical events:
Are accepted by the API
Exist in the database
May NOT automatically appear on invoices
Recommendation
Coordinate large backfills with the Tabs team instead of assuming automatic invoice recalculation.
Pre-validate customer ↔ event relationships
The API now rejects invalid customer/event combinations.
Recommended pattern
Cache customer billable event types
Validate locally before sending events
Benefits:
Cleaner internal logs
Fewer failed API calls
Easier debugging
Migration checklist
Follow these steps in order.
Pre-flight checklist
1 — Update the host
integrators.prod.api
↓
usage-events.prod.api.tabsplatform.com
2 — Add UUIDv4 idempotency keys
Requirements:
One UUID per event
Persist for retries
Deduplication lasts 45 days
3 — Remove bulk ingestion logic
Replace batching with simple per-event requests:
POST /v1/events
4 — Rename request fields
Old | New |
|---|---|
|
|
|
|
|
|
5 — Remove instant invoice assumptions
Anywhere your flow does:
POST event
→ immediately read invoice
must be refactored.
Recommended alternative
Use:
GET /events
instead of invoice polling for immediate verification.
6 — Add validation handling
Handle:
400 Bad Request
for invalid customer ↔ eventType combinations.
Do not expose raw API errors directly to merchants.