API keys
An API key lets your code do what you do in the console — create, update and delete records, add fields, use the rest of the API — without a person signing in.
Give every program its own key — a read-only one for your website’s search box, a full one for your import script — so you can see which program did what, and delete one without disturbing the others.
What an API key is for
An API key lets your code do what you do in the console — create, update and delete records over the API. Keys live under Developers → API Keys, each showing its scope and region. Give each integration its own key so you can see who’s doing what and revoke one without disturbing the others.

Scope it and route its region
Name the key, then choose its scope — the whole account, a single group, or a single list. An account key defaults to your home region; the Region dropdown routes its requests to the right regional API. Optionally set an expiry and pick permissions — leave them empty for full access, or tick just what the integration needs.

A read-only key for a browser embed
For a browser embed, scope the key to one list and hit the Search only preset — read-only, that list and nothing else. A list- or group-scoped key takes its region automatically. Click Create and the secret is shown once — copy it now. Leaked or rotating? Delete it (revocation is immediate) and only that one integration needs a new value.

Auto-plays · use Back / Next to step through at your own pace.
Create a key
- Go to Developers → API Keys and click Create API Key.
- Give it a name that says what it’s for:
ci-deploy,catalogue-sync. - Pick its scope (whole account, one list, one group) and its access, which starts at Search and read. Under Advanced, set an expiry date and pick individual permissions.
- Click Create. The secret is shown once — copy it now. It is never shown again.
Scope: account, list or group
Two separate settings: scope is where a key reaches, permissions are what it can do there.
| Scope | Reaches |
|---|---|
| Whole account (default) | Every list and group, like your console session. Right for back-office tools and build jobs. |
| A single list | One list only — never another list, any group, or your account settings. |
| A single group | One group and the lists in it. |
A key for a web page (autocomplete, public search box) should be list-scoped and read-only: site-search over your products list, Search and read access.
- It sits in your page’s JavaScript for anyone to read, so scope is the protection: another list name in the URL returns
403. - Scope does not hide records inside that list — a read key can page through every one, so only embed over a list you would publish whole.
- No key can be limited to part of a list. For per-visitor records, query from your own server and filter there.
Scope also sets the region prefix (ssk_us_…), routing requests to that region’s servers. List- and group-scoped keys take the region from the list or group; a whole-account key defaults to your account’s home region, changeable in the Region dropdown (the regions with an API deployment). Region picks the nearest servers only: an account key works everywhere, so a “wrong” choice costs a slower round trip, not a broken key.
Access: just what it needs
Give a key only the operations its program performs. Access offers three ready-made settings and starts on the narrowest.
| Access | Can do |
|---|---|
| Search and read (default) | Search your lists and groups and read their records, paging through every record in scope. The key for a website or app. |
| Read all | View everything (lists, results, facets, models, services); create, edit and delete nothing. |
| Full access | Every operation, including deleting data. Fine for a trusted back-office tool, risky for anything the public can reach — treat the secret like a password. |
For anything in between, open Advanced and tick individual permissions — grouped by area (account, analytics, API keys, records, fields, evals, media and more), with Access switching to Custom. A key that only adds records needs record-write permissions and nothing else, so a leak cannot delete your lists or read your account.
Keys work on the public API. A 403 where you expected success is almost always a missing permission — widen access and create a new key, or test with a Full access key.
Create a read-only key from the API
Key management stays in the console, with one exception: a key (or an agent using the MCP tools) holding api-key:create-read-only can create a read-only key of any scope — the building block for handing each page, or each customer of yours, its own narrow key.
POST to /api-key/read-only with the new key’s name, the account, the read permissions you want (anything ending :read or :view; writes are dropped, at least one read is required), and an optional scope/scope_target. The response carries the usable key once:
curl -X POST https://api.searchstack.dev/api-key/read-only \
-H "X-API-Key: $ACCOUNT_KEY" -H "Content-Type: application/json" \
-d '{ "account_name": "acme", "api_key_name": "site-search",
"permissions": ["search-result:read", "list:read"],
"scope": "list", "scope_target": "products" }'
- The new key holds read permissions only, so it can never write and never create another key.
- Its scope can only match the creating key’s, or be narrower.
- The endpoint is rate-limited.
- Both client libraries offer it (
client.ApiKeys.CreateReadOnly…). Shapes are in the API reference.
For an agent, include list:read: it lets the agent call GET /list/{account} and discover your list names, without which it reaches only lists you named exactly. GET /account returns the account name for any valid key; list-group:read does the same for groups.
Expiry, rotation and revocation
- Expiry — the key stops working after the date you set, on its own. Good for temporary access: a data move, a contractor.
- Rotation (swapping a key for a fresh one) — create a new key, switch your program over, delete the old one. Both work while you swap.
- Revocation (cancelling a key) — deleting a key stops it working immediately. The fix for a leaked secret; with a key per program, only that one needs a new value.