Authentication
Every request to the REST API authenticates with a Bearer API key — no OAuth dance, no session cookies.
Get a key
Create one from your workspace's API Keys page. The raw key is shown exactly once — only a hash is ever stored, so if you lose it, revoke it and create a new one.
- Sandbox-plan workspaces get keys prefixed
sk_test_. - Paid-plan workspaces get keys prefixed
sk_live_.
Send it as a Bearer token
curl https://underlayer.outworx.io/api/v1/me \
-H "Authorization: Bearer sk_test_..."Scopes
A key is either read only or read and write, chosen when you create it and not changeable afterwards — a key whose powers can grow is one you cannot reason about from the place it is pasted. Make a new key instead; they are free and revoking the old one is one click.
A read-only key may use GET and HEAD. Anything else comes back 403 insufficient_scope, whatever the endpoint — the check runs before the route does, so it is the same answer everywhere and no endpoint can forget it.
{
"error": "insufficient_scope",
"message": "This key is read-only, so it cannot POST — create a key with write access, or use a different one."
}Keys created before scopes existed are read and write, which is what they have always been. Nothing was silently downgraded.
Rate limits
Each key is limited to 120 requests per rolling one-minute window. Going over returns a 429 with a Retry-After header telling you how many seconds to wait.
Separately, a Sandbox workspace that spends its monthly allowance gets a 402 on every endpoint until the month resets or the workspace upgrades. Paid plans are never hard-capped mid-month.
Errors
Every error response is JSON with an error code and a human-readable message:
{ "error": "unauthorized", "message": "Invalid or revoked API key." }Possible error codes:
invalid_request— The request body failed validation.unauthorized— Missing, invalid, or revoked API key.not_found— No row matches that id in your workspace.rate_limited— Too many requests — see Retry-After.plan_required— Your workspace's plan doesn't include this endpoint (403), or a Sandbox workspace has spent its monthly allowance (402).internal_error— Something went wrong on our end.