---
title: "Send a usage event"
description: "The event's key makes the call safe to retry: a repeat key returns the stored event with status duplicate and changes nothing, even if its timestamp or values differ."
canonical_url: "https://twominutebilling.com/help/developers/api-reference/usage/send-a-usage-event"
---
# Send a usage event

> The event's key makes the call safe to retry: a repeat key returns the stored event with status duplicate and changes nothing, even if its timestamp or values differ.

<api-operation method="POST" path="/v1/businesses/{biz}/usage_events">
<template v-slot:docs="">

The event's `key` makes the call safe to retry: a repeat key returns the stored event with status `duplicate` and changes nothing, even if its timestamp or values differ. Keys are kept 35 days. The `Idempotency-Key` header is not used. The event is stored before we answer. An event whose customer key matches no customer is kept as unmatched and bills once you add the key to a customer. Needs `usage_events:manage`.

## Path parameters

<table>
<thead>
  <tr>
    <th>
      Parameter
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Required
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        biz
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <strong>
        yes
      </strong>
    </td>
    
    <td>
      The business's id (biz_…).
    </td>
  </tr>
</tbody>
</table>

## Body

The request body is **required**.

<table>
<thead>
  <tr>
    <th>
      Field
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Required
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        key
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <strong>
        yes
      </strong>
    </td>
    
    <td>
      Your idempotency key for this event, unique per business.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        customer
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <strong>
        yes
      </strong>
    </td>
    
    <td>
      A usage key of the customer, or the customer id (cus_…).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        event_name
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <strong>
        yes
      </strong>
    </td>
    
    <td>
      The usage event's event name.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        timestamp
      </code>
    </td>
    
    <td>
      <code>
        string · ISO-8601
      </code>
    </td>
    
    <td>
      no
    </td>
    
    <td>
      RFC 3339 with <code>
        Z
      </code>
      
       or an offset. From 35 days in the past to 5 minutes in the future. Default: now.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        properties
      </code>
    </td>
    
    <td>
      <code>
        object
      </code>
    </td>
    
    <td>
      no
    </td>
    
    <td>
      Flat, up to 50 keys and 8 KB. A meter's value property must be a number from -10^12 to 10^12 with at most 12 decimal places; a number is read from its exact text.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        amount
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      no
    </td>
    
    <td>
      Major units, from -10^12 to 10^12. A decimal string with at most 12 decimal places and no exponent, for example <code>
        "0.000125"
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        cost
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      no
    </td>
    
    <td>
      Your cost, major units, from -10^12 to 10^12. A decimal string with at most 12 decimal places and no exponent, for example <code>
        "0.000125"
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        currency
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      no
    </td>
    
    <td>
      Default: the price's currency.
    </td>
  </tr>
</tbody>
</table>

## Response

<table>
<thead>
  <tr>
    <th>
      Field
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        event
      </code>
    </td>
    
    <td>
      <code>
        object
      </code>
    </td>
    
    <td>
      The usage event result's event.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        status
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      The usage event result's status. One of <code>
        created
      </code>
      
      , <code>
        duplicate
      </code>
      
      , <code>
        voided
      </code>
      
      .
    </td>
  </tr>
</tbody>
</table>

## Status codes

<table>
<thead>
  <tr>
    <th>
      Status
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        200
      </code>
    </td>
    
    <td>
      A duplicate: the stored event.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        201
      </code>
    </td>
    
    <td>
      The event was recorded.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        400
      </code>
    </td>
    
    <td>
      The body is not correct.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        422
      </code>
    </td>
    
    <td>
      The event was refused: <code>
        timestamp_too_old
      </code>
      
      , <code>
        timestamp_in_future
      </code>
      
       or <code>
        invalid_value
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        429
      </code>
    </td>
    
    <td>
      Your organization sent more usage requests in one second than its limit. Send again after <code>
        Retry-After
      </code>
      
       seconds.
    </td>
  </tr>
</tbody>
</table>
</template>

<template v-slot:request="">

```bash [Request]
curl -X POST "$TMBILLING_URL/v1/businesses/biz_XXXXXXXXXXXX01/usage_events" \
  -H "Authorization: Bearer $TMBILLING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "resp_XXXXXXXXXXXX01:input",
    "customer": "workspace-4821",
    "event_name": "ai_tokens",
    "currency": "USD"
  }'
```

</template>

<template v-slot:response="">
<code-group>

```json [200 OK]
{
  "event": {
    "object": "usage_event",
    "id": "evt_XXXXXXXXXXXX01",
    "key": "resp_XXXXXXXXXXXX01:input",
    "customer": "cus_XXXXXXXXXXXX01",
    "event_name": "ai_tokens",
    "timestamp": "2026-03-14T09:30:00Z",
    "properties": {
      "model": "large-v2",
      "token_type": "input",
      "tokens": 1200
    },
    "amount": "Amount",
    "cost": "Cost",
    "currency": "USD",
    "customer_key": "Customer key",
    "status": "matched",
    "meters": [
      "Meter"
    ],
    "flags": [
      "Flag"
    ],
    "created_at": "2026-03-14T09:30:00Z",
    "voided_at": null,
    "void_reason": null
  },
  "status": "created"
}
```

```json [201 Created]
{
  "event": {
    "object": "usage_event",
    "id": "evt_XXXXXXXXXXXX01",
    "key": "resp_XXXXXXXXXXXX01:input",
    "customer": "cus_XXXXXXXXXXXX01",
    "event_name": "ai_tokens",
    "timestamp": "2026-03-14T09:30:00Z",
    "properties": {
      "model": "large-v2",
      "token_type": "input",
      "tokens": 1200
    },
    "amount": "Amount",
    "cost": "Cost",
    "currency": "USD",
    "customer_key": "Customer key",
    "status": "matched",
    "meters": [
      "Meter"
    ],
    "flags": [
      "Flag"
    ],
    "created_at": "2026-03-14T09:30:00Z",
    "voided_at": null,
    "void_reason": null
  },
  "status": "created"
}
```

```json [400 Bad Request]
{
  "error": {
    "type": "invalid_request_error",
    "message": "The body is not correct."
  }
}
```

```json [422 Unprocessable Entity]
{
  "error": {
    "type": "invalid_request_error",
    "message": "The event was refused: timestamp_too_old, timestamp_in_future or invalid_value."
  }
}
```

```json [429 Too Many Requests]
{
  "error": {
    "type": "rate_limit_error",
    "message": "Your organization sent more usage requests in one second than its limit."
  }
}
```

</code-group>
</template>
</api-operation>


## Sitemap

See the full [sitemap](https://twominutebilling.com/sitemap.md) for all pages.
