# Get account usage

Source: https://docs.recoupable.dev/api-reference/accounts/usage-get

List the charges that consumed an account's credits: one line item per deduction from usage_events, newest first, over a period.

## GET /api/accounts/{id}/usage

Full OpenAPI specification: https://docs.recoupable.dev/spec/accounts.json

## Authentication

This operation requires one of the security alternatives in the specification below. Security scheme definitions are included where present in the published specification.

[Authentication guide](https://docs.recoupable.dev/authentication)

## Operation and referenced schemas

```json
{
  "openapi": "3.1.0",
  "info": {
    "title": "Recoup API - Accounts",
    "description": "API documentation for the Recoup platform - an AI agent platform for the music industry",
    "license": {
      "name": "MIT"
    },
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://api.recoupable.dev"
    }
  ],
  "paths": {
    "/api/accounts/{id}/usage": {
      "get": {
        "operationId": "getAccountsByIdUsage",
        "description": "List the charges that consumed an account's credits: one line item per deduction from `usage_events`, newest first, over a period. Each item carries the amount as the raw ledger integer (`credits_deducted`, micro-dollars: 1,000,000 = $1.00) and the same amount formatted as a dollar string (`usd`), and the response carries the total for the whole period, not just the page. Access is the same as [`GET /api/accounts/{id}/credits`](/api-reference/accounts/credits-get): the authenticated account itself, or another account reachable through organization membership.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The unique identifier (UUID) of the account. Must be the authenticated account or another accessible via organization membership.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of line items to return per page.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Both orders are descending: created_at uses timestamp then row ID; cost uses credits_deducted then row ID. Cost ties are ordered by ID, not timestamp.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "cost"
              ],
              "default": "created_at"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque paging token: pass next_cursor unchanged with the same sort, from and to. New time cursors retain both the last timestamp and row ID, so tied timestamps are not skipped. Cost cursors retain amount and row ID. Legacy timestamp-only cursors remain accepted as strict time boundaries; start a fresh traversal to obtain complete tie coverage.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Start of the period (inclusive), ISO 8601. Defaults to the start of the current UTC month.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "End of the period (exclusive), ISO 8601. Defaults to now.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Usage line items retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountUsageResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request: invalid query parameter, limit above 100, malformed cursor, or a non-positive period after database timestamp normalization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountCreditsErrorResponse"
                },
                "example": {
                  "error": "limit must be between 1 and 100"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing authentication",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountCreditsErrorResponse"
                },
                "example": {
                  "error": "Unauthorized"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - account not accessible to the authenticated account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountCreditsErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AccountUsageResponse": {
        "type": "object",
        "required": [
          "account_id",
          "period",
          "total_credits_deducted",
          "total_usd",
          "events",
          "next_cursor"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "The account whose charges are listed.",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "period": {
            "type": "object",
            "required": [
              "from",
              "to"
            ],
            "description": "The period the totals cover.",
            "properties": {
              "from": {
                "type": "string",
                "format": "date-time",
                "example": "2026-08-01T00:00:00.000Z"
              },
              "to": {
                "type": "string",
                "format": "date-time",
                "example": "2026-08-27T12:00:00.000Z"
              }
            }
          },
          "total_credits_deducted": {
            "type": "integer",
            "description": "Sum of `credits_deducted` over every charge in the period, in micro-dollars. Covers the whole period, not only this page.",
            "example": 70000
          },
          "total_usd": {
            "type": "string",
            "description": "`total_credits_deducted` formatted as US dollars.",
            "example": "$0.07"
          },
          "events": {
            "type": "array",
            "description": "Charges in the period in the requested `sort` order (newest first by default).",
            "items": {
              "$ref": "#/components/schemas/AccountUsageEvent"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Opaque; pass unchanged as cursor with the same sort, from and to. A full page may return a cursor followed by an empty final page; null means this traversal has ended. Time cursors retain timestamp and ID; cost cursors retain amount and ID.",
            "example": "v1:WyIyMDI2LTA4LTI3VDExOjU2OjU4LjAwMDAwMFoiLCIzQUFObjNJajl1Ri16WklsV196bFAiXQ"
          },
          "series_bucket": {
            "type": "string",
            "enum": [
              "hour",
              "day",
              "week",
              "month"
            ],
            "description": "Granularity of `series`, derived from the span of the period: `hour` up to 2 days, `day` up to 90 days, `week` up to 12 months, `month` beyond. Present only on a first page (no `cursor`).",
            "example": "day"
          },
          "series": {
            "type": "array",
            "description": "Spend over the period, one entry per `series_bucket` that had at least one charge, ascending by `start`, in UTC. The sum of `credits_deducted` across the entries equals `total_credits_deducted`. Present only on a first page (no `cursor`); omitted on cursor pages so paging never recomputes it.",
            "items": {
              "type": "object",
              "required": [
                "start",
                "credits_deducted",
                "usd",
                "events"
              ],
              "properties": {
                "start": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Start of the bucket, UTC.",
                  "example": "2026-08-12T00:00:00.000Z"
                },
                "credits_deducted": {
                  "type": "integer",
                  "description": "Charges in the bucket, in micro-dollars.",
                  "example": 221090000
                },
                "usd": {
                  "type": "string",
                  "description": "`credits_deducted` formatted as US dollars.",
                  "example": "$221.09"
                },
                "events": {
                  "type": "integer",
                  "description": "Number of charges in the bucket.",
                  "example": 2462
                }
              }
            },
            "example": [
              {
                "start": "2026-08-11T00:00:00.000Z",
                "credits_deducted": 56080000,
                "usd": "$56.08",
                "events": 727
              },
              {
                "start": "2026-08-12T00:00:00.000Z",
                "credits_deducted": 221090000,
                "usd": "$221.09",
                "events": 2462
              },
              {
                "start": "2026-08-13T00:00:00.000Z",
                "credits_deducted": 440930000,
                "usd": "$440.93",
                "events": 5479
              }
            ]
          }
        }
      },
      "AccountCreditsErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "Account not found"
          }
        }
      },
      "AccountUsageEvent": {
        "type": "object",
        "required": [
          "id",
          "created_at",
          "source",
          "agent_type",
          "provider",
          "model_id",
          "input_tokens",
          "cached_input_tokens",
          "output_tokens",
          "tool_call_count",
          "credits_deducted",
          "usd",
          "resource_url"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Identifier of the `usage_events` row.",
            "example": "3AANn3Ij9uF-zZIlW_zlP"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the charge was recorded, normalized to UTC at database microsecond precision.",
            "example": "2026-08-27T11:56:58.000000Z"
          },
          "source": {
            "type": "string",
            "description": "Which surface originated the charge: `api` for a request to the API, `web` for the chat app. Null when this field was not recorded.",
            "example": "api",
            "nullable": true
          },
          "agent_type": {
            "type": "string",
            "description": "`main` for a top-level request or any non-agent charge; `subagent` for a nested task step. Null when this field was not recorded.",
            "example": "main",
            "nullable": true
          },
          "provider": {
            "type": "string",
            "nullable": true,
            "description": "Provider slug when the charge is a model or generation call (for example `anthropic`, `fal`). Null for research and other fixed-price endpoints.",
            "example": "fal"
          },
          "model_id": {
            "type": "string",
            "nullable": true,
            "description": "The model for LLM-backed charges (a chat turn, a song generation), otherwise the API endpoint that was billed, as `METHOD /route/pattern` (for example `POST /api/artist/socials/scrape`). Null on rows written before 2026-08-27.",
            "example": "POST /api/artist/socials/scrape"
          },
          "input_tokens": {
            "type": "integer",
            "description": "Input tokens for the call, including cached. 0 for non-LLM charges. Null when this field was not recorded.",
            "example": 0,
            "nullable": true
          },
          "cached_input_tokens": {
            "type": "integer",
            "description": "Subset of `input_tokens` served from the provider cache. Null when this field was not recorded.",
            "example": 0,
            "nullable": true
          },
          "output_tokens": {
            "type": "integer",
            "description": "Output tokens for the call. 0 for non-LLM charges. Null when this field was not recorded.",
            "example": 0,
            "nullable": true
          },
          "tool_call_count": {
            "type": "integer",
            "description": "Recorded tool count for this event. For the main agent workflow, this counts tool entries in the accumulated assistant reply, including pending and failed requests and entries retained when that reply resumes. Nested subagent entries are excluded. The value describes the reply snapshot, rather than successful executions or only new work after a resume. A writer can default an omitted count to zero, so zero alone does not establish that no tools were requested. Older events retain their previously recorded counts. Null when this field was not recorded.",
            "example": 0,
            "nullable": true
          },
          "credits_deducted": {
            "type": "integer",
            "description": "Amount charged, as the raw ledger integer in micro-dollars (1,000,000 = $1.00). Divide by 1,000,000 for dollars.",
            "example": 20000
          },
          "usd": {
            "type": "string",
            "description": "`credits_deducted` formatted as US dollars with two decimals.",
            "example": "$0.02"
          },
          "resource_url": {
            "type": "string",
            "nullable": true,
            "description": "App-relative path of what produced the charge, when there is something to open: `/chat?roomId=<roomId>` for a chat turn, `/music/<generationId>` for a song, `/tasks/<taskId>/runs/<runId>` for a scheduled task run. Null for plain API calls and for rows written before the field existed.",
            "example": "/music/0c35429f-deb8-48f0-b0f2-fd5145de2583"
          }
        }
      }
    },
    "securitySchemes": {
      "apiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Your Recoup API key. [Learn more](/quickstart#api-keys)."
      },
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      }
    }
  }
}
```
