Skip to content

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-ingest
Terminal window
Authorization: Bearer <api-key>
Content-Type: application/json

Requires usage ingest access. Use this endpoint only from a trusted backend, gateway, or server-side SDK.

{
"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.

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.

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_ids to inspect processed usage events and charge items.