Batching usage events with the bulk endpoint
POST /v1/events/bulk takes the same event fields as a single event, in an events array:
- Batch size: 1 to 1000 events per request.
- Body size: up to 32 MiB. A larger body fails with
400and the message “Request body exceeds the maximum size; split the batch into smaller requests”. - Flush policy: send a batch when it reaches 1000 events or after a fixed interval, such as one or two seconds, whichever comes first, so a quiet period doesn’t hold events back.
- Invalid JSON, a timestamp that isn’t RFC 3339, more than 1000 events, or an oversized body reject the whole request before any event in it is accepted.
- An event missing
event_nameorexternal_customer_idcan fail the request after earlier events in the array were accepted.
event_id and timestamp, the events Flexprice already accepted collapse with their resent copies: see Idempotency and Deduplication.
Batching usage events with the SDKs
Every SDK has a bulk method. Collect events in your worker and send them in one call:How the Go SDK async client sends usage events
The Go SDK also has an async client (client.NewAsyncClientWithConfig) that queues events in process memory and sends them from background goroutines. Know how it delivers before you bill on it:
- It sends each event as its own
POST /v1/eventsrequest, not through the bulk endpoint. - It doesn’t set an
event_id. Pass your own withEnqueueWithOptions, or a resent event can’t be recognized as a copy. When you leave out the timestamp, it stamps the event at enqueue time. - An event whose send fails is dropped once the retries configured on the parent client (
WithRetryConfig) run out. The failure is printed only whenDebugis on. Close()returns without waiting for queued events to be sent, so events still in memory when the process exits can be lost.Enqueueblocks while the queue is full (MaxQueueSize, 1000 by default).
IngestEventsBulk instead.
Streaming usage events with the Flexprice Collector
If your usage already flows through Kafka or another stream, run the Flexprice Collector instead of writing a sender. It reads from the stream, transforms each message into a Flexprice event, batches events (10 events or 2 seconds by default), and retries failed requests with exponential backoff. To install it, see Get Started.Keeping a high-volume sender stable
- Cap concurrency. Send from a fixed pool of workers, each with one request in flight, instead of opening a request per event.
- Back off on failure. Retry network errors, timeouts, and
5xxresponses with exponential backoff and jitter, so that many workers don’t retry in lockstep. - Let the queue absorb outages. Keep events on a durable queue until Flexprice accepts them, size it for the longest outage you want to ride out, and alert on the age of the oldest event in it.
- Watch processing lag. A
202means Flexprice accepted the events; metering runs asynchronously behind it. The Event Monitoring endpoint returnsconsumption_lag, the number of accepted events still waiting to be processed in your environment.
Send Usage Events with the API and SDKs
Authentication, single and bulk requests, and the responses to handle.
Backfill Past Usage
Load historical usage and get it onto draft or finalized invoices.

