How to run a headless agent or CI job with a CoreSpeed API key
Choose a member key (sk-cs-) or an agent key (sk-csa-), read it from CORESPEED_API_KEY, cap its monthly spend, and verify the key with memory__list_memory.

A headless agent or CI job authenticates to https://api.corespeed.io/mcp with an API key instead of a browser sign-in. A member key (sk-cs-) acts as you. An agent key (sk-csa-) acts as an agent principal and reaches the organization's shared connections only. Send it as Authorization: Bearer, read it from an environment variable, and cap its monthly spend.
- 1Choose the key kindsk-cs- acts as you; sk-csa- is an agent of its ownUnattended work gets an agent key.
- 2Create it with a monthly capDashboard, API keys, or cs keys createThe secret prints once. Keys are per environment.
- 3Read it from CORESPEED_API_KEYthe entry stores the variable, never the keyRemove any older browser entry first; duplicates collide.
- 4Verify with memory__list_memoryfree; a 200 without isError proves the key
- 5Expect manage__whoami to refusejwt_session_required: session-gated toolsStill listed for a key; presence is not permission.
- 6Branch on isErrorkey_spend_limit_exceeded, payment_requiredBoth arrive as 200; neither clears on retry.
Which key should a headless job use?
| Credential | Who is calling | Reaches | Use it for |
|---|---|---|---|
sk-cs- member key | The member who created it | That member's private connections and the organization's shared ones | A job that should act as you, such as CI on your own repository |
sk-csa- agent key | An agent principal with an identity of its own | The organization's shared connections only | An unattended agent you run elsewhere, or a nightly job you operate |
An agent is the organization's third principal kind. Any member can create one in Dashboard → Settings or with manage__agents_create and becomes its owner: the member who answers for it and who, with org admins, may manage it. Ownership is accountability. The agent inherits neither the owner's connections nor the owner's role.
Give unattended work an agent key. The activity trail then names the agent. Suspending it stops every request with 403 agent_suspended while its keys stay intact. Retiring it revokes the keys for good while the record survives for attribution. The full model is on the Authentication page.
How do you create the key?
- Member key: open Dashboard → API keys and create one, or run
cs keys create productionfrom the CLI, which prints thesk-cs-secret once. A signed-in agent can also mint one with themanage__keys_*tools. - Agent key: create the agent first, then mint a key for it from the dashboard or with
manage__agents_key_create. Only the owner or an org admin can. - Set a monthly spend cap in credits on the key. Keys belong to an organization, live until revoked, rotated or expired, and are per environment.
How do you put the key into the client?
- Store the key in an environment variable named
CORESPEED_API_KEYwherever the job runs. Let the server entry read the variable, so the key itself is never written into a config file:
# Claude Code: single quotes, so the entry stores the variable, not the key
claude mcp add corespeed https://api.corespeed.io/mcp --transport http --scope user \
--header 'Authorization: Bearer ${CORESPEED_API_KEY}'
# Codex
codex mcp add corespeed --url https://api.corespeed.io/mcp --bearer-token-env-var CORESPEED_API_KEY
A client that reads an mcpServers map takes the same entry as the browser form plus a headers object whose Authorization value is Bearer followed by the key. The header forms are Authorization: Bearer for any credential and x-api-key for keys only.
Never print, log or commit the key. In Claude Code, claude mcp list hides headers; claude mcp get prints them, key included, so avoid it in transcripts. If the machine already had a browser entry for corespeed, remove it first with claude mcp remove corespeed --scope user or codex mcp remove corespeed. Duplicate registrations collide on tool names.
How do you verify a key works?
- Call
memory__list_memory. It is free, and a200withoutisErrorproves the key authenticates. - Expect
manage__whoamito refuse. It answers200withisError: trueand codejwt_session_required, becausemanage__whoami,manage__keys_*,manage__agents_*,manage__accounts_*andmanage__switch_orgrun only under a member session. Those tools still appear intools/listfor a key. Presence is not permission.manage__remote_listruns for anyone.
A 401 means the key is unknown, revoked or expired; replace it and do not retry. A 403 means the key's agent is suspended; resume the agent, since a new key would be refused the same way. A 503 means the key authority was unreachable and CoreSpeed failed closed rather than trust an unverified key; retry with backoff.
What happens when the cap is reached?
Two boundaries stop metered calls before a tool runs, and both arrive on /mcp as 200 with isError: true:
key_spend_limit_exceeded: this key's monthly cap is reached. Metered calls with it stop until the month rolls over or the cap is raised.payment_required: the organization wallet is past its billing threshold. Adding credit clears it.
Through either hold, discovery (tools/list), account reads and key management keep working. Caps are request-boundary guardrails rather than reservations, so an action already in flight can finish above the remaining amount. Neither code clears on retry. The retry rules for every code are in Error handling; the ledger and caps are on the Billing page.
Branch on result.isError before you read any result. Treating a 200 as success is the most common integration bug.
Every call with a key is attributed through the key's owning identity in Dashboard → Activity: the member for an sk-cs- key, the agent for an sk-csa- key.
FAQ
Can the cs CLI take the API key? No. The CLI runs under a browser sign-in and takes no key. Mint the key once with cs keys create and send it directly from the job; the CLI is not part of the job. See the CLI page.
Does an agent key reach my private Notion? No. An agent principal reaches the organization's shared connections only. Share the connection, or use a member key.
Should I rotate the key when a tool answers needs_reauth? No. One connected account needs a member to reauthorize it in Dashboard → Connectors. The key is fine.
How do I rotate a key? cs keys rotate with the key id, or Dashboard → API keys. Update the environment variable where the job runs.