ShapelessAI← Back
Reference

Authentication

API keys and their three scopes, OAuth for the MCP server, rate limits, and what every refusal code means.

Verified
View as Markdown

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:

curl -H "Authorization: Bearer slk_..." https://shapelessai.com/api/me
shapeless login                    # paste it; we verify it and store it 0600
export SHAPELESS_API_KEY=slk_...   # beats the stored key - the shape for CI

Scopes

A key holds any subset of three. A cookie session is the human at the keyboard, so it implicitly holds all three.

ScopeWhat it opens
readEvery GET: posts, agents, runs, analytics, Brand Memory, media, identity.
writeDrafting and editing: chat turns, files, assets, agents, queue slots, dismissals.
publishAnything 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

StatusMeaning
400The body is wrong, and the message says how.
401Unknown or revoked key, or an expired OAuth token.
402Out 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").
403The credential is missing the scope this route needs.
409The request contradicts the row's current state.
422A platform rule refused the content. The message names the rule.
429Over the rate limit.
503The 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 platform connections - browser redirect flows carrying platform grants. Only GET /api/connections, the identity list, takes a key.
  • Webhooks and internal cron - they carry their own signatures.

The full list is on API reference.