104 lines
4.3 KiB
Plaintext
104 lines
4.3 KiB
Plaintext
---
|
|
title: "Batch Track Usage"
|
|
openapi: "openapi POST /v1/balances.batch_track"
|
|
---
|
|
|
|
import { DynamicParamField } from "/snippets/dynamic-param-field.jsx";
|
|
import { DynamicResponseField } from "/snippets/dynamic-response-field.jsx";
|
|
import { DynamicResponseExample } from "/snippets/dynamic-response-example.jsx";
|
|
|
|
<Note>
|
|
Batch track enqueues up to **1000 usage events** in a single request. Items are validated synchronously, then enqueued for asynchronous processing. The response returns **202 immediately** without balance information — balances are deducted by background workers.
|
|
|
|
Use this when you're sending high volumes of tracking events and don't need an immediate balance read for each one.
|
|
</Note>
|
|
|
|
### Common Use Cases
|
|
|
|
<CodeGroup>
|
|
|
|
```typescript Batch many customers
|
|
await autumn.balances.batchTrack([
|
|
{ customerId: "cus_alice", featureId: "ai_messages", value: 1 },
|
|
{ customerId: "cus_bob", featureId: "ai_messages", value: 1 },
|
|
{ customerId: "cus_carol", featureId: "ai_messages", value: 3 },
|
|
]);
|
|
```
|
|
|
|
```typescript Mixed features and entities
|
|
await autumn.balances.batchTrack([
|
|
{ customerId: "cus_123", featureId: "ai_messages", value: 5 },
|
|
{ customerId: "cus_123", featureId: "api_calls", value: 12 },
|
|
{ customerId: "cus_123", featureId: "seats", entityId: "team_a", value: 1 },
|
|
]);
|
|
```
|
|
|
|
</CodeGroup>
|
|
|
|
### Partial-Failure Semantics
|
|
|
|
Batch track is designed for fire-and-forget metering. On partial failure, **the endpoint still returns 202** and logs the failed items server-side. Clients should NOT retry the batch — retrying re-enqueues the already-succeeded items, which causes double-deduction. The trade-off is silent loss of the small subset that didn't enqueue vs. duplicate processing of the much larger subset that did. For event-logging workloads, gaps are preferable to duplicates.
|
|
|
|
A 503 is returned only when **zero items were successfully enqueued** (the queue is entirely unavailable). In that case the whole request is safe to retry.
|
|
|
|
If your workload requires per-item delivery guarantees, use the [single-event track endpoint](/api-reference/core/track) with client-side retry semantics instead.
|
|
|
|
### Limits
|
|
|
|
- **Maximum batch size:** 1000 items per request
|
|
- **Minimum batch size:** 1 item
|
|
- **Rate limit:** 10 requests/second per organization (separate bucket from the single `/v1/balances.track` limiter)
|
|
|
|
### Body Parameters
|
|
|
|
<DynamicParamField body="items" type="object">
|
|
Array item
|
|
<Expandable title="properties">
|
|
<DynamicParamField body="customer_id" type="string" required>
|
|
The ID of the customer.
|
|
</DynamicParamField>
|
|
|
|
<DynamicParamField body="feature_id" type="string">
|
|
The ID of the feature to track usage for. Required if event_name is not provided.
|
|
</DynamicParamField>
|
|
|
|
<DynamicParamField body="entity_id" type="string">
|
|
The ID of the entity for entity-scoped balances (e.g., per-seat limits).
|
|
</DynamicParamField>
|
|
|
|
<DynamicParamField body="event_name" type="string">
|
|
Event name to track usage for. Use instead of feature_id when multiple features should be tracked from a single event.
|
|
</DynamicParamField>
|
|
|
|
<DynamicParamField body="value" type="number">
|
|
The amount of usage to record. Defaults to 1. Use negative values to credit balance (e.g., when removing a seat).
|
|
</DynamicParamField>
|
|
|
|
<DynamicParamField body="properties" type="object">
|
|
Additional properties to attach to this usage event.
|
|
</DynamicParamField>
|
|
|
|
<DynamicParamField body="async" type="boolean">
|
|
If true, enqueue the event for asynchronous processing and return 202 immediately. The response will not include balance information.
|
|
</DynamicParamField>
|
|
|
|
<DynamicParamField body="lock" type="object">
|
|
<Expandable title="properties">
|
|
<DynamicParamField body="lock_id" type="string" required>
|
|
A unique identifier for this lock. Used to finalize the lock later via balances.finalize.
|
|
</DynamicParamField>
|
|
|
|
<DynamicParamField body="enabled" type="any" required>
|
|
Must be true to enable locking.
|
|
</DynamicParamField>
|
|
|
|
<DynamicParamField body="expires_at" type="number">
|
|
Unix timestamp (ms) when the lock automatically expires and releases the held balance.
|
|
</DynamicParamField>
|
|
|
|
</Expandable>
|
|
</DynamicParamField>
|
|
|
|
</Expandable>
|
|
</DynamicParamField>
|