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

Request logs

One row per request an organization made. What a caller sees depends on the usage permission it holds.

Documentation menu

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

GET/metering/v1/organizations/{org}/request-logs

List an organization's request logs

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

Pages the organization's requests newest first, one row per request (the attempts of a request are aggregated: the final attempt's status and deployment, the whole-request duration and time to first token, tokens and quantities summed over every attempt, the attempt count, and measurement and measurement_reason, the worst of the attempts: unknown over estimated over measured, so a request whose provider reported no usage is told apart from one that used nothing).

Read more

Reads the request's occurred_at in a half-open UTC window of at most 90 days (default the last 7 days) and returns a bounded page (default 50, at most 500) keyset-paginated by an opaque cursor bound to the organization, the frozen window and every filter. Requires usage.read_own (at any level) or usage.read. WHICH requests: a caller holding usage.read at organization level (the Administrator role) sees every request of the organization; a caller holding usage.read only through a team-level role binding sees the requests of those teams; and a caller holding usage.read_own sees the requests whose principal is themselves (a member sees the requests made as their own user principal and with their personal API keys, a service account the ones it made), whatever filters they send. Filters only narrow what the caller may already see. WHO: each request names its end user with the principal's email and display name, resolved when the page is read (one directory lookup per page) and served under the visibility rule stated on RequestLogEndUser; the principal filter also accepts an email. A request appears once its final attempt has been ingested. Requests the platform refused before they reached the router (an unknown model, an entitlement refusal, a malformed header) produce no usage fact and are not listed. Reads are not sensitive and record nothing. Only a role that holds the permission opens it: the resource grants of earlier versions no longer exist and never open the log.

curl
curl "https://console.eu.ccsio.ai/metering/v1/organizations/{org}/request-logs" \
  -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.

org
required
pathstring

The organization whose request logs are read (C7 identifier). It must be the caller's own organization (403 tenant-mismatch otherwise).

from
optional
querystring

Inclusive UTC RFC 3339 start of the window on the request's occurred_at (must end in Z; fractional seconds allowed). Supply both from and to, or omit both for the last 7 days (or, when paging, the cursor's frozen window). The interval must be positive and at most 90 days; anything else renders 400 invalid-time-range, a malformed instant 400 invalid-request.

to
optional
querystring

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

model
optional
querystring

Optional exact model reference (C0 registry grammar). A value outside the grammar renders 400 invalid-filter.

principal
optional
queryone of

Optional. Narrows to requests made by this principal: the end user's principal_ref (a C0 reference) or an email address (it contains '@'), matched case-insensitively against the organization's users and resolved to their refs. It narrows the caller's own visibility; it never widens it.

Read more

An email filter follows the visibility rule of the emails themselves: a caller who may not read the organization's member list may filter only by their own email, any other address matches no request; an address that matches no user matches no request (an empty page, not an error). A value that is neither a reference nor a plain email address (no display name, no whitespace, at most 254 bytes) renders 400 invalid-filter.

team
optional
querystring

Optional. Narrows to requests made on behalf of this team (C7 identifier). A value outside the pattern renders 400 invalid-filter.

session
optional
querystring

Optional. Narrows to the requests that carried this client-provided session id (the X-Session-Id header). A value outside the grammar renders 400 invalid-filter.

api_key_id
optional
querystring

Optional. Narrows to the requests made with this API key (its key_id). It narrows within what the caller may see and never widens it: a member who reads only their own requests gets their own requests made with that key, and a key that made none of the visible requests gives an empty page. A value outside the key id grammar renders 400 invalid-filter.

operation
optional
querystring

Optional. Narrows to one request type (the C2 operation). Anything else renders 400 invalid-filter.

status
optional
querystring

Optional. Narrows by the request's result: an outcome (success, error, canceled, unknown), an exact HTTP status (for example 429) or an HTTP status class (2xx, 4xx, 5xx). Anything else renders 400 invalid-filter.

cursor
optional
querystring

Optional. The opaque next_cursor of a previous page (given at most once). The cursor is bound to the organization, the frozen window and every filter: omitted window and filters reuse the cursor's frozen values, explicitly supplied ones must match, and changing any filter requires starting without a cursor. A malformed or foreign cursor renders 400 invalid-cursor.

limit
optional
queryinteger

Optional page size, default 50, 1..500. A non-integer renders 400 invalid-request, a value outside 1..500 renders 400 invalid-filter.

Responses

  • 200

    A page of request logs and the cursor for the next page.

    Schema
    RequestLogListResponse
    • organization_idstringrequired

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

    • windowobjectrequired
      • fromstring (date-time)required

        pattern Z$

      • tostring (date-time)required

        pattern Z$

    • request_logsarray of RequestLogrequired

      Newest first by (occurred_at, request identity).

      at most 500 items

      • request_idstringrequired

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

      • occurred_atstring (utc-second)required

        When the request concluded: the occurred_at of its final attempt. The list is ordered by it, newest first.

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

      • operationstringrequired

        The request type.

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

      • http_statusinteger or nullrequired

        The HTTP status the router answered for the request (see C2 http_status); null on records written before the field existed.

        100 to 599

      • outcomestringrequired

        The outcome class of the request's final attempt.

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

      • error_codestring or nullrequired

        The stable error code returned for the request (see C2 error_code); null when it succeeded and on records written before the field existed.

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

      • session_idstring or nullrequired

        The client-provided X-Session-Id label; null when the client sent none. A label, never an identity.

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

      • api_key_idstring or nullrequired

        The id of the API key the request was made with (its key_id in the identity API), or null for a request made without one, such as a console session, and for every request recorded before the platform kept it. The key's name is read from the identity API.

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

      • duration_msinteger or nullrequired

        Whole-request duration as measured by the router (every attempt included); null on records written before request timing existed and no attempt timing either.

        0 to 9007199254740991

      • ttft_msinteger or nullrequired

        Time to the first output the client received; null when no output was produced (a refusal, an error before the first byte, a non-streaming failure).

        0 to 9007199254740991

      • tokensobjectrequired

        Whole token counts summed over the request's provider attempts (a failed attempt that reported nothing adds nothing). A member is null when no attempt of the request carried that count (a refusal, an audio request, an attempt whose usage was never reported); total is the sum of the members that are present, null when both are null.

        • inputinteger or nullrequired

          Input (prompt) tokens.

          0 to 9007199254740991

        • outputinteger or nullrequired

          Output (completion) tokens.

          0 to 9007199254740991

        • totalinteger or nullrequired

          input + output over the members that are present.

          0 to 9007199254740991

      • measurementstringoptional

        How far tokens and quantities can be trusted, read from the ledger facts of the request's attempts. measured: every attempt reported its usage. estimated: at least one attempt's count is an estimate and none is unknown. unknown: at least one attempt has no usable usage (the model server reported none, or a counter that is absent or not a whole number; the client left before it was reported; the request was refused before any provider was called; or the fact lost its count); tokens and quantities then count only what the other attempts reported, and may be null or smaller than what was used. A caller's own answer shows 0 for a count that was not reported, because the OpenAI SDKs require integers: this member is where the difference is told. A row that groups several attempts takes the worst of them, unknown over estimated over measured. Optional to read: a server that predates the member omits it.

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

      • measurement_reasonstring or nulloptional

        Why measurement is not measured, taken from the attempt that decided it (of several equally bad attempts, the latest). estimated: coarse_counter (the provider's counter is coarser than a token) or provider_estimate (the provider says its count is an estimate). unknown: final_usage_missing (the model server sent no usable usage, the counters absent or malformed included), meter_loss (the count was lost between the router and the ledger), canceled (the client left, or the request was refused before any provider was called), implausible_count (the model server reported a count beyond what the platform accepts). null when measurement is measured. Optional to read: a server that predates the member omits it.

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

      • quantitiesarray of UsageQuantityrequired

        Every metered unit summed over the request's attempts (tokens, for audio input_characters or audio_seconds, and for image generation images); exact decimal strings.

      • end_userobjectrequired

        The authenticated principal the request ran as. An API key authenticates as principal_class service even when it is a member's personal key (principal_ref is then that member's own reference). email and display_name are the human-readable identity of that principal, resolved when the page is read (never stored with the request): in ONE lookup per page over the page's distinct principals, bounded to the organization's users (a user who is, or ever was, a member of it). They are the caller's own always; another user's are served only to a caller who may read the organization's member list (members.read at organization level, or a platform administrator) and are null otherwise, and null for a principal the organization's directory does not know (a deleted user, a service the organization has no user record for). principal_ref stays the authoritative identifier.

        • principal_refstringrequired

          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, resolved at read time; null under the same conditions as email and when the user has none.

          at most 128 characters

      • team_idstring or nullrequired

        The team the request ran under, when it carried one.

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

      • modelstringrequired

        The model reference the client selected.

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

      • deployment_idstring or nullrequired

        The deployment of the final attempt; null for a request refused before dispatch.

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

      • provider_classanyrequired

        The provider class of the final attempt; null for a request refused before dispatch.

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

      • attemptsintegerrequired

        The number of provider attempts the request made (failover and retries included); 0 for a request refused before dispatch.

        at least 0

    • next_cursorstring or nullrequired

      Pass as the cursor query parameter for the next page; null on the last page.

      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-08T00:00:00Z",
    "to": "2026-10-15T00:00:00Z"
  },
  "request_logs": [
    {
      "request_id": "req-01k7yqa2c4e6g8j0m2p4r6t8v0",
      "occurred_at": "2026-10-14T16:41:02Z",
      "operation": "chat",
      "http_status": 200,
      "outcome": "success",
      "error_code": null,
      "session_id": "sess-7f3a",
      "api_key_id": "01K7YQ4D8M2P6S9V3X5Z7B1C4F",
      "duration_ms": 1840,
      "ttft_ms": 212,
      "tokens": {
        "input": 412,
        "output": 697,
        "total": 1109
      },
      "measurement": "measured",
      "measurement_reason": null,
      "quantities": [
        {
          "unit": "input_tokens",
          "amount": "412"
        },
        {
          "unit": "output_tokens",
          "amount": "697"
        }
      ],
      "end_user": {
        "principal_ref": "svc/01K7YP2C9W4X5E8H3J6M0N1Q2R",
        "principal_class": "service",
        "email": null,
        "display_name": "billing-app"
      },
      "team_id": "platform",
      "model": "glm-5.3",
      "deployment_id": "dep-glm-eu-1",
      "provider_class": "CCSIO_INFERENCE",
      "attempts": 1
    },
    {
      "request_id": "req-01k7yq9z8x6v4t2r0p8n6m4k2j",
      "occurred_at": "2026-10-14T15:03:55Z",
      "operation": "chat",
      "http_status": 503,
      "outcome": "error",
      "error_code": "provider-unavailable",
      "session_id": null,
      "api_key_id": null,
      "duration_ms": 30211,
      "ttft_ms": null,
      "tokens": {
        "input": null,
        "output": null,
        "total": null
      },
      "measurement": "unknown",
      "measurement_reason": "final_usage_missing",
      "quantities": [],
      "end_user": {
        "principal_ref": "user/onboard/01K7YN1B3C5D7F9H2K4M6P8R0T",
        "principal_class": "user",
        "email": "[email protected]",
        "display_name": "Ana García"
      },
      "team_id": null,
      "model": "glm-5.3",
      "deployment_id": "dep-glm-eu-1",
      "provider_class": "CCSIO_INFERENCE",
      "attempts": 3
    }
  ],
  "next_cursor": null
}

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