Authentication
API keys, scopes, sandbox, and rotation. Bearer tokens — no sessions, no cookies.
GenieOS uses bearer authentication on every request. There are no
sessions, no cookies, and no per-call signing — just an Authorization
header. Scopes ride on the key itself; rotation is one click.
Authorization: Bearer gos_live_8a72c0e1...Key flavours
| Prefix | Use it for | Counts toward billing | Rate-limited |
|---|---|---|---|
gos_live_* | Production traffic | Yes | Yes |
gos_test_* | CI, integration tests, local dev | No | No |
gos_mcp_* | Issued by MCP installers (Cursor etc.) | Yes (per scope) | Yes |
A key always belongs to a single workspace. There is no concept of a multi-workspace key — if you operate several workspaces, mint one per workspace.
Scopes
Each key carries a set of scopes that bound what it can do. Scopes are
additive — a key with templates:read and templates:send can read and
send, but cannot create or modify templates.
| Scope | Allows |
|---|---|
workspace:read | Read workspace settings, plan, identities |
brand:read | Read brand voice, palette, fonts, logos |
templates:read | Read templates and the schema contract |
templates:render | Preview / render templates (no send) |
templates:write | Create, update, version templates |
templates:send | Send transactional email |
messaging.transactional.read | Browse / preview transactional SMS |
messaging.transactional.send | Send transactional SMS |
pages:read | List and read landing pages |
pages:write | Compose / update pages |
pages:publish | Publish / unpublish pages |
sequences:read | List and read sequences + runs |
sequences:trigger | Enrol contacts / cancel runs |
flows:enroll | Alias of sequence enrol |
subjects:write | Upsert subjects / contacts |
events:write | Emit events into the workspace |
stats:read | Read template stats |
social:posts:read | List company networks, organic posts, analytics |
social:posts:write | Create and edit organic social drafts |
social:posts:publish | Schedule, publish, and delete organic posts live |
social:transactional:read | Browse / preview transactional social events |
social:transactional:trigger | Queue transactional social events |
social:transactional:publish | Publish transactional social events live |
marketing:read | Read Marketing Strategy, ICPs, creation defaults |
marketing:write | Patch strategy / defaults / ICPs |
campaigns:read | List / read creations |
campaigns:write | Spawn creations / approve strategy |
lists:read | List / read contact lists |
lists:write | Create lists / add members |
approvals:read | List policies and pending requests |
approvals:write | Manage policies / decide requests |
links:read | List / get short links, click analytics, UTM suggestions, render QR (without saving to Assets) |
links:write | Create / update short links and QR designs; render with saveToAssets |
connectors:read | List connector catalog + installs |
webhooks:manage | Create / update / delete webhook subscriptions |
audit:read | Read paginated audit log |
The dashboard exposes presets — Read, Author, Send, Full —
that compose these for you. Send and Full include organic social
publish (social:posts:publish).
Generating a key
app.genieos.pro → Settings → API keys → New key. Pick a flavour (live or sandbox), pick a scope preset, name the key for the surface that will use it (e.g. "Heroku web dyno", "Vercel preview", "GitHub Actions"), then Create. The key value is shown once.
Keys are minted in the dashboard today. Authenticate the CLI with a pasted key:
# Create the key at app.genieos.pro → Settings → API keys, then:
genie login
# or headless:
export GENIEOS_API_KEY=gos_live_...
genie keys list
genie whoamiSee the CLI docs for the full subcommand surface.
Use the Install in Cursor / Install in Claude buttons in
app.genieos.pro → Developers → MCP. The browser flow mints a
short-lived gos_mcp_* key with the scopes you tick and configures your
editor with one click. Revoke from the same dashboard at any time.
See MCP for the complete install reference.
Verifying authentication
A trivial smoke test:
curl -s https://api.genieos.pro/v1/workspace \
-H "Authorization: Bearer $GENIEOS_API_KEY" \
| jq .A successful call returns the workspace document. Failures use the standard error envelope:
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "API key revoked or never issued.",
"request_id": "req_01JABC..."
}
}| Status | Type | Most likely cause |
|---|---|---|
| 401 | authentication_error | Missing / malformed / revoked key |
| 403 | permission_denied | Key is valid but doesn\u2019t have the required scope |
| 404 | not_found | Resource exists in another workspace |
| 429 | rate_limit_exceeded | See Rate limits |
Rotation
Keys can be rotated without downtime. The flow:
- Create a new key with the same scopes; deploy it alongside the old one.
- Verify production traffic on the new key (the dashboard shows last-used per key).
- Click Revoke on the old key. Revocation is instant — the API rejects the old key on the next request.
For SDK-based integrations the SDK reads GENIEOS_API_KEY at startup, so
a rolling deploy is enough. For long-lived workers, signal them to re-read
the env or restart.
No grace period
Revoked keys are rejected immediately. There is no soft-revoke or grace window — if a leaked key is in the wild, killing it is the right answer every time.
Storing keys safely
- Use a secrets manager (Doppler, Vault, AWS Secrets Manager, Google Secret
Manager, GitHub/GitLab Secrets) — not committed
.envfiles. - Scope keys narrowly. A worker that only sends mail should hold a key with
templates:sendand nothing else. - Per-environment keys. One per dev / staging / production. Never reuse a production key in a sandbox-shaped place.
- Watch the audit log. Every authenticated request lands in
audit.logwithkey_idso you can correlate suspicious activity.
What\u2019s next
- Send your first request: Quickstart.
- Understand the safety net under retries: Idempotency.
- Hand authentication off to your AI editor: MCP.