Reporting Events
Send usage data to Xtopay in real time as your customers consume your product.
Overview
Report a usage event every time a metered action occurs. Xtopay aggregates events over the billing period and charges the customer at period end.
Report a single event
await xtopay.meters.reportEvent({
meter_id: "mtr_a1b2c3",
customer_id: "cus_abc123",
event_name: "api.request",
timestamp: new Date().toISOString(), // when the event occurred (not when you report it)
quantity: 1, // for "count" meters, always 1
payload: { // arbitrary metadata
endpoint: "/v1/payments",
latency_ms: 120,
},
});Report a batch of events
For high-volume scenarios, batch up to 1,000 events per request:
await xtopay.meters.reportEvents([
{
meter_id: "mtr_a1b2c3",
customer_id: "cus_abc123",
event_name: "api.request",
timestamp: "2026-05-24T10:00:01Z",
quantity: 1,
},
{
meter_id: "mtr_a1b2c3",
customer_id: "cus_def456",
event_name: "api.request",
timestamp: "2026-05-24T10:00:02Z",
quantity: 1,
},
]);Events in a batch are processed atomically — either all are accepted or all are rejected.
Idempotency for events
Use event_id to prevent duplicate counting if you retry a failed report:
await xtopay.meters.reportEvent({
meter_id: "mtr_a1b2c3",
customer_id: "cus_abc123",
event_name: "sms.sent",
event_id: "evt_unique_abc123", // your own unique ID
timestamp: new Date().toISOString(),
quantity: 1,
});Reporting the same event_id twice counts as one event.
Backdating events
You can report events up to 48 hours in the past. This is useful if you batch-process usage data rather than reporting in real time.
Events cannot be reported for a billing period that has already been invoiced.
Event timestamps
Always use the time the event occurred in your system — not the time you reported it to Xtopay. This ensures accurate billing even if there's latency in your reporting pipeline.
// Good: use the actual event time
await xtopay.meters.reportEvent({
timestamp: requestTimestamp, // when the API call happened
...
});
// Bad: don't use the current time if the event happened earlier
await xtopay.meters.reportEvent({
timestamp: new Date().toISOString(), // misleading if event happened 30s ago
...
});High-volume patterns
For very high-volume metering (millions of events/day):
- Buffer events in memory for 1–5 seconds
- Send batches of 1,000 events at a time
- Use a background queue (BullMQ, SQS) for reliability
- Report failed batches with exponential backoff
// Example: buffer and batch with BullMQ
meterQueue.add("report", { events: bufferedEvents }, {
attempts: 5,
backoff: { type: "exponential", delay: 1000 },
});