Skip to content
Radient LogoRadient Documentation

Usage and credits API

Everything that happens on your Radient account is metered in credits. 1 credit = $1, credits are deducted at the model's own cost with no markup at inference, and you can read every movement back from the API.

Two credential rules shape this surface:

  • Usage summaries (GET /v1/usage) accept an API key or a user token.
  • Every other route on this page — organization usage, billing, ledger, auto-reload, transfers and billing sources — requires a user token. An API key gets 401 {"error":"invalid or expired token"}.

#Account usage summary — GET /v1/usage

Returns the calling account's totals. Optional start_time and end_time (RFC 3339) bound the window; a malformed value answers 400 {"error":"Invalid start_time format"}.

bash
curl "https://api.radienthq.com/v1/usage" \
  -H "Authorization: Bearer $RADIENT_API_KEY"
json
{
  "total_requests": 31,
  "successful_requests": 23,
  "failed_requests": 8,
  "total_tokens": 1591,
  "prompt_tokens": 1464,
  "completion_tokens": 127,
  "total_cost": 0.034583562799999995,
  "average_latency_ms": 653,
  "model_breakdown": [
    { "model": "…", "request_count": 8, "total_tokens": 344, "prompt_tokens": 190, "completion_tokens": 127, "total_cost": 0.000334 }
  ],
  "endpoint_breakdown": [
    { "endpoint": "chat/completions", "request_count": 8, "total_tokens": 344, "total_cost": 0.000334 }
  ]
}

(model_breakdown is trimmed.) total_cost is in USD — the amount deducted from your balance across requests in the window, including tools and media.

#Organization usage — GET /v1/tenants/{tenant_id}/usage

The paginated, per-request view for a tenant, for organizations and their members. Query parameters: page, per_page (default 50, max 200), start_date, end_date (RFC 3339), sort, direction (asc/desc), cursor.

The tenant in the path must be the one your token belongs to, or you get 403 {"error":"Tenant ID in path does not match JWT"}.

json
{
  "msg": "Usage records retrieved",
  "result": {
    "page": 1, "per_page": 2, "total_pages": 16, "total_records": 31,
    "records": [
      {
        "id": "…", "timestamp": "2026-10-09T16:46:10.046Z",
        "account_id": "…", "tenant_id": "…",
        "usage_type": "inference", "model": "…", "provider": "…",
        "prompt_tokens": 315, "completion_tokens": 0, "total_tokens": 315,
        "units": 0, "cost": 0.00001323, "latency": 233, "success": true,
        "endpoint": "decisions",
        "billing_account_id": "…", "billing_source_tenant_id": "…", "billing_source_kind": "own"
      }
    ]
  }
}

Each record carries: usage_type (inference or tool), model, provider (the serving endpoint), token counts, units, cost in USD, latency (ms), success / error_type, endpoint, and — when a team pool pays — billing_account_id with billing_source_tenant_id and billing_source_kind (own or team), so pooled spend is attributable.

#Usage rollup — GET /v1/tenants/{tenant_id}/usage/rollup

Aggregates the same data. rollup is required and must be daily, monthly or annual — anything else answers 400 {"error":"Invalid rollup value (must be 'daily', 'monthly', or 'annual')"}. Optional start_date, end_date, application_id, usage_type, provider.

json
{
  "msg": "Usage rollup data retrieved",
  "result": { "data_points": [
    { "timestamp": "2026-10-09T16:46:10.046Z", "total_requests": 31, "total_tokens": 1591,
      "prompt_tokens": 1464, "completion_tokens": 127, "units": 56,
      "total_cost": 0.0345835628, "success_count": 23, "failure_count": 8 }
  ] }
}

#Team usage — GET /v1/tenants/{tenant_id}/usage/team

For organizations: team-wide totals broken down per member, readable by any active member of a tenant whose Team plan is entitled (no plan → 403 {"code":"team_plan_required",…}). Query: start_date, end_date, rollup (default daily), members (up to 5 comma-separated account ids).

json
{
  "msg": "Team usage retrieved",
  "result": {
    "window": { "start": null, "end": null },
    "rollup": "daily",
    "tenant_id": "…",
    "viewer": { "account_id": "…", "role": "owner" },
    "totals": { "total_requests": 61, "total_tokens": 6998, "total_cost": 0.469030485 },
    "members": [ { "account_id": "…", "name": "…", "email": "…", "role": "owner", "status": "active", "in_roster": true, "is_viewer": true, "totals": { "…": "…" } } ],
    "series": { "team": [ "…" ], "viewer": [ "…" ], "others": [ "…" ], "members": {} }
  }
}

#Balance and ledger

  • GET /v1/tenants/{tenant_id}/billing/credits → {"msg":"Credit balance retrieved","result":{"balance": 4.9962311112}}
  • GET /v1/tenants/{tenant_id}/billing/ledger?page=&per_page= (per page max 200) → paginated entries:
json
{ "id": "…", "billing_account_id": "…", "type": "debit", "amount": 0.00001323,
  "balance": 4.965416437200002, "description": "Inference usage: … model, 315 tokens",
  "reference_id": "…", "created_at": "2026-10-09T16:46:10.057Z" }

type is credit or debit; source (where present) is one of purchase, registration_bonus, signup_grant, admin, transfer_escrow, transfer_release, transfer_return. Both routes require the path tenant to be your own — a mismatch answers 403 {"error":"tenant ID in path does not match authenticated tenant"}.

  • GET /v1/tenants/{tenant_id}/billing shows the billing account behind the balance: status, credits, giftable_credits, held_credits (credits escrowed in pending transfers), has_been_funded, member_spend_effective and member_spend_source (see Team pooling).
  • PATCH /v1/tenants/{tenant_id}/billing lets an owner or admin set billing_emails (up to 10 addresses) and member_spend_enabled.
  • GET /v1/prices (no auth) returns the current promotional credit amounts: {"msg":"Prices retrieved","result":{"default_new_credits":5,"default_registration_credits":10}}.

#Auto-reload

Top up automatically when the balance drops.

RoutePurpose
GET /v1/tenants/{tenant_id}/billing/auto-reloadCurrent settings
PUT /v1/tenants/{tenant_id}/billing/auto-reloadReplace the settings wholesale
POST /v1/tenants/{tenant_id}/billing/auto-reload/chargeAttempt a charge now

PUT is a full replace and refuses unknown fields:

json
{
  "auto_reload": { "enabled": true, "threshold_usd": 2, "amount_credits": 10, "payment_method_id": "pm_…" },
  "alerts": { "enabled": true, "warn_threshold_usd": 2, "rearm_threshold_usd": 3 }
}

Limits and defaults: amount_credits is a whole number between 5 and 10,000; threshold_usd between 0.01 and 10,000; defaults are $2.00 / 10 credits. The charge worker has a 10-minute cooldown between attempts.

GET answers with configured plus the current settings and their state (state, last_charged_at, last_error, disabled_reason, in_flight_started_at). Coded errors include 400 payment_method_required / payment_method_not_found, 409 auto_reload_busy / auto_reload_disabled, and 503 auto_reload_unconfigured — the last one means billing automation is not configured on the deployment.

#Credit transfers and gifting

Send credits to another Radient user as a gift or a plain transfer. The sender's balance is debited (escrowed) at creation.

POST /v1/tenants/{tenant_id}/billing/transfers, with an Idempotency-Key header required — 16 to 128 characters of A-Z a-z 0-9 _ -:

bash
curl https://api.radienthq.com/v1/tenants/{tenant_id}/billing/transfers \
  -H "Authorization: Bearer $RADIENT_USER_TOKEN" \
  -H "Idempotency-Key: radient-docs-gift-0001" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 1,
    "recipient_email": "[email protected]",
    "kind": "gift",
    "reason": "thanks",
    "message": "Thanks!"
  }'
FieldRules
amount≥ $0.01, rounded half-up to 2 decimals before the debit
recipient_emailThe recipient's Radient account email — or any address, which receives an invitation
kindgift or transfer
reasonGift only: thanks, welcome or congrats. Sending it on a transfer → 422
messageGift only, up to 280 characters

Responses: 201 on creation, 200 when the same Idempotency-Key replays the same request (same key, different body → 409 idempotency_key_reused; no key → 400 idempotency_key_required).

What can be gifted: credits you purchased, and credits received through transfers. Promotional credits (registration_bonus, signup_grant) and operator-granted (admin) credits are not giftable — attempting to gift them answers 422 {"code":"transfer_insufficient_giftable","error":"granted credits can no longer be transferred",…}. A total balance that cannot cover the amount answers 422 transfer_insufficient_credits.

Lifecycle: pending → accepted, declined, revoked, or expired (30 days). Sender routes: GET /v1/tenants/{tenant_id}/billing/transfers (list, filters status, page, per_page), DELETE …/transfers/{transfer_id} (revoke a pending transfer — returns the escrow; 409 transfer_not_pending otherwise), POST …/transfers/{transfer_id}/resend (rotates the invitation token; rate-limited, one resend per 12 hours).

Recipient routes (user token; your verified email must match, else 403 email_mismatch):

  • GET /v1/transfers, GET /v1/transfers/{transfer_id} — a transfer that is not yours answers 404 transfer_not_found
  • POST /v1/transfers/{transfer_id}/accept — accepting is idempotent; the credits land in your balance
  • POST /v1/transfers/{transfer_id}/decline

Invitations (recipient without an account yet): GET /v1/transfer-invites/{token} (anonymous, rate-limited) previews a masked summary, and POST /v1/transfer-invites/{token}/attach (user token) binds the invitation to your account — no money moves; the transfer is still accepted separately.

#Team pooling (billing sources)

On a Team plan, an organization's balance becomes a payer for its members. The billing-sources API shows which balances can pay for your calls and lets you pin a preference.

  • GET /v1/me/billing-sources → the caller's sources:
json
{ "msg": "Billing sources retrieved", "result": { "sources": [
    { "billing_account_id": "…", "tenant_id": "…", "tenant_name": "…", "kind": "own",
      "role": "owner", "is_home": true, "available": true, "selected": false, "credits": { "balance": 0 } },
    { "billing_account_id": "…", "tenant_id": "…", "tenant_name": "…", "kind": "team",
      "role": "member", "is_home": false, "available": true, "selected": false,
      "member_spend_enabled": true, "member_spend_source": "default", "credits": { "balance": 4.531 } }
  ], "selection": null, "selection_required": true } }

member_spend_enabled is the organization's decision to let members draw on its balance, and member_spend_source records whether that is an explicit setting (explicit) or derived from the plan (default).

  • PUT /v1/me/billing-source — {"mode":"automatic"} or {"mode":"pinned","billing_account_id":"…"}. Pinning a source that could not currently pay answers 400 {"code":"invalid_billing_source",…}.
  • GET /v1/me/billing-sources/usage — consumption broken down by payer; GET /v1/me/billing-sources/capacity — balances, held escrow and total.

Order of charging: a token minted by the OAuth code exchange pools the team first, then your own account; every other token and all API keys charge your own account first, then any team. A still-applicable pinned source goes first. Fall-through to the next source happens only for insufficient credits — an own account that is missing or inactive refuses outright rather than charging a team.

See Team plan for exactly what happens to pooled spend when a plan is cancelled or downgraded, and the credit gate for how admission works.