Docs
One key, and everything it opens
The key you point a client at also drives your account: link a subscription, read what is left of each one, mint and revoke keys, and change how work is spread. Over HTTP, or from an agent through MCP.
Hand this to your agent
Everything below, written for a coding agent rather than a person: get an account, link a subscription, point an app at it, and give itself the tools to run it afterwards. No browser and no dashboard. The only step you do is reading a six-digit code out of your inbox and pasting it back.
Set up megaloop for me, then use it.
megaloop pools the AI subscriptions I already pay for behind one endpoint and one key, routing
each request to an account that still has quota. Full reference: https://megaloop.dev/llms.txt
1. ACCOUNT: two calls, no browser. Ask me for the emailed six-digit code.
POST https://megaloop.dev/v1/auth/code {"email":"MY_EMAIL"}
POST https://megaloop.dev/v1/auth/verify {"email":"MY_EMAIL","code":"CODE"}
The second returns a session token, and creates the account if I had none. Hold it in memory
for step 2 only: do not write it to a file.
2. KEY: shown once, and it is what you use from here for everything. Save it where I keep
secrets.
POST https://megaloop.dev/v1/keys bearer: the session token {"name":"agent"}
3. LINK A SUBSCRIPTION: GET /v1/providers lists what I can link and how each one links.
SHOW ME THAT LIST AND ASK WHICH ONE. Do not pick for me, and do not assume I want every
subscription I hold in the pool. Ask me what to call it too; the name is how I will
recognise it later.
POST /v1/accounts/link/direct a provider I hold a key for
POST /v1/accounts/link/start + /complete one that needs me to sign in
4. POINT MY APP AT IT: base URL https://api.megaloop.dev, my key as a bearer token.
A 200 from /v1/accounts does NOT prove this worked: an empty pool answers 200 too. Send one
real request and check you get content back.
5. GIVE YOURSELF THE TOOLS: the MCP server, so you call tools instead of curl. Needs node 20+
and nothing else. WRITE THIS INTO WHATEVER CONFIG MY MCP CLIENT USES, then restart the client.
Do not set MEGALOOP_BASE_URL. Then call its `help` tool.
{"mcpServers":{"megaloop":{"command":"npx","args":["-y","megaloop-mcp"],
"env":{"MEGALOOP_API_KEY":"MY_KEY"}}}}
Never print or commit my key. Spending is real subscription quota, so do not loop to explore.Every call in it was run against production in that order before it was written down.
Authenticating
One credential does both jobs. Mint a key on Keys; it starts sk-ml-v1- and is shown once. Send it as Authorization: Bearer <key>, the same header the inference endpoint takes. There is no second sign-in for the API or for MCP.
Four things a key deliberately cannot do: unlink an account, close your account, and either half of changing your sign-in address. The first two destroy something that cannot be recovered; the last two are the account-takeover path, because sign-in is passwordless and whoever holds the address holds the account. All four answer a key with 401 and need a session token instead. That is what POST /v1/auth/verify returns, so an agent holding one can make these calls too. The dashboard is the easy route, not the only one.
Full reference, always current: openapi.json
From an agent
megaloop-mcp is a stdio MCP server. It needs node 20 or newer and nothing else. The published package is one self-contained file, so there is nothing to clone, build or keep updated. Pick your client below.
How it authenticates
With the key you already have, and nothing else. Mint one on Keys, set it as MEGALOOP_API_KEY in the config below, and the server sends it as an x-api-key header on every call it makes to https://megaloop.dev. There is no OAuth step, no device code, no second credential to manage, and no browser window: an MCP server has no way to show you one, which is why it is built this way.
The key never leaves the process it is given to. It is read once from the environment at start-up, sent only in that header, and never written to a log line, an error message, or a tool result, so an agent reading its own output cannot repeat it back. Revoke it on Keys and the tools stop working; see the revocation note there for how quickly.
Leave the base URL unset. The server defaults to the management API, which is a different host from the inference endpoint your client points at. Setting it to 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. Swap YOUR_KEY for a key from Keys.
Codex
# ~/.codex/config.toml
[mcp_servers.megaloop]
command = "npx"
args = ["-y", "megaloop-mcp"]
env = { MEGALOOP_API_KEY = "YOUR_KEY" }Codex reads TOML rather than JSON, and takes no add command. Swap YOUR_KEY for a key from Keys.
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. Swap YOUR_KEY for a key from Keys.
To check it took, ask the agent “what is in my megaloop pool?”. It should call get_status and read back your linked accounts and plan. If the tools are missing entirely, the host has not restarted since you added the config.
What it can then do
Thirteen tools. The ones worth knowing: get_status for the whole pool in one call, get_limits for how much of every subscription is left side by side, and start_account_link to add a subscription without leaving the session. Your client can show the limits of the one account it is signed into; this shows all of them.
There is no unlink tool, for the reason above: a key may not do it, so a tool for it could only ever fail.
Linking a subscription over the API
Two calls with a person in between. Useful when the one linking the account is not the one running the code. You hand them a URL and they approve in their own browser.
- 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 they are handed differs by provider. One shows a short code, another lands on a page that will not load and expects the whole address bar. Do not guess: GET /v1/providers carries the exact wording to show them, per provider, in paste_prompt. Pass it through rather than writing your own, and paste what they give you without trimming it.
Providers that take a key rather than a browser approval skip all of this. One call to link/direct.
The endpoints
Every management call below works against https://megaloop.dev. Point inference at https://api.megaloop.dev. That is the host Keys gives you, and the one to put in a client config. Errors are JSON with a stable code; an account belonging to someone else and one that never existed both answer 404, identically.
| Accounts | What it does |
|---|---|
| GET /v1/providers | What can be linked, and the exact wording to show a user |
| GET /v1/accounts | Every linked account, with health and pause state |
| POST /v1/accounts/link/start | Begin a browser link; returns an authorize URL |
| POST /v1/accounts/link/complete | Exchange what the user pasted back for an account |
| POST /v1/accounts/link/direct | Link from a credential you already hold |
| POST /v1/accounts/{id}/resume | Put a paused account back in rotation |
| DELETE /v1/accounts/{id} | Unlink. Session only, an API key is refused |
| Keys | What it does |
|---|---|
| POST /v1/keys | Mint a key. The value is returned once and never again |
| GET /v1/keys | List keys by prefix and last use, never by value |
| DELETE /v1/keys/{id} | Revoke a key. Inference can keep accepting it for up to 60 seconds |
| Usage | What it does |
|---|---|
| GET /v1/usage | Per-account, per-day, per-model usage and its list-price cost |
| GET /v1/requests | Recent request events for your account |
| GET /v1/limits | How much of each linked subscription is left, per window |
| Routing | What it does |
|---|---|
| GET /v1/routing | How each provider's rotation is currently juggled |
| PUT /v1/routing/{provider} | Choose a strategy for one rotation |
| DELETE /v1/routing/{provider} | Return one rotation to the default |
| Account | What it does |
|---|---|
| GET /v1/billing/status | Your tier, trial, account cap and period end |
| POST /v1/billing/checkout | Start a subscription checkout |
| POST /v1/billing/portal | Open the billing portal |
| GET /v1/session | Identify the caller |
| POST /v1/tenant/delete | Close the account. Session only |