Authentication
API keys and their three scopes, OAuth for the MCP server, rate limits, and what every refusal code means.
Two credentials reach the same account. A person in a browser rides a signed session cookie. An agent rides either an API key (the API and the CLI) or an OAuth token (the hosted MCP server). Both are judged by one scope policy.
API keys
Mint one under Settings, API keys. Name it, pick its scopes, copy it once: only its sha256 is stored, so we cannot show it again. Revoking it in the same screen kills it on the next request.
A key is slk_ followed by 40 base64url characters. Send it on every request:
No account yet: sign up without a browser
An agent can open the account and mint its own first key in four calls, no browser and no card. The only human step is the 6-digit code we email: read it from an inbox you own, or ask the person for it. The code lasts 10 minutes and dies after 3 wrong tries. A new account starts on the Free plan with $5 of credits.
The same call signs an existing account in, so it is also how an agent gets a key for an account
a person already has. Connecting a social network still needs the person: GET /api/connections
answers connect, a list of {platform, url, expiresAt}, one per network not yet connected. Hand
the person the url; it lasts 15 minutes, so fetch a fresh one rather than reusing an old one. If
they are signed out, the link asks them to sign in with the same email (code or Google) and then
opens the network's consent screen.
Scopes
A key holds any subset of three. A cookie session is the human at the keyboard, so it implicitly holds all three.
| Scope | What it opens |
|---|---|
read | Every GET: posts, agents, runs, analytics, Brand Memory, media, identity. |
write | Drafting and editing: chat turns, files, assets, agents, queue slots, dismissals. |
publish | Anything that puts content out or marks it out: creating a post, approving, publishing, waking an agent, sending an engagement action. |
The line that matters is write against publish. A write key can draft all day and change
nothing the world sees. Only publish puts something on a real account.
Give a key the least it needs. A read-only key handed to a reporting script that leaks is a leak, not a foothold.
OAuth, for MCP
The hosted MCP server at https://shapelessai.com/mcp takes no key. It is OAuth 2.1 with dynamic
client registration and PKCE, so a host registers itself:
- Protected-resource metadata:
https://shapelessai.com/.well-known/oauth-protected-resource/mcp - Scopes:
read,write,publish,offline_access - Transport: streamable HTTP
An unauthenticated call answers 401 with a WWW-Authenticate: Bearer resource_metadata="..."
header pointing at that document, which is the handshake every MCP client keys off. Tokens are
revocable by the human under Settings, API keys, Connected apps. Setup per host is on
MCP server.
Rate limit
600 requests an hour per key. Requests that fail the scope check still count. Cookie sessions are not limited by this.
Over the limit is a 429. Back off; do not spin. Polling a job every second for ten minutes is
600 requests, which is the whole hour - use jobs_tail (or GET /api/studio/tail), which holds
one connection open instead.
Refusals
| Status | Meaning |
|---|---|
400 | The body is wrong, and the message says how. |
401 | Unknown or revoked key, or an expired OAuth token. |
402 | Out of allowance: the Free plan's ten posts for that UTC day (code: "free_daily_cap", with the day and its resetsAt) or an empty credit wallet (code: "trial_exhausted"). Every 402 body carries upgrade: the pricing page and a checkout link per plan, for the human to click. |
403 | The credential is missing the scope this route needs. |
409 | The request contradicts the row's current state. |
422 | A platform rule refused the content. The message names the rule. |
429 | Over the rate limit. |
503 | The service has no database. |
What a key deliberately cannot do
These refuse a bearer key. It is not an oversight:
- Key management (
/api/keys) - a key must never mint itself a wider key. - Money (
/api/checkout,/api/portal) - buying and cancelling belong to the person paying. - Sign-in and the platform OAuth click - browser redirect flows carrying platform grants. An
agent mints the link (
POST /api/connections/link) and the human opens it; listing, grouping, tracking and disconnecting accounts take a key. - Webhooks and internal cron - they carry their own signatures.
The full list is on API reference.
