Authenticate with an API key

How a request says who it is — the API key, the one project the key acts in, and the scopes that say what it may do.

3 min read

Every request to the API carries an API key. The key says which project the request acts in and what it may do there.

The key

Send the key in the Authorization header, after the word Bearer.

HTTP
Authorization: Bearer sl_live_…

A key starts with sl_live_. A key issued before the prefix became sl_live_ starts with sg_live_ and keeps working. You see it once, when it is issued or rotated, because Slen stores only a hash of it. Keys are issued on the keys page — Manage API keys walks through it.

Keep the key where your server keeps its secrets. Do not put it into code that runs in a browser or on a customer's device.

The examples of this reference read the key from the SLEN_API_KEY environment variable.

Terminal
curl https://api.slen.ai/api/v1/models \
  -H "Authorization: Bearer $SLEN_API_KEY"
200 OK
{
  "data": [
    {
      "model_code": "gpt-4o-mini",
      "provider": "openai",
      "model_price_id": "1108",
      "input_price_per_million": "0.15000000",
      "output_price_per_million": "0.60000000",
      "cached_input_price_per_million": "0.07500000",
      "max_output_tokens": 16384,
      "currency": "USD",
      "effective_from": "2026-01-01T00:00:00+00:00",
      "effective_to": null
    }
  ]
}

The two probes, /health and /ready, are the only paths that take no key.

What a key reaches

A key belongs to one project of one organization, and it acts in that project only.

  • What the key creates is created in its project. A list answers with the rows of its project.

  • A row of another project, or of another organization, answers 404 — exactly as a row that does not exist.

  • What an organization shares between its projects can be read with the key and cannot be changed with it. An attempt answers 403 with the code project_access_restricted.

A service that works with two projects needs two keys.

Scopes

A key carries one or more scopes. Every operation that takes a key requires one scope, and the page of a resource names it for each operation.

ScopeAlso grants
read—
gateway:writeread
management:readcustomers:read
management:writemanagement:read, flows:write, customers:read, customers:write
flows:writemanagement:read, customers:read
customers:read—
customers:writecustomers:read
ScopeWhat it is for
readRead what the project did — operations, executions, authorizations, the ledger, analytics, the model catalogue
gateway:writeSend requests that may spend — run a flow
management:readRead the configuration — flows, provider connections and pools, customers and their credits
management:writeChange the configuration and the budgets, top up and adjust customers' credits, approve or reject what waits for a decision
flows:writeCreate, edit and publish flows
customers:readRead your customers, their credit accounts and statements, and the credit prices
customers:writeCreate, top up, charge, adjust, block and delete your customers, and change the settings of their accounts

Some scopes include others, and the first table lists everything each one includes. management:write includes management:read, flows:write, customers:write and customers:read. It does not include read, so a key that carries management:write alone cannot call an operation that requires read.

Give a key the scopes its service needs and no more. A service that only sends requests needs gateway:write. An application that also keeps its customers — adds them, tops them up, charges and blocks them — needs gateway:write and customers:write, and changes nothing else with them.

When a request is refused

  • 401 with the code invalid_api_key — the request has no key, the key does not exist, or it was revoked. A rotated key answers the same to its old secret.

  • 403 with the code insufficient_scope — the key is valid and does not carry the scope the operation requires. error.message names the missing scope.

  • 403 with the code project_access_restricted — the key tried to change something that belongs to the whole organization.

The envelope of an error is described in Overview, and every code in Error codes.

Built from openapi b070e1f, sdk contract 6a2e0e0, php 4089db3, node 0fa87be