Metering API reference

Base URL: https://r3ckon.com

The metering API accepts usage metadata and nothing else. It exists so gateways, self-hosted stacks, and internal pipelines can feed the ledger without a managed provider connection.

Authentication

Every request carries a bearer key:

Authorization: Bearer aiok_ingest_…

Keys are account-scoped and role-scoped:

  • aiok_admin_…: full console access plus every API below. This is the key revealed once at signup.
  • aiok_ingest_…: may push usage (both ingest endpoints) but cannot read the console or manage the account.
  • aiok_sdk_…: may push to the SDK feed only.

Only a SHA-256 hash of each key is stored. Rotation is currently by request (info@tahosasystems.com) after billing-email verification.

POST /api/v1/ingest/authoritative

The billing-grade feed: daily (or coarser) aggregates that estimates, retirements, and invoices are computed from.

curl -X POST https://r3ckon.com/api/v1/ingest/authoritative \
  -H "Authorization: Bearer $R3CKON_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [{
      "apiConnection": "anthropic",
      "model": "claude-sonnet-5",
      "region": "us-east-1",
      "inputTokens": 18400000,
      "cachedInputTokens": 12100000,
      "outputTokens": 2300000,
      "reasoningTokens": 410000,
      "serviceTier": "standard",
      "timestamp": "2026-08-04T00:00:00Z"
    }]
  }'

Response: { "accepted": 1 }

Event fields

Field Type Required Notes
model string (1..200) yes The provider's model identifier, verbatim. Unknown models estimate under the registry's most conservative class.
inputTokens integer >= 0 yes The FULL input stream, including any cached portion.
outputTokens integer >= 0 yes Completion tokens.
region string (1..64) yes Cloud region code when known (e.g. us-east-1). Unrecognized values estimate under conservative unknown-facility parameters. A recognized code selects that cloud's published facility profile, which can lower the estimate relative to the unknown default, so report the region truthfully; region values are recorded with the event and are auditable.
timestamp ISO 8601 datetime with offset yes The period the aggregate covers (use the day start for daily buckets).
cachedInputTokens integer >= 0 no The cached SUBSET of inputTokens. Omitted means unreported, not zero.
reasoningTokens integer >= 0 no The reasoning SUBSET of outputTokens, where the provider reports it (never billed twice). Omitted means unreported; for reasoning-class models that triggers the methodology's conservative hidden-reasoning multiplier.
serviceTier standard | batch | priority no Batch and priority tiers carry their own energy multipliers.
apiConnection string (1..64) no Which source produced this usage; groups the console's per-API filters. Accounts support up to 50 distinct connections.
endUserPseudoId string (<=128) no An opaque pseudonymous id if you segment end users. Never send anything identifying.

The content boundary (HTTP 422)

Every payload is deep-scanned before parsing. If any key anywhere in the JSON matches a content-shaped name (prompt, completion, content, messages, message, text, input, output, system, body, response, query, answer, transcript), the request is rejected with 422 and nothing is stored:

{ "error": "Ingest rejected: payload contains content-shaped key \"prompt\". This platform is metadata-only and must never receive prompt or completion content." }

This is an architectural invariant, enforced by tests, not a policy.

Idempotency and re-submission

Managed connections replace their (connection, window) slice atomically on every sync. For your own pushes, the same practice applies: if you need to restate a day, re-push the whole day's aggregates for that apiConnection after deleting nothing; duplicate submission of the same window will double-count, so push each window once or contact us to reset a window.

Errors

Status Meaning
400 Malformed JSON, missing events array, or field validation failure (message says which).
401 Missing or unknown bearer key, or a role without ingest rights.
422 Content boundary violation (see above).

POST /api/v1/usage-events

The SDK feed: identical body and validation, accepted from sdk, ingest, or admin keys. It powers live views and is never billed from; billing and retirement always come from the authoritative feed.

Account APIs

The console is built on account-scoped APIs authenticated with your aiok_admin_… key. The stable, supported surface today:

  • GET /api/admin/overview: everything the dashboard shows, as JSON: monthly footprint with P05/P50/P90/P95 per category, retirements, credit position, invoices, certificates, connections, filters.
  • GET /api/admin/connections / POST (create) / DELETE /api/admin/connections/{id} / POST /api/admin/connections/{id}/sync with { "periodStart": "YYYY-MM-DD", "periodEnd": "YYYY-MM-DD" }.
  • GET /api/admin/certificates/{id}/pdf: the certificate PDF.
  • GET /api/admin/exports/{name}: reporting CSVs (water restoration summary, CDP Water and ESRS E3 inputs).
  • POST /api/admin/billing-portal: a Stripe customer portal session URL.

These return JSON errors in the same { "error": "…" } shape. Endpoints not listed here (reconcile, seeding) are operator-only and may change.

Machine-readable: this page as markdown, the whole product as llms-full.txt.

Next: what it costs

See pricing