Skip to main content
DocumentationUsage · console.latam.ccsio.ai

Usage

Usage ingest and the organization's usage reads: records, pages and summaries, filtered by principal where the caller may.

Documentation menu

The descriptions of the operations and fields are the contract’s own, in English.

GET/metering/v1/usage

Read a usage fact back by idempotency key

Credential
API key
Permission
usage.read

Reads back the ingested C2 usage record by its canonical idempotency key (the idempotency_key query parameter, in the key's canonical compact-JSON form, percent-encoded). The response is the codec's exact C2 wire bytes — byte-identical to the ingested fixture. A key that was never applied is 404 usage-not-found.

curl
curl "https://console.latam.ccsio.ai/metering/v1/usage?idempotency_key=<idempotency_key>" \
  -H "Authorization: Bearer $CCSIO_API_KEY"

Parameters

NameInDescription
X-Request-ID
optional
headerstring

Optional request ULID. A valid ULID (upper or lowercase) is honored; when the header is absent or invalid, the runtime mints the id. The response X-Request-ID header carries the canonical uppercase form.

idempotency_key
required
querystring

The key's canonical C2 form: compact JSON, five fields in schema order (tenant_id, plane_instance_id, request_or_run_id, attempt, provider_response_id), percent-encoded; the object shape is the C2 schema's idempotency_key; out-of-form is idempotency-key-invalid, distinct from invalid-request.

Responses

  • 200

    The usage fact, in its C2 wire form.

    Schema
    UsageRecord
    • deployment_idstring or nulloptional

      pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$

    • provider_classanyoptional

      Allowed values: "CCSIO_INFERENCE""CUSTOMER_HOSTED""EXTERNAL_MANAGED"null

    • request_duration_msinteger or nulloptional

      Whole router request timing, shared by all attempt records; absent on legacy records.

      0 to 9007199254740991

    • request_ttft_msinteger or nulloptional

      Whole router request timing, shared by all attempt records; absent on legacy records.

      0 to 9007199254740991

    • session_idstring or nulloptional

      Client-provided session label (the X-Session-Id request header), copied onto every attempt record of the request; absent or null when the client sent none. It groups requests for the operator; it is never an identity and never used for authorization or tenancy.

      pattern ^[A-Za-z0-9._:-]{1,128}$

    • http_statusinteger or nulloptional

      The HTTP status the router answered for the whole request: its single response, identical on every attempt record of the request (the per-attempt result is outcome_class). A request that failed after the response header was committed (a stream cut mid-way) keeps the committed status, 200. Absent or null on legacy records.

      100 to 599

    • error_codestring or nulloptional

      The stable error code of the router's response to the request (the OpenAI-format error.code, or the platform error code on the routes that answer in that envelope), identical on every attempt record of the request; for a stream cut after the header was committed it is the code of the terminal error frame, or, on the surfaces that write no terminal frame (a cut chat stream, an aborted audio transfer), the code the failure classifies to. Null or absent when the request succeeded and on legacy records.

      pattern ^[a-z][a-z0-9._-]{0,127}$

    • api_key_idstring or nulloptional

      The id of the API key the request was authenticated with (the key's key_id in the identity API, never the key itself), copied by the router from the signed context onto every attempt record of the request; absent or null for a request made without an API key, such as one from a console session. It says which credential was used; it is never an identity and never used for authorization or tenancy.

      pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$

    • schema_versionanyrequired

      always "c2/v1"

    • event_idstringrequired

      pattern ^[a-z][a-z0-9._-]{0,127}$

    • idempotency_keyobjectrequired
      • tenant_idstringrequired

        pattern ^[a-z][a-z0-9._-]{0,127}$

      • plane_instance_idstringrequired

        pattern ^[a-z][a-z0-9._-]{0,127}$

      • request_or_run_idstringrequired

        pattern ^[a-z][a-z0-9._-]{0,127}$

      • attemptintegerrequired

        1 to 9007199254740991

      • provider_response_idone of or nullrequired

        One of

        • #1stringoptional

          pattern ^[a-z][a-z0-9._-]{0,127}$

        • #2anyoptional

          always ""

    • occurred_atstring (utc-second)required

      pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$

    • emitted_atstring (utc-second)required

      pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$

    • monotonic_since_boot_msintegerrequired

      0 to 9007199254740991

    • seqobjectrequired
      • stream_idstringrequired

        pattern ^[a-z][a-z0-9._-]{0,127}$

      • nintegerrequired

        1 to 9007199254740991

    • meter_epochstringrequired

      pattern ^[a-z][a-z0-9._-]{0,127}$

    • tenant_idstringrequired

      pattern ^[a-z][a-z0-9._-]{0,127}$

    • team_idstring or nullrequired

      pattern ^[a-z][a-z0-9._-]{0,127}$

    • principal_classstringrequired

      Allowed values: "user""service""agent"

    • principal_refstringrequired

      Original authenticated principal reference, preserved byte-for-byte under the C0 identity grammar.

      pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$

    • planestringrequired

      Allowed values: "ai""agent""memory""brain"

    • operationstringrequired

      Allowed values: "chat""embedding""audio""image""document""tool""agent_overhead""responses""decision"

    • accounting_scopestringrequired

      Allowed values: "provider_attempt""platform_overhead""agent_aggregate"

    • model_aliasstringrequired

      Original selected model reference, preserved byte-for-byte under the C0 model registry grammar.

      pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$

    • model_catalog_entry_digeststringrequired

      pattern ^[a-f0-9]{64}$

    • request_idstringrequired

      pattern ^[a-z][a-z0-9._-]{0,127}$

    • run_idstring or nullrequired

      pattern ^[a-z][a-z0-9._-]{0,127}$

    • agent_idstring or nullrequired

      pattern ^[a-z][a-z0-9._-]{0,127}$

    • agent_spec_digeststring or nullrequired

      pattern ^[a-f0-9]{64}$

    • quantitiesarray of objectrequired

      at most 16 items

      • unitstringrequired

        pattern ^[a-z][a-z0-9._-]{0,127}$

      • amountstringrequired

        pattern ^(0|[1-9][0-9]{0,17})(\.[0-9]{0,8}[1-9])?$

    • measurementstringrequired

      Allowed values: "measured""estimated""unknown"

    • measurement_reasonstring or nullrequired

      Allowed values: "coarse_counter""provider_estimate""final_usage_missing""meter_loss""canceled""implausible_count"

    • duration_msinteger or nullrequired

      0 to 9007199254740991

    • ttft_msinteger or nullrequired

      0 to 9007199254740991

    • request_countintegerrequired

      0 to 9007199254740991

    • tool_call_countintegerrequired

      0 to 9007199254740991

    • outcome_classstringrequired

      Allowed values: "success""error""canceled""unknown"

    • data_classificationstringrequired

      Allowed values: "public""internal""restricted"

    • routing_inputsobjectrequired
      • rule_idsarray of stringrequired

        at most 16 items

      • classification_labelstringrequired

        Allowed values: "public""internal""restricted"

      • priority_groupstringrequired

        Allowed values: "low""normal""high"

    • routing_inputs_digeststringrequired

      pattern ^[a-f0-9]{64}$

    • bundle_versionintegerrequired

      1 to 9007199254740991

    • bundle_digeststringrequired

      pattern ^[a-f0-9]{64}$

  • 400

    Client refusal unrelated to authentication, including malformed input, a denied or failed request.

  • 401

    The request carries no credential, more than one, or one the platform does not accept, and is refused before the operation runs; `error.code` says why. Supply exactly one credential. Codes: invalid-request (no credential, or both Authorization:

    Read more

    Bearer and x-api-key), api-key-invalid (a value that is not a platform API key, or a key of a kind the platform does not accept), api-key-unknown, api-key-revoked, api-key-expired, bootstrap-disabled (the one-shot installation credential, once a key exists), token-malformed (a bearer token that is not a JWT), token-algorithm-unsupported, token-signature-invalid, token-claim-invalid, token-issuer-mismatch, token-audience-mismatch, token-expired, token-not-yet-valid, issuer-untrusted, issuer-residency-mismatch (the issuer belongs to another plane), issuer-resolution-unknown, jwks-unavailable, jwks-key-not-found, staff-token-inactive (a platform operator's token), staff-not-operator, staff-directory-unavailable, identity-not-provisioned (a verified identity with no account on this plane), organization-not-found (a verified identity or key whose organization this plane does not know), internal-error (a fault while the credential is checked is refused too, fail closed), context-cancelled

  • 402

    The organization has to pay first: its standing is payment_required.

    Read more

    The request boundary applies this payment gate to every route except an organization's billing routes, the caller's own context, organization list, onboarding, session report and personal keys, the public routes, and the routes of platform operators, who administer an organization that has to pay. The operations the gate covers declare this response. On /v1 the refusal is rendered in the OpenAI error format. Code: payment-required

  • 403

    The credential is valid but may not do this here; the request is refused by the request boundary before the handler runs, and `error.code` says which refusal. An operation may add codes of its own.

    Read more

    Codes: policy-denied (no role of the caller holds the permission the operation needs, or the credential class may not call it: a personal API key outside inference and MCP, a route that needs a signed-in person, the one-shot installation credential outside its three steps), tenant-mismatch (the organization a path, query, body or X-Tenant header names is not the caller's own), organization-provisioning, organization-suspended, organization-disabled, organization-deleted (the state of the caller's organization), user-disabled, residency-mismatch (the organization lives on another plane), organization-selection-required (a caller with more than one organization, or a platform operator, must name one in X-Organization-Id), organization-not-selectable, no-active-organization-membership, team-not-selectable (the X-Organization-Id or X-Team-Id the caller sent does not name an organization or team it may act in), identity-managed-by-provider (a person who is not a platform operator changes an organization's status, which belongs to the identity provider), support-session-required (a platform operator reads an organization's data without an open support session)

  • 404

    The requested resource or path was not found.

  • 405

    The path is claimed but the request method is not allowed. Go ServeMux returns its standard plain-text response and lists permitted methods in Allow.

  • 500

    Platform failure, rendered without internal cause details.

POST/metering/v1/usage

Ingest one C2 usage record

Credential
API key
Permission
usage.manage
Request body
Body up to 1 MiB

Ingests one C2 v1 usage record. The body is the strict C2 profile (unknown fields and trailing data rejected). Idempotent under redelivery: a duplicate key renders exactly {"status":"redelivered"} with no event_id or checkpoint.

Read more

First delivery renders {"status":"ingested","event_id":...,"checkpoint":{...}}; event_id is present only when usage-event emission is enabled on the serving role (see info). The request body is capped at 1048576 bytes; over-cap is 400 invalid-request, never 413.

curl
curl -X POST "https://console.latam.ccsio.ai/metering/v1/usage" \
  -H "Authorization: Bearer $CCSIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "schema_version": null,
  "event_id": "string",
  "idempotency_key": {
    "tenant_id": "string",
    "plane_instance_id": "string",
    "request_or_run_id": "string",
    "attempt": 0,
    "provider_response_id": "string"
  },
  "occurred_at": "string",
  "emitted_at": "string",
  "monotonic_since_boot_ms": 0,
  "seq": {
    "stream_id": "string",
    "n": 0
  },
  "meter_epoch": "string",
  "tenant_id": "string",
  "team_id": "string",
  "principal_class": "user",
  "principal_ref": "string",
  "plane": "ai",
  "operation": "chat",
  "accounting_scope": "provider_attempt",
  "model_alias": "string",
  "model_catalog_entry_digest": "string",
  "request_id": "string",
  "run_id": "string",
  "agent_id": "string",
  "agent_spec_digest": "string",
  "quantities": [
    {
      "unit": "string",
      "amount": "string"
    }
  ],
  "measurement": "measured",
  "measurement_reason": "coarse_counter",
  "duration_ms": 0,
  "ttft_ms": 0,
  "request_count": 0,
  "tool_call_count": 0,
  "outcome_class": "success",
  "data_classification": "public",
  "routing_inputs": {
    "rule_ids": [
      "string"
    ],
    "classification_label": "public",
    "priority_group": "low"
  },
  "routing_inputs_digest": "string",
  "bundle_version": 0,
  "bundle_digest": "string"
}'
Built from the schema’s required members: replace the values.

Parameters

NameInDescription
X-Request-ID
optional
headerstring

Optional request ULID. A valid ULID (upper or lowercase) is honored; when the header is absent or invalid, the runtime mints the id. The response X-Request-ID header carries the canonical uppercase form.

Request body application/json

UsageRecord
  • deployment_idstring or nulloptional

    pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$

  • provider_classanyoptional

    Allowed values: "CCSIO_INFERENCE""CUSTOMER_HOSTED""EXTERNAL_MANAGED"null

  • request_duration_msinteger or nulloptional

    Whole router request timing, shared by all attempt records; absent on legacy records.

    0 to 9007199254740991

  • request_ttft_msinteger or nulloptional

    Whole router request timing, shared by all attempt records; absent on legacy records.

    0 to 9007199254740991

  • session_idstring or nulloptional

    Client-provided session label (the X-Session-Id request header), copied onto every attempt record of the request; absent or null when the client sent none. It groups requests for the operator; it is never an identity and never used for authorization or tenancy.

    pattern ^[A-Za-z0-9._:-]{1,128}$

  • http_statusinteger or nulloptional

    The HTTP status the router answered for the whole request: its single response, identical on every attempt record of the request (the per-attempt result is outcome_class). A request that failed after the response header was committed (a stream cut mid-way) keeps the committed status, 200. Absent or null on legacy records.

    100 to 599

  • error_codestring or nulloptional

    The stable error code of the router's response to the request (the OpenAI-format error.code, or the platform error code on the routes that answer in that envelope), identical on every attempt record of the request; for a stream cut after the header was committed it is the code of the terminal error frame, or, on the surfaces that write no terminal frame (a cut chat stream, an aborted audio transfer), the code the failure classifies to. Null or absent when the request succeeded and on legacy records.

    pattern ^[a-z][a-z0-9._-]{0,127}$

  • api_key_idstring or nulloptional

    The id of the API key the request was authenticated with (the key's key_id in the identity API, never the key itself), copied by the router from the signed context onto every attempt record of the request; absent or null for a request made without an API key, such as one from a console session. It says which credential was used; it is never an identity and never used for authorization or tenancy.

    pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$

  • schema_versionanyrequired

    always "c2/v1"

  • event_idstringrequired

    pattern ^[a-z][a-z0-9._-]{0,127}$

  • idempotency_keyobjectrequired
    • tenant_idstringrequired

      pattern ^[a-z][a-z0-9._-]{0,127}$

    • plane_instance_idstringrequired

      pattern ^[a-z][a-z0-9._-]{0,127}$

    • request_or_run_idstringrequired

      pattern ^[a-z][a-z0-9._-]{0,127}$

    • attemptintegerrequired

      1 to 9007199254740991

    • provider_response_idone of or nullrequired

      One of

      • #1stringoptional

        pattern ^[a-z][a-z0-9._-]{0,127}$

      • #2anyoptional

        always ""

  • occurred_atstring (utc-second)required

    pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$

  • emitted_atstring (utc-second)required

    pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$

  • monotonic_since_boot_msintegerrequired

    0 to 9007199254740991

  • seqobjectrequired
    • stream_idstringrequired

      pattern ^[a-z][a-z0-9._-]{0,127}$

    • nintegerrequired

      1 to 9007199254740991

  • meter_epochstringrequired

    pattern ^[a-z][a-z0-9._-]{0,127}$

  • tenant_idstringrequired

    pattern ^[a-z][a-z0-9._-]{0,127}$

  • team_idstring or nullrequired

    pattern ^[a-z][a-z0-9._-]{0,127}$

  • principal_classstringrequired

    Allowed values: "user""service""agent"

  • principal_refstringrequired

    Original authenticated principal reference, preserved byte-for-byte under the C0 identity grammar.

    pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$

  • planestringrequired

    Allowed values: "ai""agent""memory""brain"

  • operationstringrequired

    Allowed values: "chat""embedding""audio""image""document""tool""agent_overhead""responses""decision"

  • accounting_scopestringrequired

    Allowed values: "provider_attempt""platform_overhead""agent_aggregate"

  • model_aliasstringrequired

    Original selected model reference, preserved byte-for-byte under the C0 model registry grammar.

    pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$

  • model_catalog_entry_digeststringrequired

    pattern ^[a-f0-9]{64}$

  • request_idstringrequired

    pattern ^[a-z][a-z0-9._-]{0,127}$

  • run_idstring or nullrequired

    pattern ^[a-z][a-z0-9._-]{0,127}$

  • agent_idstring or nullrequired

    pattern ^[a-z][a-z0-9._-]{0,127}$

  • agent_spec_digeststring or nullrequired

    pattern ^[a-f0-9]{64}$

  • quantitiesarray of objectrequired

    at most 16 items

    • unitstringrequired

      pattern ^[a-z][a-z0-9._-]{0,127}$

    • amountstringrequired

      pattern ^(0|[1-9][0-9]{0,17})(\.[0-9]{0,8}[1-9])?$

  • measurementstringrequired

    Allowed values: "measured""estimated""unknown"

  • measurement_reasonstring or nullrequired

    Allowed values: "coarse_counter""provider_estimate""final_usage_missing""meter_loss""canceled""implausible_count"

  • duration_msinteger or nullrequired

    0 to 9007199254740991

  • ttft_msinteger or nullrequired

    0 to 9007199254740991

  • request_countintegerrequired

    0 to 9007199254740991

  • tool_call_countintegerrequired

    0 to 9007199254740991

  • outcome_classstringrequired

    Allowed values: "success""error""canceled""unknown"

  • data_classificationstringrequired

    Allowed values: "public""internal""restricted"

  • routing_inputsobjectrequired
    • rule_idsarray of stringrequired

      at most 16 items

    • classification_labelstringrequired

      Allowed values: "public""internal""restricted"

    • priority_groupstringrequired

      Allowed values: "low""normal""high"

  • routing_inputs_digeststringrequired

    pattern ^[a-f0-9]{64}$

  • bundle_versionintegerrequired

    1 to 9007199254740991

  • bundle_digeststringrequired

    pattern ^[a-f0-9]{64}$

Responses

  • 200

    The usage record was ingested (or redelivered).

    Schema
    IngestResponse
    • statusstringrequired

      The ingest result: ingested (first delivery) or redelivered (duplicate key).

      Allowed values: "ingested""redelivered"

    • event_idstringoptional

      The durable outbox row's ULID, minted at enqueue (first delivery only; omitted on redelivery; present only when usage-event emission is enabled on the serving role).

      pattern ^[0-9A-HJKMNP-TV-Z]{26}$

    • checkpointobjectoptional

      The scope's C3 checkpoint cursors (first delivery only; omitted on redelivery).

      • tenant_idstringrequired

        pattern ^[a-z][a-z0-9._-]{0,127}$

      • plane_instance_idstringrequired

        pattern ^[a-z][a-z0-9._-]{0,127}$

      • stream_idstringrequired

        pattern ^[a-z][a-z0-9._-]{0,127}$

      • contiguous_usage_throughintegerrequired

        0 to 9007199254740991

      • usage_high_waterintegerrequired

        0 to 9007199254740991

  • 400

    Client refusal unrelated to authentication, including malformed input, a denied or failed request.

  • 401

    The request carries no credential, more than one, or one the platform does not accept, and is refused before the operation runs; `error.code` says why. Supply exactly one credential. Codes: invalid-request (no credential, or both Authorization:

    Read more

    Bearer and x-api-key), api-key-invalid (a value that is not a platform API key, or a key of a kind the platform does not accept), api-key-unknown, api-key-revoked, api-key-expired, bootstrap-disabled (the one-shot installation credential, once a key exists), token-malformed (a bearer token that is not a JWT), token-algorithm-unsupported, token-signature-invalid, token-claim-invalid, token-issuer-mismatch, token-audience-mismatch, token-expired, token-not-yet-valid, issuer-untrusted, issuer-residency-mismatch (the issuer belongs to another plane), issuer-resolution-unknown, jwks-unavailable, jwks-key-not-found, staff-token-inactive (a platform operator's token), staff-not-operator, staff-directory-unavailable, identity-not-provisioned (a verified identity with no account on this plane), organization-not-found (a verified identity or key whose organization this plane does not know), internal-error (a fault while the credential is checked is refused too, fail closed), context-cancelled

  • 402

    The organization has to pay first: its standing is payment_required.

    Read more

    The request boundary applies this payment gate to every route except an organization's billing routes, the caller's own context, organization list, onboarding, session report and personal keys, the public routes, and the routes of platform operators, who administer an organization that has to pay. The operations the gate covers declare this response. On /v1 the refusal is rendered in the OpenAI error format. Code: payment-required

  • 403

    The credential is valid but may not do this here; the request is refused by the request boundary before the handler runs, and `error.code` says which refusal. An operation may add codes of its own.

    Read more

    Codes: policy-denied (no role of the caller holds the permission the operation needs, or the credential class may not call it: a personal API key outside inference and MCP, a route that needs a signed-in person, the one-shot installation credential outside its three steps), tenant-mismatch (the organization a path, query, body or X-Tenant header names is not the caller's own), organization-provisioning, organization-suspended, organization-disabled, organization-deleted (the state of the caller's organization), user-disabled, residency-mismatch (the organization lives on another plane), organization-selection-required (a caller with more than one organization, or a platform operator, must name one in X-Organization-Id), organization-not-selectable, no-active-organization-membership, team-not-selectable (the X-Organization-Id or X-Team-Id the caller sent does not name an organization or team it may act in), identity-managed-by-provider (a person who is not a platform operator changes an organization's status, which belongs to the identity provider), support-session-required (a platform operator reads an organization's data without an open support session)

  • 405

    The path is claimed but the request method is not allowed. Go ServeMux returns its standard plain-text response and lists permitted methods in Allow.

  • 500

    Platform failure, rendered without internal cause details.

GET/metering/v1/usage/summary

Summarize the selected organization's usage

Credential
API key
Permission
Any ofusage.read_ownusage.readplatform-usage.readsupport-access.read

The organization is derived exclusively from the verified actor context; tenant or organization query parameters are not accepted. Reads occurred_at in the half-open [from, to) UTC interval, defaulting to the last 7 days and capped at 90 days. Counts and quantities are exact strings.

Read more

Metrics retain accounting_scope so provider attempts, platform overhead, and agent aggregates are not double-counted as a single total. Unknown or duplicate query parameters and invalid windows return 400; a missing selected organization returns 403. Windows with no usage return empty scopes/models/by_principal, zero daily series, and cost unavailable. Optional model_alias and accounting_scope filters apply to the full requested window before aggregation or pagination; filtering never operates on a truncated request page. The optional principal filter (a principal_ref or an email address, with the request-log principal filter's validation, case-insensitive email resolution and visibility rule) narrows every total, daily bucket and breakdown to that principal's usage. The optional api_key_id filter narrows them to the usage made with one API key; with both, a fact must match both. by_principal breaks the filtered window down per principal: one entry per accounting scope and principal_ref, named with the email and display name resolved when the summary is read, at most 100 per accounting scope (by_principal_truncated tells when any scope was cut); the scope totals always cover every principal. Requires usage.read_own (at any level), usage.read or, for a platform operator, platform-usage.read. WHICH usage: a caller holding usage.read at organization level (the Administrator role) reads every principal's usage; a caller holding usage.read_own without it - the built-in User role, and a Team Admin, whose usage.read applies to its team's request log and not to this report - reads ONLY the usage whose principal is themselves (a member's own user principal and personal API keys, a service account the usage it made), whatever the request carries: the principal filter is forced to the caller's own reference, so a principal filter naming anyone else, by reference or by email, matches nothing (200 with an empty result, never an error and never a hint of whose usage it is - the request log's narrowing) and by_principal holds only the caller. WITH AN API KEY: these routes answer a service-account API key sent in x-api-key or as Authorization: Bearer, on the console host of the key's own organization and region; a personal API key reaches inference and MCP only and is refused here with 403 policy-denied. A key whose role holds usage.read_own without usage.read reads ONLY the usage made with that key: the facts whose api_key_id is the key's own key_id, not everything its service account made. Whatever the request carries, the read stays bound to that key and to its service account: an api_key_id naming another key (of the same service account or of anyone else) and a principal naming anyone else match nothing (200 with an empty result, never an error), and the key's own id or reference is the same read as no filter. A key whose role holds usage.read at organization level reads the organization's usage exactly as the Administrator role does and may narrow it to one key with api_key_id. Neither level reads another organization: the organization is the key's own and no parameter or header names it. A revoked or expired key is 401 api-key-revoked or api-key-expired, as on every route; an organization with no active subscription is refused with 402 payment-required before any role is checked. A caller holding none of these permissions is 403 policy-denied. A platform operator (platform-usage.read: a permission of the fixed operator set, held by no organization or team role and by no custom role) who selected the organization with the X-Organization-Id header reads the organization's totals, daily series and per-model rows exactly as the Administrator role does, with by_principal an empty list and by_principal_truncated false and nobody named: the view is not per user, so a principal or api_key_id filter is refused with 400 invalid-request, while the period, model_alias, accounting_scope and operation_class filters apply. Without a selected organization the operator is told to select one (403 organization-selection-required). The permission opens no other read: the usage page, the request logs, the usage lookup and the status reads need usage.read or usage.read_own and answer a platform operator with 403 policy-denied. The answer for the organization's own members is unchanged.

curl
curl "https://console.latam.ccsio.ai/metering/v1/usage/summary" \
  -H "Authorization: Bearer $CCSIO_API_KEY"

Parameters

NameInDescription
X-Request-ID
optional
headerstring

Optional request ULID. A valid ULID (upper or lowercase) is honored; when the header is absent or invalid, the runtime mints the id. The response X-Request-ID header carries the canonical uppercase form.

from
optional
querystring

Inclusive UTC RFC 3339 start (must end in Z; fractional seconds allowed). Supply both from and to or omit both for the last 7 days, or the cursor's frozen window when paging. The interval must be positive and at most 90 days.

to
optional
querystring

Exclusive UTC RFC 3339 end (must end in Z; fractional seconds allowed). Required when from is supplied.

model_alias
optional
querystring

Optional exact model reference, preserving case and punctuation. Omit for all models; a valid reference with no matching usage returns empty totals and zero daily buckets.

accounting_scope
optional
querystring

Optional accounting scope. Omit for all scopes, which remain separate in every aggregate; the literal all is not accepted.

principal
optional
queryone of

Optional.

Read more

Narrows every total, daily bucket and breakdown of the response to the usage made by this principal: the principal_ref (a C0 reference) or an email address (it contains '@'), matched case-insensitively against the organization's users and resolved to their refs, exactly as the request-log principal filter does. A reference matches the usage of that principal_ref whatever its principal_class (a member's own sessions and personal API keys share their reference). An email filter follows the visibility rule of the emails themselves: a caller who may not read the organization's member list (members.read at organization level, or a platform administrator) may filter only by their own email, any other address matches no usage; an address that matches no user matches no usage (a 200 with empty scopes, models and by_principal, zero daily buckets or an empty page — not an error — so the filter cannot be used to probe whose address it is). A value that is neither a reference nor a plain email address (no display name, no whitespace, at most 254 bytes) renders 400 invalid-request. On the page read the cursor is bound to the filter as it was typed. The platform operator's summary (platform-usage.read) is not per user: there this filter renders 400 invalid-request. For an API key reading only its own usage, a principal other than its service account's matches no usage.

api_key_id
optional
querystring

Optional. Narrows every total, daily bucket and breakdown of the response (or every record of the page) to the usage made with this API key: the facts whose api_key_id is this value, the key's key_id in the identity API.

Read more

Usage made from a console session carries no key and never matches, and neither does usage recorded before the usage fact carried the key (2026-10-06) nor a tool call through the MCP endpoint. A key that made no usage in the window gives a 200 with empty scopes, models and by_principal, zero daily buckets or an empty page, not an error. A value outside the key id grammar renders 400 invalid-request. On the page read the cursor is bound to the filter. The platform operator's summary (platform-usage.read) is not per user: there this filter renders 400 invalid-request. For an API key whose role holds usage.read_own without usage.read, the read is already bound to that key's own id: its own key_id is the same read as no filter, and any other id (of its service account's other keys too) gives a 200 with an empty result.

operation_class
optional
querystring

Optional. Narrows every total, daily bucket and breakdown of the response (or every record of the page) to one class of usage. `inference` is the usage of models: every fact whose operation is not `tool`. `tool` is the calls of MCP tools: the facts whose operation is `tool`, whose model_alias names the installation and the tool. Without it the read covers both, as before. A page's cursor is bound to it.

Responses

  • 200

    The selected organization's usage metrics for the requested window.

    Schema
    UsageSummaryResponse
    • organization_idstringrequired

      pattern ^[a-z][a-z0-9._-]{0,63}$

    • windowobjectrequired
      • fromstring (date-time)required

        pattern Z$

      • tostring (date-time)required

        pattern Z$

    • scopesarray of UsageSummaryScoperequired

      Metrics grouped by accounting_scope; scopes are never combined into an ambiguous total.

      • accounting_scopestringrequired

        Allowed values: "provider_attempt""platform_overhead""agent_aggregate"

      • recordsUsageCountrequired

        An exact non-negative integer serialized as a string to avoid client precision loss.

      • request_countUsageCountrequired

        An exact non-negative integer serialized as a string to avoid client precision loss.

      • tool_call_countUsageCountrequired

        An exact non-negative integer serialized as a string to avoid client precision loss.

      • quantitiesarray of UsageQuantityrequired
      • measurement_countsobjectrequired
        • measuredUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • estimatedUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • unknownUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

      • outcome_countsobjectrequired
        • successUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • errorUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • canceledUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • unknownUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

    • modelsarray of UsageSummaryModelrequired

      Metrics grouped by the pair (accounting_scope, model_alias).

      • accounting_scopestringrequired

        Allowed values: "provider_attempt""platform_overhead""agent_aggregate"

      • recordsUsageCountrequired

        An exact non-negative integer serialized as a string to avoid client precision loss.

      • request_countUsageCountrequired

        An exact non-negative integer serialized as a string to avoid client precision loss.

      • tool_call_countUsageCountrequired

        An exact non-negative integer serialized as a string to avoid client precision loss.

      • quantitiesarray of UsageQuantityrequired
      • measurement_countsobjectrequired
        • measuredUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • estimatedUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • unknownUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

      • outcome_countsobjectrequired
        • successUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • errorUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • canceledUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • unknownUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

      • model_aliasstringrequired

        Original selected model reference, preserved byte-for-byte under the C0 model registry grammar.

        pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$

    • by_principalarray of UsageSummaryPrincipalrequired

      Metrics grouped by the pair (accounting_scope, principal_ref): who made the usage of the filtered window, each principal named (see UsageSummaryPrincipal). Ordered by request_count descending (an exact integer), then principal_ref ascending, then accounting_scope. At most 100 entries per accounting_scope (so at most 300): a scope with more principals lists its first 100 and by_principal_truncated is true. The scope totals in scopes always cover every principal.

      at most 300 items

      • accounting_scopestringrequired

        Allowed values: "provider_attempt""platform_overhead""agent_aggregate"

      • recordsUsageCountrequired

        An exact non-negative integer serialized as a string to avoid client precision loss.

      • request_countUsageCountrequired

        An exact non-negative integer serialized as a string to avoid client precision loss.

      • tool_call_countUsageCountrequired

        An exact non-negative integer serialized as a string to avoid client precision loss.

      • quantitiesarray of UsageQuantityrequired
      • measurement_countsobjectrequired
        • measuredUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • estimatedUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • unknownUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

      • outcome_countsobjectrequired
        • successUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • errorUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • canceledUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

        • unknownUsageCountrequired

          An exact non-negative integer serialized as a string to avoid client precision loss.

      • principal_refstringrequired

        The principal's authoritative reference, preserved byte-for-byte under the C0 identity grammar.

        pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$

      • principal_classstringrequired

        Allowed values: "user""service""agent"

      • emailstring or nullrequired

        The principal's email address, resolved at read time; null when the principal has none (a service account), is unknown to the organization's directory, or this caller may not see another user's email.

        at most 254 characters

      • display_namestring or nullrequired

        The principal's display name (for a service account, its name), resolved at read time; null under the same conditions as email and when the principal has none.

        at most 128 characters

    • by_principal_truncatedbooleanrequired

      True when at least one accounting scope has more than 100 principals and by_principal lists only its first 100 (ordered by request_count descending, then principal_ref). scopes, models and series always cover every principal.

    • costobjectrequired
      • statusstringrequired

        Usage quantities have no authoritative pricing data; no estimated monetary total is presented.

        always "unavailable"

    • seriesarray of UsageSeriesBucketrequired

      Ascending UTC calendar-day buckets covering the whole half-open response window. First and last bucket boundaries are clipped to the window, including fractional seconds. Every intersecting day is present, including zero days. Within each accounting scope, summing daily metrics and quantities equals the full-window scoped totals; scopes are never added together.

      at least 1 items · at most 91 items

      • windowobjectrequired
        • fromstring (date-time)required

          pattern Z$

        • tostring (date-time)required

          pattern Z$

      • scopesarray of UsageSummaryScoperequired

        Each requested accounting scope is present independently. An empty scope has exact zero counts, zero measurement/outcome counts, and quantities []; no units or measurements are fabricated.

        at least 1 items · at most 3 items

  • 400

    Client refusal unrelated to authentication, including malformed input, a denied or failed request.

  • 401

    The request carries no credential, more than one, or one the platform does not accept, and is refused before the operation runs; `error.code` says why. Supply exactly one credential. Codes: invalid-request (no credential, or both Authorization:

    Read more

    Bearer and x-api-key), api-key-invalid (a value that is not a platform API key, or a key of a kind the platform does not accept), api-key-unknown, api-key-revoked, api-key-expired, bootstrap-disabled (the one-shot installation credential, once a key exists), token-malformed (a bearer token that is not a JWT), token-algorithm-unsupported, token-signature-invalid, token-claim-invalid, token-issuer-mismatch, token-audience-mismatch, token-expired, token-not-yet-valid, issuer-untrusted, issuer-residency-mismatch (the issuer belongs to another plane), issuer-resolution-unknown, jwks-unavailable, jwks-key-not-found, staff-token-inactive (a platform operator's token), staff-not-operator, staff-directory-unavailable, identity-not-provisioned (a verified identity with no account on this plane), organization-not-found (a verified identity or key whose organization this plane does not know), internal-error (a fault while the credential is checked is refused too, fail closed), context-cancelled

  • 402

    The organization has to pay first: its standing is payment_required.

    Read more

    The request boundary applies this payment gate to every route except an organization's billing routes, the caller's own context, organization list, onboarding, session report and personal keys, the public routes, and the routes of platform operators, who administer an organization that has to pay. The operations the gate covers declare this response. On /v1 the refusal is rendered in the OpenAI error format. Code: payment-required

  • 403

    The credential is valid but may not do this here; the request is refused by the request boundary before the handler runs, and `error.code` says which refusal. An operation may add codes of its own.

    Read more

    Codes: policy-denied (no role of the caller holds the permission the operation needs, or the credential class may not call it: a personal API key outside inference and MCP, a route that needs a signed-in person, the one-shot installation credential outside its three steps), tenant-mismatch (the organization a path, query, body or X-Tenant header names is not the caller's own), organization-provisioning, organization-suspended, organization-disabled, organization-deleted (the state of the caller's organization), user-disabled, residency-mismatch (the organization lives on another plane), organization-selection-required (a caller with more than one organization, or a platform operator, must name one in X-Organization-Id), organization-not-selectable, no-active-organization-membership, team-not-selectable (the X-Organization-Id or X-Team-Id the caller sent does not name an organization or team it may act in), identity-managed-by-provider (a person who is not a platform operator changes an organization's status, which belongs to the identity provider), support-session-required (a platform operator reads an organization's data without an open support session)

  • 405

    The path is claimed but the request method is not allowed. Go ServeMux returns its standard plain-text response and lists permitted methods in Allow.

  • 500

    Platform failure, rendered without internal cause details.

  • 503

    A dependency the operation needs is not configured on this plane or could not be reached, and nothing was changed. `error.code` names it; an operation lists the ones it can answer besides the boundary's. Retry later. Codes: support-audit-unavailable (the request boundary: an operator's read under an open support session could not be recorded, so nothing was served)

Example response
{
  "organization_id": "acme",
  "window": {
    "from": "2026-10-12T00:00:00Z",
    "to": "2026-10-14T00:00:00Z"
  },
  "scopes": [
    {
      "accounting_scope": "provider_attempt",
      "records": "5",
      "request_count": "5",
      "tool_call_count": "0",
      "quantities": [
        {
          "unit": "input_tokens",
          "amount": "1840"
        },
        {
          "unit": "output_tokens",
          "amount": "3122"
        }
      ],
      "measurement_counts": {
        "measured": "5",
        "estimated": "0",
        "unknown": "0"
      },
      "outcome_counts": {
        "success": "4",
        "error": "1",
        "canceled": "0",
        "unknown": "0"
      }
    }
  ],
  "models": [
    {
      "accounting_scope": "provider_attempt",
      "model_alias": "gpt-4o",
      "records": "3",
      "request_count": "3",
      "tool_call_count": "0",
      "quantities": [
        {
          "unit": "input_tokens",
          "amount": "1200"
        },
        {
          "unit": "output_tokens",
          "amount": "3122"
        }
      ],
      "measurement_counts": {
        "measured": "3",
        "estimated": "0",
        "unknown": "0"
      },
      "outcome_counts": {
        "success": "2",
        "error": "1",
        "canceled": "0",
        "unknown": "0"
      }
    },
    {
      "accounting_scope": "provider_attempt",
      "model_alias": "embed-1",
      "records": "2",
      "request_count": "2",
      "tool_call_count": "0",
      "quantities": [
        {
          "unit": "input_tokens",
          "amount": "640"
        }
      ],
      "measurement_counts": {
        "measured": "2",
        "estimated": "0",
        "unknown": "0"
      },
      "outcome_counts": {
        "success": "2",
        "error": "0",
        "canceled": "0",
        "unknown": "0"
      }
    }
  ],
  "by_principal": [
    {
      "accounting_scope": "provider_attempt",
      "principal_ref": "svc/01K7YP2C9W4X5E8H3J6M0N1Q2R",
      "principal_class": "service",
      "email": null,
      "display_name": "billing-app",
      "records": "5",
      "request_count": "5",
      "tool_call_count": "0",
      "quantities": [
        {
          "unit": "input_tokens",
          "amount": "1840"
        },
        {
          "unit": "output_tokens",
          "amount": "3122"
        }
      ],
      "measurement_counts": {
        "measured": "5",
        "estimated": "0",
        "unknown": "0"
      },
      "outcome_counts": {
        "success": "4",
        "error": "1",
        "canceled": "0",
        "unknown": "0"
      }
    }
  ],
  "by_principal_truncated": false,
  "cost": {
    "status": "unavailable"
  },
  "series": [
    {
      "window": {
        "from": "2026-10-12T00:00:00Z",
        "to": "2026-10-13T00:00:00Z"
      },
      "scopes": [
        {
          "accounting_scope": "provider_attempt",
          "records": "3",
          "request_count": "3",
          "tool_call_count": "0",
          "quantities": [
            {
              "unit": "input_tokens",
              "amount": "1000"
            },
            {
              "unit": "output_tokens",
              "amount": "1800"
            }
          ],
          "measurement_counts": {
            "measured": "3",
            "estimated": "0",
            "unknown": "0"
          },
          "outcome_counts": {
            "success": "3",
            "error": "0",
            "canceled": "0",
            "unknown": "0"
          }
        }
      ]
    },
    {
      "window": {
        "from": "2026-10-13T00:00:00Z",
        "to": "2026-10-14T00:00:00Z"
      },
      "scopes": [
        {
          "accounting_scope": "provider_attempt",
          "records": "2",
          "request_count": "2",
          "tool_call_count": "0",
          "quantities": [
            {
              "unit": "input_tokens",
              "amount": "840"
            },
            {
              "unit": "output_tokens",
              "amount": "1322"
            }
          ],
          "measurement_counts": {
            "measured": "2",
            "estimated": "0",
            "unknown": "0"
          },
          "outcome_counts": {
            "success": "1",
            "error": "1",
            "canceled": "0",
            "unknown": "0"
          }
        }
      ]
    }
  ]
}
GET/metering/v1/usage/page

List recent usage for the selected organization

Credential
API key
Permission
Any ofusage.read_ownusage.readsupport-access.read

The organization is derived exclusively from the verified actor context; tenant or organization query parameters are not accepted. Reads occurred_at in a half-open UTC interval and returns a bounded page, in descending occurrence time with deterministic ledger-identity tie breaking.

Read more

The cursor is bound to the organization, frozen window, model filter, accounting-scope filter, principal filter, and API key filter, so a continuation cannot move to another tenant or time range. Counts and quantities preserve exact string values. Unknown or duplicate query parameters, invalid windows, and invalid cursors return 400; a missing selected organization returns 403. An empty window returns records [] and next_cursor null. Optional model_alias, accounting_scope and principal filters (the principal filter takes a principal_ref or an email, like the request-log filter of the same name) apply to the full requested window before aggregation or pagination; filtering never operates on a truncated request page. Requires usage.read_own (at any level) or usage.read. WHICH usage: a caller holding usage.read at organization level (the Administrator role) reads every principal's usage; a caller holding usage.read_own without it - the built-in User role, and a Team Admin, whose usage.read applies to its team's request log and not to this report - reads ONLY the usage whose principal is themselves (a member's own user principal and personal API keys, a service account the usage it made), whatever the request carries: the principal filter is forced to the caller's own reference, so a principal filter naming anyone else, by reference or by email, matches nothing (200 with an empty result, never an error and never a hint of whose usage it is - the request log's narrowing) and by_principal holds only the caller. WITH AN API KEY: these routes answer a service-account API key sent in x-api-key or as Authorization: Bearer, on the console host of the key's own organization and region; a personal API key reaches inference and MCP only and is refused here with 403 policy-denied. A key whose role holds usage.read_own without usage.read reads ONLY the usage made with that key: the facts whose api_key_id is the key's own key_id, not everything its service account made. Whatever the request carries, the read stays bound to that key and to its service account: an api_key_id naming another key (of the same service account or of anyone else) and a principal naming anyone else match nothing (200 with an empty result, never an error), and the key's own id or reference is the same read as no filter. A key whose role holds usage.read at organization level reads the organization's usage exactly as the Administrator role does and may narrow it to one key with api_key_id. Neither level reads another organization: the organization is the key's own and no parameter or header names it. A revoked or expired key is 401 api-key-revoked or api-key-expired, as on every route; an organization with no active subscription is refused with 402 payment-required before any role is checked. For a key reading only its own usage the cursor freezes the key's id and its service account's reference, so a cursor of a read of the organization's usage is refused with 400 invalid-request and a cursor of another key reads nothing. A caller holding neither permission is 403 policy-denied. For a caller reading only their own usage the cursor freezes their own reference as the principal filter, so a cursor minted for a read of everyone's usage (or for anyone else) is refused with 400.

curl
curl "https://console.latam.ccsio.ai/metering/v1/usage/page" \
  -H "Authorization: Bearer $CCSIO_API_KEY"

Parameters

NameInDescription
X-Request-ID
optional
headerstring

Optional request ULID. A valid ULID (upper or lowercase) is honored; when the header is absent or invalid, the runtime mints the id. The response X-Request-ID header carries the canonical uppercase form.

from
optional
querystring

Inclusive UTC RFC 3339 start (must end in Z; fractional seconds allowed). Supply both from and to or omit both for the last 7 days, or the cursor's frozen window when paging. The interval must be positive and at most 90 days.

to
optional
querystring

Exclusive UTC RFC 3339 end (must end in Z; fractional seconds allowed). Required when from is supplied.

model_alias
optional
querystring

Optional exact model reference, preserving case and punctuation. Omit for all models; a valid reference with no matching usage returns empty totals and zero daily buckets.

accounting_scope
optional
querystring

Optional accounting scope. Omit for all scopes, which remain separate in every aggregate; the literal all is not accepted.

principal
optional
queryone of

Optional.

Read more

Narrows every total, daily bucket and breakdown of the response to the usage made by this principal: the principal_ref (a C0 reference) or an email address (it contains '@'), matched case-insensitively against the organization's users and resolved to their refs, exactly as the request-log principal filter does. A reference matches the usage of that principal_ref whatever its principal_class (a member's own sessions and personal API keys share their reference). An email filter follows the visibility rule of the emails themselves: a caller who may not read the organization's member list (members.read at organization level, or a platform administrator) may filter only by their own email, any other address matches no usage; an address that matches no user matches no usage (a 200 with empty scopes, models and by_principal, zero daily buckets or an empty page — not an error — so the filter cannot be used to probe whose address it is). A value that is neither a reference nor a plain email address (no display name, no whitespace, at most 254 bytes) renders 400 invalid-request. On the page read the cursor is bound to the filter as it was typed. The platform operator's summary (platform-usage.read) is not per user: there this filter renders 400 invalid-request. For an API key reading only its own usage, a principal other than its service account's matches no usage.

api_key_id
optional
querystring

Optional. Narrows every total, daily bucket and breakdown of the response (or every record of the page) to the usage made with this API key: the facts whose api_key_id is this value, the key's key_id in the identity API.

Read more

Usage made from a console session carries no key and never matches, and neither does usage recorded before the usage fact carried the key (2026-10-06) nor a tool call through the MCP endpoint. A key that made no usage in the window gives a 200 with empty scopes, models and by_principal, zero daily buckets or an empty page, not an error. A value outside the key id grammar renders 400 invalid-request. On the page read the cursor is bound to the filter. The platform operator's summary (platform-usage.read) is not per user: there this filter renders 400 invalid-request. For an API key whose role holds usage.read_own without usage.read, the read is already bound to that key's own id: its own key_id is the same read as no filter, and any other id (of its service account's other keys too) gives a 200 with an empty result.

operation_class
optional
querystring

Optional. Narrows every total, daily bucket and breakdown of the response (or every record of the page) to one class of usage. `inference` is the usage of models: every fact whose operation is not `tool`. `tool` is the calls of MCP tools: the facts whose operation is `tool`, whose model_alias names the installation and the tool. Without it the read covers both, as before. A page's cursor is bound to it.

limit
optional
queryinteger

Page size: 1 to 100 records, default 50. Anything else renders 400 invalid-request.

cursor
optional
querystring

Opaque next_cursor from the preceding page. Omitted window and filters reuse the cursor's frozen values; explicitly supplied values must match. Version 2 binds model_alias and accounting_scope as well as organization and window. Legacy version-1 cursors are accepted only for unfiltered continuations.

Read more

Changing any filter requires starting without a cursor. A cursor binds the organization, the window and every filter, including api_key_id; for an API key reading only its own usage it also binds the key, so it cannot be used to read another key's records.

Responses

  • 200

    A page of usage evidence for the selected organization.

    Schema
    UsagePageResponse
    • organization_idstringrequired

      pattern ^[a-z][a-z0-9._-]{0,63}$

    • windowobjectrequired
      • fromstring (date-time)required

        pattern Z$

      • tostring (date-time)required

        pattern Z$

    • recordsarray of RecentUsageRecordrequired

      at most 100 items

      • event_idstringrequired

        pattern ^[a-z][a-z0-9._-]{0,127}$

      • occurred_atstring (utc-second)required

        pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$

      • request_idstringrequired

        pattern ^[a-z][a-z0-9._-]{0,127}$

      • model_aliasstringrequired

        Original selected model reference, preserved byte-for-byte under the C0 model registry grammar.

        pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$

      • provider_classanyrequired

        Allowed values: "CCSIO_INFERENCE""CUSTOMER_HOSTED""EXTERNAL_MANAGED"null

      • operationstringrequired

        Allowed values: "chat""embedding""audio""image""document""tool""agent_overhead""responses""decision"

      • accounting_scopestringrequired

        Allowed values: "provider_attempt""platform_overhead""agent_aggregate"

      • measurementstringrequired

        Allowed values: "measured""estimated""unknown"

      • outcome_classstringrequired

        Allowed values: "success""error""canceled""unknown"

      • request_duration_msinteger or nullrequired

        Whole router request timing, shared by all attempt records; absent on legacy records.

        0 to 9007199254740991

      • quantitiesarray of UsageQuantityrequired
      • request_countstringrequired

        An exact non-negative integer serialized as a string to avoid client precision loss.

        pattern ^(0|[1-9][0-9]*)$

      • tool_call_countstringrequired

        An exact non-negative integer serialized as a string to avoid client precision loss.

        pattern ^(0|[1-9][0-9]*)$

    • next_cursorstring or nullrequired

      Opaque continuation cursor bound to the selected organization, frozen window, exact model reference and accounting scope; null when there are no more records.

      at most 2048 characters

  • 400

    Client refusal unrelated to authentication, including malformed input, a denied or failed request.

  • 401

    The request carries no credential, more than one, or one the platform does not accept, and is refused before the operation runs; `error.code` says why. Supply exactly one credential. Codes: invalid-request (no credential, or both Authorization:

    Read more

    Bearer and x-api-key), api-key-invalid (a value that is not a platform API key, or a key of a kind the platform does not accept), api-key-unknown, api-key-revoked, api-key-expired, bootstrap-disabled (the one-shot installation credential, once a key exists), token-malformed (a bearer token that is not a JWT), token-algorithm-unsupported, token-signature-invalid, token-claim-invalid, token-issuer-mismatch, token-audience-mismatch, token-expired, token-not-yet-valid, issuer-untrusted, issuer-residency-mismatch (the issuer belongs to another plane), issuer-resolution-unknown, jwks-unavailable, jwks-key-not-found, staff-token-inactive (a platform operator's token), staff-not-operator, staff-directory-unavailable, identity-not-provisioned (a verified identity with no account on this plane), organization-not-found (a verified identity or key whose organization this plane does not know), internal-error (a fault while the credential is checked is refused too, fail closed), context-cancelled

  • 402

    The organization has to pay first: its standing is payment_required.

    Read more

    The request boundary applies this payment gate to every route except an organization's billing routes, the caller's own context, organization list, onboarding, session report and personal keys, the public routes, and the routes of platform operators, who administer an organization that has to pay. The operations the gate covers declare this response. On /v1 the refusal is rendered in the OpenAI error format. Code: payment-required

  • 403

    The credential is valid but may not do this here; the request is refused by the request boundary before the handler runs, and `error.code` says which refusal. An operation may add codes of its own.

    Read more

    Codes: policy-denied (no role of the caller holds the permission the operation needs, or the credential class may not call it: a personal API key outside inference and MCP, a route that needs a signed-in person, the one-shot installation credential outside its three steps), tenant-mismatch (the organization a path, query, body or X-Tenant header names is not the caller's own), organization-provisioning, organization-suspended, organization-disabled, organization-deleted (the state of the caller's organization), user-disabled, residency-mismatch (the organization lives on another plane), organization-selection-required (a caller with more than one organization, or a platform operator, must name one in X-Organization-Id), organization-not-selectable, no-active-organization-membership, team-not-selectable (the X-Organization-Id or X-Team-Id the caller sent does not name an organization or team it may act in), identity-managed-by-provider (a person who is not a platform operator changes an organization's status, which belongs to the identity provider), support-session-required (a platform operator reads an organization's data without an open support session)

  • 405

    The path is claimed but the request method is not allowed. Go ServeMux returns its standard plain-text response and lists permitted methods in Allow.

  • 500

    Platform failure, rendered without internal cause details.

  • 503

    A dependency the operation needs is not configured on this plane or could not be reached, and nothing was changed. `error.code` names it; an operation lists the ones it can answer besides the boundary's. Retry later. Codes: support-audit-unavailable (the request boundary: an operator's read under an open support session could not be recorded, so nothing was served)

Example response
{
  "organization_id": "acme",
  "window": {
    "from": "2026-10-12T00:00:00Z",
    "to": "2026-10-14T00:00:00Z"
  },
  "records": [
    {
      "event_id": "event.req-01k7yqa2c4e6g8j0m2p4r6t8v0",
      "occurred_at": "2026-10-13T16:41:02Z",
      "request_id": "req-01k7yqa2c4e6g8j0m2p4r6t8v0",
      "model_alias": "gpt-4o",
      "provider_class": "CCSIO_INFERENCE",
      "operation": "chat",
      "accounting_scope": "provider_attempt",
      "quantities": [
        {
          "unit": "input_tokens",
          "amount": "412"
        },
        {
          "unit": "output_tokens",
          "amount": "697"
        }
      ],
      "measurement": "measured",
      "outcome_class": "success",
      "request_duration_ms": 1840,
      "request_count": "1",
      "tool_call_count": "0"
    },
    {
      "event_id": "event.req-01k7yq5v8n3m4p7r2s6t9w0x1y",
      "occurred_at": "2026-10-13T09:14:27Z",
      "request_id": "req-01k7yq5v8n3m4p7r2s6t9w0x1y",
      "model_alias": "embed-1",
      "provider_class": "CCSIO_INFERENCE",
      "operation": "embedding",
      "accounting_scope": "provider_attempt",
      "quantities": [
        {
          "unit": "input_tokens",
          "amount": "320"
        }
      ],
      "measurement": "measured",
      "outcome_class": "success",
      "request_duration_ms": 96,
      "request_count": "1",
      "tool_call_count": "0"
    }
  ],
  "next_cursor": "eyJ2Ijo0LCJ0ZW5hbnQiOiJhY21lIiwid2luZG93Ijp7ImZyb20iOiIyMDI2LTEwLTEyVDAwOjAwOjAwWiIsInRvIjoiMjAyNi0xMC0xNFQwMDowMDowMFoifSwiYWZ0ZXIiOnsiYXQiOiIyMDI2LTEwLTEzVDA5OjE0OjI3WiIsInBsYW5lIjoicGxhbmUuZXUiLCJyZXF1ZXN0IjoicmVxLTAxazd5cTV2OG4zbTRwN3IyczZ0OXcweDF5IiwiYXR0ZW1wdCI6MSwicHJvdmlkZXIiOiJcdTAwM2NudWxsXHUwMDNlIn0sInByaW5jaXBhbCI6InN2Yy8wMUs3WVAyQzlXNFg1RThIM0o2TTBOMVEyUiIsImFwaV9rZXlfaWQiOiIwMUs3WVAzQTVUOFEyTjZSNFYxVzlYWkI3RCJ9"
}

Generated from the platform contracts at commit 5f833620.

Explore the platform

Get your first API key

Registration is open. Four steps to your first call: create your account, create your organization, create your API key, and start using it.

  1. 01Create your account
  2. 02Create your organization
  3. 03Create your API key
  4. 04Start using it