outerlayer CLI and the dashboard call. Call it yourself to script what they do.
Every endpoint is under one base URL:
/v1/. A breaking change ships under a new prefix, such as /v2/.
Authenticate
Send a credential as a bearer token on every request:
A factory key never works on
/v1/orgs/.... A management key never works on factory endpoints.
GET /health, GET /v1/health/ingestion, GET /v1/health/files, GET /v1/capabilities, GET /v1/pricing and GET /.well-known/oauth-protected-resource need no credential.
Name the factory
Factory endpoints also need theX-Outerlayer-App-Id header. Its value is the factory id. Copy it from the factory’s Settings → General.
401 and a login token gets 400 app_id_required. A login token acts only on the factory this header names. A path that names another factory, such as /v1/apps/{appId}, answers 403.
You can leave the header out on:
/v1/orgs/{orgName}/...and/v1/me/factories, which name no factory./v1/mcpwith a factory key, because the key belongs to one factory./v1/apps/{appId}/mcp, which takes the factory from the path. It accepts only a user or OAuth token, never an API key.
Make a request
List the factory’s live work items:work.read. A page holds up to 100 items:
pagination.cursor is not null, send it back as ?cursor=<cursor> for the next page.
Errors
An error answers with a status code and this body:error.code, which is stable. error.message is for people. Some errors add fields, such as required_permission above.
Rate limits
Most endpoints have no rate limit. These do, counted per organization:
An MCP tool call counts against the same limit as the REST endpoint it mirrors.
Each limit has its own bucket. A
429 carries X-RateLimit-Limit, X-RateLimit-Remaining, and, when known, X-RateLimit-Reset (Unix time in milliseconds) and Retry-After (seconds).