sablenetwork
Documentation — all sections

API key controls

When you mint a key you can scope it: cap its monthly spend, restrict it to a set of models, and give it an expiry. These are enforced on every inference call. A key created without any of them behaves exactly as it always has — unlimited, all models, no expiry.

Creating a scoped key

POST /v1/keys accepts these optional fields alongside name:

curl https://api.buildsable.com/v1/keys \
-H "Authorization: Bearer $SABLE_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
  "name": "trading-agent-prod",
  "spend_limit_usd": 50,
  "allowed_models": ["sable-llama-3.3-70b", "sable-deepseek-v3"],
  "expires_in_days": 90
}'

The plaintext key is returned exactly once at creation — store it immediately. See Authentication.

Enforcement

The controls are checked at inference time on /v1/chat/completions and /v1/embeddings:

| Condition | Status | Error type | | --- | --- | --- | | Monthly spend would exceed spend_limit_usd | 402 | spend_limit_exceeded | | Requested model not in allowed_models | 403 | scope_denied | | Call made after the key's expiry | 401 | — |

Spend is measured against the same metered cost that appears in each receipt and rolls up in usage, so a key's cap and your account totals always agree.

# HTTP 402 Payment Required
{
"error": {
  "type": "spend_limit_exceeded",
  "message": "monthly spend limit reached for this key"
}
}

The spend cap is a monthly window. A key that hits its limit resumes at the start of the next month; revoke and re-mint if you need it sooner, or raise the cap on a fresh key. Expiry is one-way — an expired key returns 401 and can't be reactivated.