Docs
Everything the dashboard does, over HTTP
Every dashboard action is an HTTP call. A key’s capabilities decide what it may do; the calls marked Session only below require a session token.
New here? Start with the setup guide.
Hand this to your agent
Help me set up Megaloop using its supported API onboarding flow.
Read https://megaloop.dev/llms.txt and follow the setup instructions.
Ask for my email, terms confirmation, and verification code when needed.
Help me connect the AI subscription I choose, configure my app,
and verify the connection with one small test request.Authenticating
Mint a key on Keys. It starts sk-ml-v1-. Lose it and the key control on its row shows it again — to somebody signed in, never to an API key. Send it as Authorization: Bearer <key> — the same header the management API and the inference endpoint both take.
Three independent capabilities. read — accounts, usage, traffic, limits, keys, plan. inference — serve requests through the pool and choose which account they land on. manage — link accounts, mint and revoke keys. None implies another.
The default is inference alone. Choose on Keys, or send {"capabilities":["read","inference"]} to POST /v1/keys. A key can only grant what it already holds, so it cannot widen itself. A missing capability returns 403 naming it.
The rows marked Session only refuse every key, whatever it carries: they link an account from a credential you hold, unlink accounts, close the account, resume a paused account, move the sign-in address, accept the terms, or reach billing. A session token comes from POST /v1/auth/verify, so an agent holding one can make them too.
Full reference, always current: openapi.json
Pointing a client at the pool
Two settings, the same pair every client needs: the base URL https://api.megaloop.dev and your key as a bearer token. All that differs between clients is what they call them.
Claude Code CLI
Set up with settings.json
1. Open or create your user settings file:
- macOS / Linux
~/.claude/settings.json- Windows
%USERPROFILE%\.claude\settings.json
Merge these env entries into the existing JSON object; do not overwrite your other settings. Replace YOUR_KEY with your own Megaloop key.
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.megaloop.dev",
"ANTHROPIC_AUTH_TOKEN": "YOUR_KEY"
}
}2. Save, then run in your terminal — not inside an existing chat:
claudeSave the file, then restart the CLI. Typing a configuration command into an existing chat does not change that session.
For one launch without editing your global settings, fill in the downloaded template and run:
claude --settings ./megaloop-settings.json3. Run /status to check the base URL and auth token, then send a test message and find it in Megaloop → Traffic.
Do not commit a real key to a repository or share a filled-in file. Send only the placeholder template; each person supplies their own key.
Official configuration documentation ↗Codex CLI
Set up with config.toml
1. Open or create your user settings file:
- macOS / Linux
~/.codex/config.toml- Windows
%USERPROFILE%\.codex\config.toml
Merge into your user config; do not overwrite it or duplicate a table. Keep model and model_provider at the top level, before any [section]. Choose a supported model your linked accounts can serve.
model = "gpt-6-sol"
model_provider = "megaloop"
[model_providers.megaloop]
name = "Megaloop"
base_url = "https://api.megaloop.dev/v1"
wire_api = "responses"
env_key = "MEGALOOP_API_KEY"
requires_openai_auth = false2. Save, then run in your terminal — not inside an existing chat:
export MEGALOOP_API_KEY="YOUR_KEY"
codex$env:MEGALOOP_API_KEY="YOUR_KEY"
codexSet the key in each new terminal, or supply it through your secret manager. The token stays out of config.toml. Managed company settings may require your administrator's approval.
3. Start a new session, send a test message, and confirm it appears in Megaloop → Traffic. This selects Megaloop instead of the CLI's usual provider; it does not remove your existing sign-in.
Do not commit a real key to a repository or share a filled-in file. Send only the placeholder template; each person supplies their own key.
Official configuration documentation ↗Cursor
Cursor Settings → Models → API Keys
OpenAI API Key YOUR_KEY
Override OpenAI Base URL https://api.megaloop.dev/v1Add each name as a custom model, exactly as written: a model Cursor already ships goes to Cursor, not to your pool. Tab completion stays on Cursor's own models. GET /v1/models lists every name your key can use.
Any other client
base URL https://api.megaloop.dev
token YOUR_KEY sent as: Authorization: Bearer YOUR_KEYEvery client needs the same two values under whatever names it gives them. If yours offers a choice between an API key and an auth token, take the auth token.
Use the auth token, not the API key
An interactive session treats an API key found in your environment as something to ask you about: it shows an approval dialog, and the default answer is no. Decline it — or press Enter — and the session does not stop. It falls back to the login already on your machine and sends that credential here, which megaloop rejects, after which the client retries ten times and rotates the login token on each attempt.
So the symptom is not silence. It is a session that looks as though your own subscription login has broken, while your dashboard shows no traffic at all. An auth token has no such dialog: it replaces the ambient login outright.
A one-shot run never shows the dialog, which is why a sample that works the first time can fail the moment the same settings are used in a real session.
Confirming it took
The one string that proves it is Auth token: ANTHROPIC_AUTH_TOKEN. A line naming the base URL is printed whenever the variable is set, whichever credential is actually being used — it tells you the variable arrived, not that your requests did.
The fastest check needs no command: a client running on the pool bills as API usage rather than against a plan, and says so on the line it prints at startup. The authority is this end — GET /v1/requests shows the request or it never arrived.
From an editor
An editor points at https://api.megaloop.dev/v1 — with the /v1, because the editor appends the rest of the path itself. Get it wrong and the error names the correct URL back to you.
Then add the models by hand, under whatever the editor calls a custom model. Use the `megaloop-` names, exactly as listed under Cursor above — an editor will refuse to add a model it already ships, and the built-in it offers instead goes to its own servers rather than to your subscriptions. That failure is silent: no error, the request simply never reaches the pool. Copy a name from the list; only advertised aliases are supported.
GET /v1/models lists every name your key can use, aliases included. A model on your own hardware is typed under the name you pulled it as.
From an agent
megaloop-mcp is a stdio MCP server. Requires node 20 or newer; nothing to clone or build. Pick your client below and swap YOUR_KEY for a key from Keys.
How it authenticates
Mint the key on Keys with the Read and serve option — most tools read your account, so an inference-only key is refused by them. Set it as MEGALOOP_API_KEY; the server sends it as an x-api-key header to https://megaloop.dev. No OAuth step.
The three linking tools, mint_key and revoke_key need Full access. Give the server one only if it should link accounts or rotate keys.
The key is read once from the environment and sent only in that header — never to a log line, an error message, or a tool result. Revoking it on Keys stops the tools working.
Leave MEGALOOP_BASE_URL unset. It defaults to the management API; pointing it at the inference host breaks every tool.
Installing it
Claude Code
claude mcp add megaloop --env MEGALOOP_API_KEY=YOUR_KEY -- npx -y megaloop-mcpRegisters it for the directory you run it in; re-run it elsewhere, or add --scope user.
Codex CLI
# ~/.codex/config.toml
[mcp_servers.megaloop]
command = "npx"
args = ["-y", "megaloop-mcp"]
env = { MEGALOOP_API_KEY = "YOUR_KEY" }Codex CLI uses TOML. Add this block to your configuration file.
Any other MCP host
{
"mcpServers": {
"megaloop": {
"command": "npx",
"args": ["-y", "megaloop-mcp"],
"env": { "MEGALOOP_API_KEY": "YOUR_KEY" }
}
}
}Command, arguments and environment: the three values every host accepts.
To verify, ask the agent “what is in my megaloop pool?” — it should call get_status. If no megaloop tools appear at all, the host has not restarted since the config changed.
What it can then do
Nineteen tools. Start with help, which maps each question to the tool that answers it. get_status returns the whole pool in one call; get_limits returns every subscription’s remaining headroom side by side.
There is no unlink tool: unlinking is Session only, so a tool for it could only fail.
Linking a subscription over the API
Two calls with a person in between — for when whoever owns the subscription is not the one running the code.
- Call
link/start. You get anauthorize_urland alink_session_id, good for ten minutes. - Send them the URL. They approve in a browser and are handed something back.
- Call
link/completewith the session id and whatever they were handed, verbatim.
curl -X POST https://megaloop.dev/v1/accounts/link/start \
-H "Authorization: Bearer YOUR_KEY" \
-H "content-type: application/json" \
-d '{"provider":"<id from /v1/providers>","name":"my-account"}'
# -> { "link_session_id": "...", "authorize_url": "https://...", "expires_at": "..." }curl -X POST https://megaloop.dev/v1/accounts/link/complete \
-H "Authorization: Bearer YOUR_KEY" \
-H "content-type: application/json" \
-d '{"link_session_id":"...","code":"<exactly what they pasted>"}'What the user is handed back differs per provider — a short code, or a whole URL. Do not guess: GET /v1/providers carries the exact wording to show them in paste_prompt. Pass their answer through verbatim, untrimmed.
Providers that take a key rather than a browser approval skip all of this. One call to link/direct.
The endpoints
Management calls go to https://megaloop.dev; inference goes to https://api.megaloop.dev. Errors are JSON with a stable code — branch on that, not the message. A resource owned by someone else and one that never existed both answer 404.
Each row names the capability it needs. Without it: 403. Session only means no key can call it at all: 401.
| Accounts | What it does |
|---|---|
| GET /v1/providers | What can be linked, and the exact wording to show a user. Needs read |
| GET /v1/accounts | Every linked account, with health and pause state. Needs read |
| POST /v1/accounts/link/start | Begin a browser link; returns an authorize URL. Needs manage |
| POST /v1/accounts/link/complete | Exchange what the user pasted back for an account. Needs manage |
| POST /v1/accounts/link/direct | Link from a credential you already hold. Session only, an API key is refused |
| POST /v1/accounts/{id}/resume | Put a paused account back in rotation. Session only, an API key is refused |
| DELETE /v1/accounts/{id} | Unlink. Session only, an API key is refused |
| Keys | What it does |
|---|---|
| POST /v1/keys | Mint a key. Inference-only by default; needs a manage key or a session |
| GET /v1/keys | List keys by prefix, capability and last use, never by value. Needs read |
| POST /v1/keys/{id}/reveal | Show a key again. Needs a SESSION — an API key is refused however powerful, so one leaked key cannot collect the rest |
| DELETE /v1/keys/{id} | Revoke a key. Needs a manage key or a session; inference lags 60s |
| Pools | What it does |
|---|---|
| GET /v1/pools | Your pools, with how many accounts and live keys each holds. Needs read |
| POST /v1/pools | Create an empty pool. Needs manage |
| PATCH /v1/pools/{id} | Rename one. Nothing routes on the name. Needs manage |
| PUT /v1/pools/{id}/accounts | Replace the whole membership. Refused if it would empty a pool with live keys bound. Needs manage |
| DELETE /v1/pools/{id} | Delete one. Refused while a live key is bound, since that would widen it. Needs manage |
| Usage | What it does |
|---|---|
| GET /v1/usage | Per-account, per-day, per-model usage and its list-price cost. Needs read |
| GET /v1/requests | Recent request events for your account. Needs read |
| GET /v1/requests/{id}/transcript | What one request sent and received, while capture is on and for the seven days a body is kept. Needs manage |
| GET /v1/limits | How much of each linked subscription is left, per window. Needs read |
| Routing | What it does |
|---|---|
| GET /v1/routing | How each provider's rotation is currently juggled. Needs read |
| PUT /v1/routing/{provider} | Choose a strategy for one rotation. Needs inference |
| DELETE /v1/routing/{provider} | Return one rotation to the default. Needs inference |
| Account | What it does |
|---|---|
| GET /v1/billing/status | Your tier, trial, account cap and period end. Needs read |
| POST /v1/billing/checkout | Start a subscription checkout. Session only |
| POST /v1/billing/portal | Open the billing portal. Session only |
| GET /v1/session | Identify the caller. Needs read |
| GET /v1/settings/usage-cutoff | Read the organization-wide usage cutoff. Needs read |
| PUT /v1/settings/usage-cutoff | Set the usage cutoff (1–99%). Session only; admin required |
| PATCH /v1/session | Set the account's light/dark theme. Session only |
| DELETE /v1/session | Sign out. Session only |
| POST /v1/session/email | Send a code to a new sign-in address. Session only, an API key is refused |
| POST /v1/session/email/confirm | Confirm the code and move the address. Session only, an API key is refused |
| GET /v1/legal/acceptance | Whether the current terms have been accepted. Needs read |
| POST /v1/legal/acceptance | Accept the current terms. Session only |
| GET /v1/notifications/preferences | Which usage alerts are on. Needs read |
| PATCH /v1/notifications/preferences | Change them. Session only |
| POST /v1/tenant/delete | Close the account. Session only |
| POST /v1/support/tickets | Write to a person. Session only, an API key is refused — with no session, support@megaloop.dev |