Docs
Status
OverviewQuickstartSetup promptsThe core loopAuthenticationOverviewCoding agentsModelsThe waterfallAdding modelsAnthropic APIErrorsOpenRouter compatibilityIntegrating ExperientialCredits & billingTelemetryAPI reference

Get started

  • Overview
  • Quickstart
  • Setup prompts
  • The core loop
  • Authentication

Guides

  • Overview
  • Coding agents
  • Models
  • The waterfall
  • Adding models
  • Anthropic API
  • Errors

Integrations

  • OpenRouter compatibility
  • Integrating Experiential

Billing & usage

  • Credits & billing
  • Telemetry

Reference

  • API reference
PreviousOpenRouter compatibilityNextCredits & billing

Integrations

Integrating Experiential into your product

For products that wrap Experiential's inference and rebill their own end-users — a coding tool, an agent platform, a vertical SaaS. Route model calls through Experiential, attribute each call to one of your customers, and meter or rebill it.

Base URLs

Two base URLs, both under one host. Everything below uses a normal xpl_ inference key unless it says otherwise.

  • Serving: https://api-pr-1584.preview.experientiallabs.ai/v1 (OpenAI / Anthropic clients). Also served at https://api-pr-1584.preview.experientiallabs.ai/api/v1.
  • OpenRouter-compatible + account/metering: https://api-pr-1584.preview.experientiallabs.ai/api/v1.

If you are simply migrating an existing OpenRouter integration, start with OpenRouter compatibility.

Quickstart

Mint a key and make your first call, then wire the billing sync. The fastest path is to paste a setup prompt into a coding agent — it creates the account from your email and wires the gateway with no browser. Or do it by hand:

  1. Sign in and mint an xpl_ key (see Quickstart), or POST https://api-pr-1584.preview.experientiallabs.ai/api/signup/instant with {"email": "...", "agree": true} to create an account and receive an xpl_ key in the response.
  2. Point an OpenAI-compatible client at https://api-pr-1584.preview.experientiallabs.ai/v1 and call models by their catalog slug (e.g. claude-fable-5.1).
  3. Poll the usage export and push settled cost into your billing system (below).
A new org receives a welcome credit grant at signup, but spending stays locked until the founder proves inbox ownership (verification email) or a card charge settles. Until then GET /v1/models and telemetry work, but a paid completion is refused.

Billing & metering for resellers

The core of a reseller integration is a billing sync job: pull settled per-request cost, map each row to the end-customer it belongs to, and push a usage event into your own billing system.

Getting per-request cost

Three ways to read cost, cheapest-to-wire to most complete:

  • Inline, per response. Read usage.cost (USD) off the response — stamped on every Chat/Responses reply (final usage chunk when streaming), no request flag needed. BYOK rows carry usage.is_byok: true and cost: 0. Good for showing a cost immediately; not a durable feed on its own.
  • One request by id. Every completion response carries an x-request-id header (the gateway request id); pass it to GET /api/v1/generation?id= for cost and token detail. It accepts the bare id or the gen-<request_id> form. (See OpenRouter compatibility.)
  • The settled-usage export (recommended for billing). GET /api/v1/usage is a cursor-paginated feed of settled per-request rows with attribution, real cost, and token counts — the feed a billing sync job should poll.

The usage export

GET /api/v1/usage returns settled rows, newest first, with a keyset cursor:

GET /api/v1/usage
curl "https://api-pr-1584.preview.experientiallabs.ai/api/v1/usage?limit=1000" \
-H "Authorization: Bearer xpl_..."

The response is { "data": [ ... ], "next_cursor": { ... } | null }. Each row in data carries:

FieldMeaning
idThe request id.
created_atSettlement timestamp (ISO 8601).
modelThe model slug.
providerThe winning provider (nullable).
attribution_labelThe safety_identifier / user you set on the request; null when neither was sent.
real_cost_usdAlways-real per-call cost in USD (charged credits + attributed BYOK pass-through). 0 with pricing_known false means “unpriced”, not free.
cost_usdCharged platform-credit cost in USD.
estimated_cost_usdEstimated / attributed cost in USD.
pricing_knownWhether a price was known for the request.
input_tokens · output_tokens · cached_input_tokens · reasoning_tokensToken counts.
statusTerminal status of the request.
api_key_idThe key that made the request (nullable).

Filter by ?attribution_label=<id> (plus optional window, model, api_key_id, status, limit) to pull one end-customer’s requests. When a full page comes back, next_cursor is { cursor_ts, cursor_id, cursor_after }; pass those three values back as the cursor_ts, cursor_id, and cursor_after query params for the next page, and persist them so the next run resumes where you stopped. next_cursor is null on the last page. This is a pull/poll model today; there is no push webhook yet.

Attribute each request to your end-customer

Pass the OpenAI-standard safety_identifier on every request (legacy alias: user). Experiential records it as the request’s attribution label and rolls usage up per end-user — no per-customer key required.

safety_identifier
curl https://api-pr-1584.preview.experientiallabs.ai/v1/chat/completions \
-H "Authorization: Bearer xpl_..." \
-H "Content-Type: application/json" \
-d '{
"model": "claude-fable-5.1",
"messages": [{"role": "user", "content": "..."}],
"safety_identifier": "cust_8842"
}'

The label then appears as attribution_label on the matching /api/v1/usage row, so you can group cost and tokens by your own customer id without running a separate key per customer.

Pipe into your billing system

  1. Poll GET /api/v1/usage on a schedule, resuming from your stored cursor.
  2. Map each row to your end-customer by its attribution_label.
  3. Push a usage event (cost and/or tokens) into your billing system.

The pattern is the same regardless of billing vendor: Metronome, Orb, and Stripe metered billing each take a customer id and a metered quantity, which is exactly what a mapped usage row provides. Because the feed is settled cost, you can rebill at your own margin — bill your customer whatever multiple of real_cost_usd your pricing calls for.

Credits & funding

  • Platform-funded (credits). Your org holds credit balance; each request draws from it and usage.cost / real_cost_usd is the real USD cost. This is the default and what you rebill against.
  • BYOK (bring-your-own-key). A model served through your own provider connection is billed by the provider directly, so Experiential settles cost: 0 (inline is_byok: true, with the upstream charge on cost_details.upstream_inference_cost) and the export row’s real_cost_usdis the attributed pass-through cost. Those rows still carry tokens and attribution, so you can still meter your customers on usage; just don’t expect a platform charge on them.

Provisioning keys

For programmatic key management — minting a key per end-customer or rotating keys — use an opt-in provisioning key rather than your everyday inference key. It is still an ordinary xpl_key; “provisioning” is a capability flag set at creation ("provisioning": true).

  • The first provisioning key comes from the dashboard. The whole /api/v1/keys* family is gated behind a provisioning key — including the GET reads. A signed-in org admin satisfies the same gate, so mint the first one from the dashboard; from then on that key can mint further keys over the API.
  • Use it as the bearer for the key-management routes: POST /api/v1/keys to create (body name, optional daily limit USD cap, and provisioning: true to mint another provisioning key — the plaintext key is returned exactly once), GET /api/v1/keys to list, GET/PATCH/DELETE /api/v1/keys/{hash} to read, update, or revoke. {hash} is the key’s hash field (its uuid id), never the secret.
  • A normal inference key gets a 403 on every /api/v1/keys* route.
  • Keep the provisioning key server-side; never ship it to a client or use it to serve inference traffic.

Key-per-customer is an alternative to safety_identifierattribution: mint a distinct inference key per end-customer, and each customer’s usage is naturally isolated to their key with independent revocation and per-key limits. safety_identifier is simpler (one key, per-request label); you can also combine them.