API REFERENCE
Credit Usage Events (Admin)
On this page
/api/admins/credits/eventsReturns 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 --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_idstringrequiredUUID of the account whose usage_events rows to return.
periodstring · enumWindow to filter created_at against. Same semantics as the rollup endpoint. Defaults to monthly.
Values: "all", "daily", "weekly", "monthly"
Default: "monthly"
limitintegerPage size — number of events to return per request, sorted by created_at descending. Defaults to 100; max 500.
Default: 100
pageinteger1-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 · enumrequiredStatus of the request
Values: "success", "error"
account_idstringrequiredUUID of the account whose events were returned (echoes the request)
format: uuid
periodstring · enumrequiredThe period the response was filtered to (echoes the request)
Values: "all", "daily", "weekly", "monthly"
pageintegerrequired1-indexed page returned (echoes the request, or 1 if omitted)
minimum: 1
limitintegerrequiredPage size used for this response (echoes the request, or the default if omitted)
minimum: 1
total_countintegerrequiredTotal 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>requiredRaw usage_events rows, sorted by created_at descending
Item properties for events
idstringrequirednanoid primary key of the usage_events row
created_atstringrequiredWhen the event was recorded
format: date-time
sourcestring · enumrequiredWhich surface originated the debit. web = open-agents chat. api = recoupable api (chat completion or research call).
Values: "web", "api"
agent_typestring · enumrequiredmain for the top-level agent turn or any non-agent debit; subagent for a nested task-tool step
Values: "main", "subagent"
providerstringnullableProvider slug (e.g. anthropic). Null when the debit isn't tied to a specific provider (e.g. research).
model_idstringnullableThe 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_tokensintegerrequiredTotal input tokens for the call (including cached). 0 for non-LLM debits.
cached_input_tokensintegerrequiredSubset of input_tokens that hit the provider cache (priced at the cache-read rate).
output_tokensintegerrequiredOutput tokens for the call. 0 for non-LLM debits.
tool_call_countintegerrequiredNumber of tool calls observed in this step
credits_deductedintegerrequiredThe 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_urlstringnullableApp-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>requiredAdmin 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
idstringrequiredUUID of the grant row — the grant_id returned by POST /api/admins/credits
format: uuid
account_idstringrequiredUUID 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_atstringrequiredWhen the grant was made
format: date-time
granted_bystringrequiredUUID of the admin account that made the grant
format: uuid
reasonstringrequiredThe reason the admin recorded for the grant, verbatim
previous_creditsintegerrequirednullableBalance immediately before the grant. Null when the account had no credits row and the grant created one.
remaining_creditsintegerrequiredBalance the account was left holding by the grant
errorstringError message (only present if status is 'error')
400Missing or invalid account_id, period, or limit+
application/json
statusstring · enumrequiredStatus of the request
Values: "error"
messagestringrequiredError 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 · enumrequiredStatus of the request
Values: "error"
messagestringrequiredError message describing what went wrong
Full specification
Download the OpenAPI file for complete schemas, constraints, and examples.
Download accounts.jsonView operation source
{
"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"
}
}
}
}
}
}