Signing in with OAuth assumes a person at a browser. When there’s nobody to approve a prompt — a CI job, a scheduled agent, a bot posting bugs — use an API key instead.
Create one under Settings → API keys in the project you want to expose (see
Secrets and API keys), then send it as
x-api-key rather than a bearer token:
curl -X POST https://api.studio.heizen.work/mcp \
-H "x-api-key: $HEIZEN_API_KEY" \
-H "x-heizen-toolsets: all" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Most clients can carry it as a static header — http_headers in Codex, headers
in Cursor, VS Code and Gemini CLI, -H in Claude Code.
How a key differs from signing in
| OAuth token | API key | |
|---|---|---|
| Header | Authorization: Bearer |
x-api-key |
| Scope | everything you can reach | one project, enforced |
| Cross-project tools | yes | blocked |
studio_api_call |
yes | blocked |
| Lifetime | 1h + refresh | until revoked |
| Best for | humans in a client | CI and bots |
A key belongs to exactly one project, and that scope is enforced inside the MCP
layer on every tool: it can’t name another project, the allProjects flag is
ignored, the cross-project my-bugs / my-tasks shortcuts are skipped, and the
studio_api_call escape hatch is refused outright.
Permissions
Each key carries an explicit permission list, chosen when you create it:
bug:read bug:write · story:read story:write · tests:read tests:write ·
docs:read docs:write · worklog:read worklog:write · meeting:read meeting:write ·
integration:read integration:write · api:read api:write
whoami, list_toolsets and the project tools need no permission. OAuth
sessions skip the check entirely — your Studio account permissions govern
instead.
Keys can be disabled or deleted from the same settings page, and they can carry an expiry. Rotate them like any other credential; revoking one takes effect on the next call.