Skip to content

Usage events tools

MCP tools for Usage events: usage_events_create, usage_events_list.

  • usage_events_create: Record usage events
  • usage_events_list: List usage events

usage_events_create

Record usage events. Operation usage_events.create · Brand level · permission usage:write · risk tier write · since M5

Records a batch of 1 to 1,000 usage events for metered prices, billed in arrears on the customer's next invoice. Each event names the customerId, the meter (a meter of one of the brand's metered prices), the quantity (an integer string; negative usage, such as refunded volume, reduces the period), when it happened (occurredAt), optional attributes, and its own idempotencyKey, unique in the brand and mode.

Every event gets a result, in request order (results[i]), and the batch is recorded even when some events fail:

  • created: recorded now;
  • duplicate: an event with this key and the same content was recorded earlier (or earlier in the batch); it is counted once, so resending a batch after a timeout is safe;
  • failed: not recorded, with an error (usage_idempotency_key_reused, resource_not_found or customer_deleted for the customer, usage_meter_unknown, usage_occurred_at_out_of_range, resource_not_found or subscription_item_meter_mismatch for a subscriptionItemId).

A malformed request (a missing field, a quantity that isn't an integer, more than 1,000 events) is refused as a whole with validation_failed, and nothing is recorded.

Usage is aggregated per customer, meter, day (in the entity's time zone) and attribute set. Usage that happened in a period that was already invoiced is recorded as late and billed on the next invoice as a separate late usage line. Each request counts once against the API key's rate limit, whatever its size.

Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: true · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
eventsarray of objectyes1 to 1000 usage events. (1–1000 items)
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand.
idempotency_keystringnoA unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters)
dry_runbooleannotrue: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false)
  • Brand: pass brand_id with an organization or entity key; a brand key acts on its own brand.
  • Idempotency: the result returns the idempotency_key used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
  • Dry run: supported. dry_run: true checks permissions and rules and computes the result, then rolls everything back.
  • Plan feature: needs usage_billing.enabled.

Errors

Examples

Two events, one sent again

The second event was already recorded by an earlier request: it is reported, not counted again.

Arguments:

JSON
{
  "events": [
    {
      "idempotencyKey": "req_7f3a9c",
      "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0a1",
      "meter": "api.calls",
      "quantity": "120",
      "occurredAt": "2026-10-13T09:15:00Z",
      "attributes": {
        "model": "large"
      }
    },
    {
      "idempotencyKey": "req_7f3a9b",
      "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0a1",
      "meter": "api.calls",
      "quantity": "80",
      "occurredAt": "2026-10-13T09:14:00Z"
    }
  ],
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "object": "usage_event_batch",
  "created": 1,
  "duplicates": 1,
  "failed": 0,
  "results": [
    {
      "index": 0,
      "idempotencyKey": "req_7f3a9c",
      "status": "created",
      "id": "uev_01m4v0d9k2j7r5t3w8x6y4z2a0",
      "late": false,
      "error": null
    },
    {
      "index": 1,
      "idempotencyKey": "req_7f3a9b",
      "status": "duplicate",
      "id": "uev_01m4v0d9k2j7r5t3w8x6y4z2a1",
      "late": false,
      "error": null
    }
  ]
}

Refunded volume, and a misspelled meter

Arguments:

JSON
{
  "events": [
    {
      "idempotencyKey": "refund_re_8812",
      "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0a1",
      "meter": "payments.volume",
      "quantity": "-25000000",
      "occurredAt": "2026-10-13T10:00:00Z"
    },
    {
      "idempotencyKey": "call_99102",
      "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0a1",
      "meter": "api.cals",
      "quantity": 1,
      "occurredAt": "2026-10-13T10:00:05Z"
    }
  ],
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "object": "usage_event_batch",
  "created": 1,
  "duplicates": 0,
  "failed": 1,
  "results": [
    {
      "index": 0,
      "idempotencyKey": "refund_re_8812",
      "status": "created",
      "id": "uev_01m4v0d9k2j7r5t3w8x6y4z2a0",
      "late": false,
      "error": null
    },
    {
      "index": 1,
      "idempotencyKey": "call_99102",
      "status": "failed",
      "id": null,
      "late": null,
      "error": {
        "code": "usage_meter_unknown",
        "message": "No metered price of this brand uses this meter.",
        "param": "events.1.meter",
        "details": {
          "meter": "api.cals"
        }
      }
    }
  ]
}

usage_events_list

List usage events. Operation usage_events.list · Brand level · permission usage:read · risk tier read · since M5

Lists the brand's usage events in the mode of the request, newest recorded first.

  • customerId, meter: one customer's or one meter's events;
  • occurredFrom (inclusive) and occurredTo (exclusive): when the usage happened (ISO 8601 instants);
  • late=true: only late usage (it happened in a period that was already invoiced), late=false: the others.

Paginate with limit (1–100, default 10) and starting_after (the next_cursor of the previous page).

Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
limitintegerno(1–100)
starting_afterID (uev_…)no–
customerIdID (cus_…)noOnly this customer's events.
meterstringnoOnly this meter's events. (at most 100 characters)
occurredFromdate-time (ISO 8601)noEvents that happened at or after this instant.
occurredTodate-time (ISO 8601)noEvents that happened before this instant.
latestringnotrue: only late events (they happened in a period that was already invoiced); false: only the others.
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand.
  • Brand: pass brand_id with an organization or entity key; a brand key acts on its own brand.
  • Read-only: changes nothing; idempotency_key is ignored.

Errors

Example

A customer's API calls on one day

Arguments:

JSON
{
  "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0a1",
  "meter": "api.calls",
  "occurredFrom": "2026-10-13T00:00:00+02:00",
  "occurredTo": "2026-10-14T00:00:00+02:00",
  "limit": 2,
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}

Result output:

JSON
{
  "object": "list",
  "data": [
    {
      "id": "uev_01m4v0d9k2j7r5t3w8x6y4z2a0",
      "object": "usage_event",
      "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
      "livemode": false,
      "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0a1",
      "subscriptionItemId": null,
      "meter": "api.calls",
      "quantity": "120",
      "occurredAt": "2026-10-13T09:15:00.000Z",
      "attributes": {
        "model": "large"
      },
      "idempotencyKey": "req_7f3a9c",
      "late": false,
      "walletId": null,
      "reservationId": null,
      "amount": null,
      "createdAt": "2026-10-13T09:15:02.000Z"
    },
    {
      "id": "uev_01m4v0d9k2j7r5t3w8x6y4z2a1",
      "object": "usage_event",
      "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
      "livemode": false,
      "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0a1",
      "subscriptionItemId": null,
      "meter": "api.calls",
      "quantity": "80",
      "occurredAt": "2026-10-13T09:14:00.000Z",
      "attributes": {},
      "idempotencyKey": "req_7f3a9b",
      "late": false,
      "walletId": null,
      "reservationId": null,
      "amount": null,
      "createdAt": "2026-10-13T09:14:01.000Z"
    }
  ],
  "has_more": true,
  "next_cursor": "uev_01m4v0d9k2j7r5t3w8x6y4z2a1"
}