Batch Ingest Usage Events
Batch ingest submits multiple usage events in one HTTP request. Use it when your backend naturally collects usage in batches, or when one batch may contain events that must be processed by different extractor rule sets.
Unlike the single-event ingest endpoint, the extractor rule set ID is carried by each event item in the request body.
POST /v1/projects/:project_id/events/batch-ingestAuthentication
Section titled “Authentication”Authorization: Bearer <api-key>Content-Type: application/jsonRequires usage ingest access. Use this endpoint only from a trusted backend, gateway, or server-side SDK.
Request Body
Section titled “Request Body”{ "source": "openai-gateway", "events": [ { "extractor_rule_set_id": "ers_openai", "idempotency_key": "openai-gateway:chatcmpl_123", "subject_type": "organization", "subject_id": "org_001", "occurred_at": 1781222400, "raw_json": { "provider": "openai", "usage": { "model": "gpt-4.1-mini", "prompt_tokens": 1200 } } }, { "extractor_rule_set_id": "ers_agent_tools", "source": "agent-runtime", "idempotency_key": "agent-runtime:task_456", "subject_type": "user", "subject_id": "user_456", "occurred_at": 1781222410, "raw_json": { "tool": "web_search", "usage": { "calls": 1 } } } ]}| Field | Required | Description |
|---|---|---|
source |
Conditionally | Default event source for the batch. Required when an item does not provide its own source. |
events |
Yes | Usage event items to submit. Must not be empty. |
events[].extractor_rule_set_id |
Yes | Published extractor rule set used to normalize this event. Each item may use a different rule set. |
events[].source |
Conditionally | Event source for this item. Overrides the batch-level source. |
events[].idempotency_key |
Yes | Stable retry key for this event. Use upstream request IDs, gateway event IDs, task IDs, or another deterministic event identity. Reusing the same key with the same project_id and occurred_at produces the same raw_event_id. |
events[].external_event_id |
No | Upstream event or request ID for support and reconciliation. |
events[].subject_type |
Conditionally | Explicit subject type. Must match [a-z][a-z0-9_]{0,63} and be provided with events[].subject_id. |
events[].subject_id |
Conditionally | Explicit subject ID. Must be provided with events[].subject_type. |
events[].occurred_at |
Yes | Event occurrence time as Unix seconds. Required for partition routing and idempotency. |
events[].raw_json |
Yes | Original usage JSON for this event. |
events[].x-billing |
No | Dynamic billing extension for this event item. |
events[].x-usage-control |
No | Usage-control extension for this event item. Set budget_lease_id to charge it against one active Budget Lease. |
events[].metadata |
No | Ingest-side metadata for audit or operations. |
Batch Commit Behavior
Section titled “Batch Commit Behavior”The batch endpoint has an all-or-nothing commit contract from the client’s point of view.
Meterry validates the whole request before writing to the usage queue. If any event is invalid, the entire request fails with a non-2xx response. Examples include a missing extractor_rule_set_id, missing source, invalid raw_json, a rule set that does not exist, a draft or archived rule set, or a tenant/project mismatch.
For each item, a complete subject_type and subject_id pair overrides the extractor’s subject paths and defaults. If the pair is omitted, subject resolution uses path values first and defaults second. A partial pair makes the whole batch invalid.
After validation, Meterry writes the whole batch to the usage queue. The API returns success only after the queue write succeeds. A successful HTTP response means the batch has been accepted for asynchronous processing; it does not mean rating, wallet debit, analytics projection, or invoicing has completed.
If the HTTP request fails, retry the same batch. Meterry filters already processed events by each event’s idempotency_key, so callers can treat a failed batch response as “the batch did not complete successfully” and safely push the batch again. Each retry is still a new ingest attempt for realtime quota admission, even when downstream raw-event processing deduplicates the event.
Response
Section titled “Response”The API returns HTTP 202 Accepted when the batch is accepted.
{ "status": "received", "count": 2, "raw_event_ids": ["raw_01hxy7f9q8m2", "raw_01hxy7f9q8m3"]}On failure, the API returns a non-2xx response and no events from the batch should be considered accepted by the client.
{ "error": "events[1].extractor_rule_set_id is not published"}- Every batch ingest request must use the project-scoped path.
- Every event must have a stable
idempotency_key; without one, the batch request is rejected because retries cannot be safely deduplicated. - Use List Usage Event Details with returned
raw_event_idsto inspect processed usage events and charge items.