RecoupGet a Free AuditFree Audit

API REFERENCE

Credit Usage Events (Admin)

On this page
GET/api/admins/credits/events

Returns the raw usage_events rows for a single account over the selected period, sorted by created_at descending. Powers the drilldown view that expands when a row in the /api/admins/credits/rollup table is opened. Each event represents one debit (main agent turn, subagent step, chat completion, or research call), with token counts and credits_deducted matching the wallet drop on credits_usage for that account.

The response also carries a grants array covering the same account and period: the admin credit grants made through POST /api/admins/credits. The two arrays answer different questions — events is what the system spent, grants is what a person set by hand, and only a grant carries an actor and a reason. Requires the authenticated account to be a Recoup admin.

Authentication

x-api-key in header

bearerAuth bearer

Request

cURL
curl --request GET \
  --url 'https://api.recoupable.dev/api/admins/credits/events?account_id=YOUR_ACCOUNT_ID' \
  --header 'x-api-key: YOUR_API_KEY'

Replace the YOUR_ placeholders with your values. Required query parameters are included; optional parameters are listed below.

Parameters

Query parameters

account_idstringrequired

UUID of the account whose usage_events rows to return.

periodstring · enum

Window to filter created_at against. Same semantics as the rollup endpoint. Defaults to monthly.

Values: "all", "daily", "weekly", "monthly"

Default: "monthly"

limitinteger

Page size — number of events to return per request, sorted by created_at descending. Defaults to 100; max 500.

Default: 100

pageinteger

1-indexed page number. Server returns rows (page - 1) * limit through page * limit - 1. Defaults to 1. Use total_count in the response to drive a 'load more' control on the drilldown (page * limit < total_count).

Default: 1

Responses

200Usage events retrieved successfully

application/json

statusstring · enumrequired

Status of the request

Values: "success", "error"

account_idstringrequired

UUID of the account whose events were returned (echoes the request)

format: uuid

periodstring · enumrequired

The period the response was filtered to (echoes the request)

Values: "all", "daily", "weekly", "monthly"

pageintegerrequired

1-indexed page returned (echoes the request, or 1 if omitted)

minimum: 1

limitintegerrequired

Page size used for this response (echoes the request, or the default if omitted)

minimum: 1

total_countintegerrequired

Total number of usage_events rows for this account in the selected period (i.e. the size of the full result set before pagination). The client derives has_more as page * limit < total_count and shows 'X of Y events'. Computed via a COUNT(*) query alongside the paginated row fetch.

minimum: 0

eventsarray<object>required

Raw usage_events rows, sorted by created_at descending

Item properties for events
idstringrequired

nanoid primary key of the usage_events row

created_atstringrequired

When the event was recorded

format: date-time

sourcestring · enumrequired

Which surface originated the debit. web = open-agents chat. api = recoupable api (chat completion or research call).

Values: "web", "api"

agent_typestring · enumrequired

main for the top-level agent turn or any non-agent debit; subagent for a nested task-tool step

Values: "main", "subagent"

providerstringnullable

Provider slug (e.g. anthropic). Null when the debit isn't tied to a specific provider (e.g. research).

model_idstringnullable

The model for LLM-backed debits (e.g. anthropic/claude-opus-4.6), otherwise the billed API endpoint as METHOD /route/pattern (e.g. POST /api/research/web). Null on rows written before 2026-08-27.

input_tokensintegerrequired

Total input tokens for the call (including cached). 0 for non-LLM debits.

cached_input_tokensintegerrequired

Subset of input_tokens that hit the provider cache (priced at the cache-read rate).

output_tokensintegerrequired

Output tokens for the call. 0 for non-LLM debits.

tool_call_countintegerrequired

Number of tool calls observed in this step

credits_deductedintegerrequired

The amount debited from credits_usage.remaining_credits for this event, in micro-dollars (1,000,000 = $1.00). Same value the wallet dropped by on this turn.

resource_urlstringnullable

App-relative path of what produced the debit (/chat?roomId=<roomId>, /music/<generationId>, /tasks/<taskId>/runs/<runId>). Null for plain API calls and for rows written before the field existed.

grantsarray<object>required

Admin credit grants made against this account in the selected period, sorted by created_at descending — the write-side counterpart to events. A grant is a staff member setting the balance through POST /api/admins/credits, so unlike an event it carries an actor and a reason. Not paginated by page/limit and not counted in total_count, which describe usage_events only; capped at the 500 most recent grants in the period. Empty for the overwhelming majority of accounts, which have never been granted anything.

Item properties for grants
idstringrequired

UUID of the grant row — the grant_id returned by POST /api/admins/credits

format: uuid

account_idstringrequired

UUID of the account the grant was made against. Always equal to the top-level account_id, since the endpoint reports on one account at a time; present because each entry is the full stored grant row.

format: uuid

created_atstringrequired

When the grant was made

format: date-time

granted_bystringrequired

UUID of the admin account that made the grant

format: uuid

reasonstringrequired

The reason the admin recorded for the grant, verbatim

previous_creditsintegerrequirednullable

Balance immediately before the grant. Null when the account had no credits row and the grant created one.

remaining_creditsintegerrequired

Balance the account was left holding by the grant

errorstring

Error message (only present if status is 'error')

400Missing or invalid account_id, period, or limit

application/json

statusstring · enumrequired

Status of the request

Values: "error"

messagestringrequired

Error message describing what went wrong

401Unauthorized - missing or invalid credentials

No response body schema is specified.

403Forbidden - authenticated account is not a Recoup admin

No response body schema is specified.

500Internal server error while fetching usage events

application/json

statusstring · enumrequired

Status of the request

Values: "error"

messagestringrequired

Error message describing what went wrong

Full specification

Download the OpenAPI file for complete schemas, constraints, and examples.

Download accounts.json
View operation source
json
{
  "description": "Returns the raw `usage_events` rows for a single account over the selected period, sorted by `created_at` descending. Powers the drilldown view that expands when a row in the [`/api/admins/credits/rollup`](/api-reference/admins/credits-rollup) table is opened. Each event represents one debit (main agent turn, subagent step, chat completion, or research call), with token counts and `credits_deducted` matching the wallet drop on `credits_usage` for that account.\n\nThe response also carries a `grants` array covering the same account and period: the admin credit grants made through [`POST /api/admins/credits`](/api-reference/admins/credits-grant). The two arrays answer different questions — `events` is what the system spent, `grants` is what a person set by hand, and only a grant carries an actor and a reason. Requires the authenticated account to be a Recoup admin.",
  "parameters": [
    {
      "name": "account_id",
      "in": "query",
      "required": true,
      "description": "UUID of the account whose `usage_events` rows to return.",
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    },
    {
      "name": "period",
      "in": "query",
      "required": false,
      "description": "Window to filter `created_at` against. Same semantics as the rollup endpoint. Defaults to `monthly`.",
      "schema": {
        "type": "string",
        "enum": [
          "all",
          "daily",
          "weekly",
          "monthly"
        ],
        "default": "monthly"
      }
    },
    {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size — number of events to return per request, sorted by `created_at` descending. Defaults to 100; max 500.",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 500,
        "default": 100
      }
    },
    {
      "name": "page",
      "in": "query",
      "required": false,
      "description": "1-indexed page number. Server returns rows `(page - 1) * limit` through `page * limit - 1`. Defaults to 1. Use `total_count` in the response to drive a 'load more' control on the drilldown (`page * limit < total_count`).",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "default": 1
      }
    }
  ],
  "security": [
    {
      "apiKeyAuth": []
    },
    {
      "bearerAuth": []
    }
  ],
  "responses": {
    "200": {
      "description": "Usage events retrieved successfully",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AdminCreditsEventsResponse"
          }
        }
      }
    },
    "400": {
      "description": "Missing or invalid `account_id`, `period`, or `limit`",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AccountErrorResponse"
          }
        }
      }
    },
    "401": {
      "description": "Unauthorized - missing or invalid credentials"
    },
    "403": {
      "description": "Forbidden - authenticated account is not a Recoup admin"
    },
    "500": {
      "description": "Internal server error while fetching usage events",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AccountErrorResponse"
          }
        }
      }
    }
  }
}