Integrations
Authenticate with one xpl_ key, inspect what a key can spend, and provision keys programmatically — mint one per end-customer, rotate on a schedule, or cap a key's daily spend, all over the API.
The account and key-management routes answer under one host at https://api-pr-1743.preview.experientiallabs.ai/api/v1. New to the surface? Start with Integrate the gateway.
There are two kinds of key: an inference key and a provisioning key. Both are ordinary xpl_keys — “provisioning” is a capability flag on the key (is_provisioning), not a different prefix or a separate account. You set it when you mint the key ("provisioning": true on POST /api/v1/keys); a key without it is a normal inference key.
/credits, /key, /generation, /activity, /usage, GET /models, GET /providers — see the Cost API).GET/POST/PATCH/DELETE /keys). Every /api/v1/keys* route — including the GET reads — is gated behind it; a normal inference key gets a 403 on all of them.For the everyday xpl_ key mechanics — how it looks, the Bearer header, and what one key can and cannot do — see Authentication.
POST /api/v1/keys. Keep the provisioning key server-side; do not use it as your day-to-day inference key.GET /api/v1/key returns usage/limit metadata for the key in the Authorization header. usage, limit, and limit_remaining are real — the cap is a daily one, so limit_remainingis measured against today’s spend. This read requires an xpl_ key credential (it reports on the presented key itself).
The {hash} path segment is the key’s hash field (the row’s uuid id, as returned by list/create), never the secret.
| Route | Notes |
|---|---|
| GET /api/v1/keys | List keys ({data:[...]}); revoked hidden unless ?include_disabled=true. |
| POST /api/v1/keys | Create a key; returns {data, key:"xpl_..."} — the plaintext once. Body: name (required), limit (daily USD cap), provisioning (bool). |
| GET /api/v1/keys/{hash} | Read one key. |
| PATCH /api/v1/keys/{hash} | Update name / disabled / limit. disabled:true revokes (terminal). |
| DELETE /api/v1/keys/{hash} | Revoke one key; returns {data:{success:true}}. |
# Requires a provisioning key as the bearer.curl https://api-pr-1743.preview.experientiallabs.ai/api/v1/keys \-H "Authorization: Bearer xpl_...provisioning..." \-H "Content-Type: application/json" \-d '{"name": "cust_8842","limit": 25,"provisioning": false}'
On the key list/CRUD object, usage and limit_remaining are intentionally null today (there is no cheap per-key lifetime-spend reader for a list; a fabricated 0 would mislead). Real per-key spend lives on GET /api/v1/key (the presented key) and GET /api/v1/usage (filter by api_key_id, on the Cost API). This is a documented follow-up, not a permanent gap.
A key per end-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 daily limits. safety_identifier is simpler (one key, per-request label, on the Cost API); you can also combine them.
403 on every /api/v1/keys* route.