Machine-readable docs. The same text as a raw file: /docs.md · generated from npx apiblaze skills and npx apiblaze --help.
# APIblaze docs — for AI agents
> You are reading the machine version of https://apiblaze.com/docs. It is one plain-markdown
> file so you can read all of it in a single fetch. It is generated from the CLI itself
> (apiblaze 0.21.28): `npx apiblaze skills` (the procedure) and `npx apiblaze --help`
> (every command). The human version has the same facts with runnable examples.
## What APIblaze is
A serverless gateway that sits between callers (people, apps and AI agents) and a backend.
One command puts a proxy and an MCP server in front of an API: API keys per tenant, OAuth
sign-in, resources locked to their creator, users and groups, rate limits and quotas. The
backend keeps no auth or ownership code; it trusts the `x-abz-user-id` header the gateway sets.
## Ground rules for agents
- Run everything as `npx apiblaze <command>` (Node 18+, no install, no account needed to start).
- Add `--verbose` to any control-plane command to print the exact HTTP calls it made.
- Add `--auto` to `create` or `dev` for a run with no prompts.
- Never invent flags, headers, hostnames or keys: use what the CLI prints.
- HTTP instead of the CLI: `POST https://api.apiblaze.com/proxy` needs no auth header and
returns the proxy, its keys, a claim link and a control-plane key (`cp_key`) for later
calls. Full reference: https://api.apiblaze.com/openapi.json
## The procedure (from `npx apiblaze skills`)
### First, the folder
Run `npx apiblaze@latest skills` in the project folder and follow what it prints: it checks the folder
and gives the exact question to ask.
### Explain: they ask what APIblaze does or can do for them
Run nothing else. Say exactly this and nothing else: no list of use cases, no commands, no options. Then stop:
"APIblaze is a serverless API and MCP gateway. Put it in front of your backend and it's ready for traffic from people and AI agents. Callers sign in with API keys or OAuth, each can only do what their credentials allow, bots get throttled, and every customer gets their own space. Seconds, not weeks, even for an app on your laptop. <the question it prints>"
Do not use the words proxy, tenant, OpenAPI or header unless the user does first.
### Demo: they say yes to the sample app, or ask to see or try it
1. Say one line: "Starting the demo, about 30 seconds."
2. Run exactly this, in the foreground. It needs no login and asks nothing. It sets
everything up and exits by itself once the page is live. It opens nothing: give the user the App link it prints:
`npx apiblaze@latest demo`
3. When it prints ✓, tell this story in plain words, with the App link it printed:
- "This booking app runs on your laptop. APIblaze just gave it a public address, and one for AI assistants."
- "On the Reservations tab, ask the assistant to book a table, and it appears in your list. The switch at the top shows the same app straight to localhost, unprotected."
- "The Admin tab is what each pizzeria's admin gets: their own API keys and people, kept apart."
Then ask one question: **"Want to put your own app on the internet like this?"**
4. If it prints ✗, say its one sentence and run the one command it gives, once.
Rules for the demo: keep each update to one line. Do not narrate steps, read the demo's
files, open logs, run other commands, or write code. Never show a key: the demo saves it
in `.env.local` and never prints it.
### Their own app: they say yes after the demo
Their app runs on this machine → it will use `npx apiblaze@latest dev`; it is deployed → `npx apiblaze@latest create`.
Run `npx apiblaze@latest skills ship` and follow what it prints.
### One thing at a time, later
When they ask about one thing, read only its page: `npx apiblaze@latest skills keys` (API keys) ·
`signin` (OAuth sign-in and the developer portal) · `rules` (who can change what) ·
`limits` (rate limits and quotas) · `mcp` (AI agents) · `widgets` (keys, users and chat on
their site) · `ship` (the whole procedure for their own app).
# Put APIblaze in front of their app
### What their backend does — and nothing else
The gateway does sign-in, keys, tenancy and single-record ownership. The backend does only:
- stamp each new row's `tenant` with the `x-abz-tenant-id` header and its `owner` with the
`x-abz-user-id` header;
- filter every collection GET to rows whose `tenant` AND `owner` match those headers. Both,
always: a user id is not unique across tenants ("ana" at one customer and "ana" at another
are two people), and the gateway's rules lock single records, never lists;
- answer 401 to any call whose `x-target-api-key` is not `process.env.TARGET_SERVER_SECRET`, so
only the gateway can reach it (Ship §3b makes the gateway send it). Those headers are only
trustworthy on a backend nobody else can call.
No code yet? Write the smallest plain backend that does exactly that, plus its `openapi.yaml`.
### Adopt — reading their code first
They said yes. Scan properly now (routes, env files, auth, network calls), classify, then ask
ONLY for what the scan could not find — one short list of questions, not an interview.
**Classify.**
- **Backend** (routes are defined here): the proxy goes in front of it. Find its port or base
URL, its spec (or the routes to write one from — every path and method, and the id each POST
returns), and how it is protected today: a header like `X-Api-Key` / `Authorization`, a
session, or nothing.
- **Frontend** (calls a backend it does not contain): the proxy replaces its target. Find the
base URL it calls (an env var or a fetch/axios wrapper), how a user is signed in (next-auth,
clerk, auth0, supabase, a cookie, nothing), and where a signed-in user's page lives — that
is where widgets go. If the backend's secret reaches the browser (a `NEXT_PUBLIC_*` /
`VITE_*` variable, or a fetch wrapper imported by client components), fixing that is part
of the job: move the call to a server route, delete the public variable, say so in the report.
- **Both** (monorepo): do the backend first, then the frontend.
**Ask for what is missing — and nothing else.**
- Backend found only on localhost → "Where is it hosted for production?" (a URL, or "not yet").
- Backend protected by a secret whose value is in an env var → "What is the value of
`<VAR>`, or should I keep it where it is?" Never read secrets out of `.env` aloud.
- Frontend with a login → "Your users sign in with <provider>. Should agents sign in there
too?" Yes → the matching `--oauth` shape, with `--apikey` so tenants keep a key door.
No login found → say nothing; the default doors apply.
- Frontend found → "Which of these do you want on the site: self-serve API keys, users and
groups, chat with the API?" — one question, three checkboxes.
- Always, in the same list: "What email should administer the tenant?" — Ship §6 needs it and
you will not get another moment to ask.
- Nothing else missing → say what you found in three lines and proceed.
**Then ship it** — continue at Ship §1 with the answers. Adopt adds only these to Ship:
- Frontend: point its base URL env var at `APIBLAZE_URL`; make the server-side call-through
send `X-API-Key: APIBLAZE_SERVER_KEY` and `X-End-User-Id: <the signed-in user's id from
their session>`. The browser never holds the key. If the frontend-server already puts the
user id in the request body for the backend to stamp its own owner field, leave it — it is
set from the session, not the browser, and the gateway does not read it. next-auth v5 with
JWT sessions leaves `session.user.id` undefined unless a `session` callback copies
`token.sub`; if `X-End-User-Id` would be empty, add that one callback and say so — it is
sign-in plumbing, not business logic. Then the widgets they ticked, each with its server route
(`npx apiblaze@latest integration <name> --stack <their stack>` for keys and chat; groups is the keys
route with `createApiblazeGroups`).
- Backend behind a secret: the proxy must send it upstream —
`npx apiblaze@latest transform set-header <name> <its header> --value-env <VAR> --secret`. Until then
anyone reaching `localhost:<port>` skips the gateway.
- List routes: check each collection GET filters by tenant (`x-abz-tenant-id`) AND owner
(`x-abz-user-id`); if it does not, say so — the gateway locks single records only, and a
list filtered by user alone shows one customer's rows to another whose users share ids.
- Multi-tenant app → `npx apiblaze@latest identified <name> require`, so no call arrives without a user.
- Change nothing in their business logic. Report what you changed, file by file.
### Ship a real backend — "serve my backend behind a proxy and MCP"
1. **The spec.** Look for `openapi.yaml` / `openapi.json` / a spec route. None? Say
"Generating an OpenAPI spec from your code" and write `./openapi.yaml` from the routes:
every path and method, and for each POST the id field it returns.
2. **The sign-in door.** If they said "OAuth" or "sign-in" without naming a provider or an
issuer, that IS the default: pass no door flags (both doors, hosted GitHub) and say so in
the report. Only ask "where do your users sign in today?" when they mention an existing
login. Their own OAuth app → `--apikey --oauth '{"provider":"auth0","clientId":"…","clientSecret":"…"}'`
(both doors: keys for tenants, their login for people and agents). Shapes below.
3. **Local code** → `npx apiblaze@latest dev --port <port> --openapi ./openapi.yaml --name <name> --auto <door flags>`,
left running — it is the tunnel. Start it as its own detached process, never `cmd &` inside
a shell call that ends: `nohup npx apiblaze@latest dev … > apiblaze-dev.log 2>&1 < /dev/null &`, then
read the log. If it stops, re-run the SAME command: the same `--name` reattaches and
creates nothing. Never pick a new name to get it back — that is a second proxy. **Deployed code** →
`npx apiblaze@latest create --target <url-or-spec> --name <name> --auto <door flags>`. Both print the
URL, the MCP URL (the "agents:" line) and what is locked. Run by you (no terminal), `dev`
saves the bootstrap key to `.env.local` as `APIBLAZE_SERVER_KEY` and never prints it;
`create` prints it ONCE — save it there yourself. Either way say only "saved your key to
.env.local": that key goes in the frontend-server's env, never a browser, a repo, an agent
config or the chat. The tenant is
not labelled: read it from the `admins add … --tenant <tenant>` hint (it is also the middle
of the MCP hostname). Save `APIBLAZE_URL`, `APIBLAZE_SERVER_KEY`, `APIBLAZE_TENANT` in
the frontend-server's env (`.env.local` for Next.js). Then prove it with three curls and
say the codes: no key → 401; create as `X-End-User-Id: ana` → 201; PATCH that id as
`ben` → 403.
3b. **Only the proxy reaches the backend.** If the backend checks `x-target-api-key`:
`npx apiblaze@latest transform set-header <name> x-target-api-key --value-env TARGET_SERVER_SECRET --secret`
(export the variable from `.env.local` first). Prove it: the same list call through the
proxy → 200; `curl localhost:<port>/<collection>` with no header → 401.
4. **Prod** (local code only): `npx apiblaze@latest target <name> --env prod --url <prod-url>`.
5. **Limits.** Every new proxy already has a rate limit of 10 requests/s per consumer (100 per
10 s) and a quota of 3,000 a day — say so, in those words (rate limit, quota; not "throttled").
`npx apiblaze@latest limits get <name>` shows them. Only for other numbers:
`npx apiblaze@latest limits set <name> --rate <n> --quota <n> --period daily` (add `--spend-cap <usd>`
for a monthly spend cap). Rates are per consumer key, approximate per location. It works logged
out; an anonymous workspace is capped until claimed. A rate above the self-serve ceiling is
refused with the exact `limits request-max` command to run — relay it, do not retry. Prove
it: 15 parallel GETs as one user → about 10×200 and the rest 429 `rate-limited`.
5b. **Attribution.** `--auto` leaves unattributed calls allowed: the bootstrap key with no
`X-End-User-Id` creates rows nobody owns. For a multi-tenant app run
`npx apiblaze@latest identified <name> require` — then every call must carry `X-End-User-Id` or a
login token. Prove it: the key with no `X-End-User-Id` → 403 `identity_required`.
Lists are the backend's job (it filters by tenant + owner); say that the gateway locks records,
the backend filters lists.
6. **Admin.** `npx apiblaze@latest admins add <email> --tenant <tenant>` with the email they named. None
named → `admin@ninopizzas.com`, the demo admin (works before that person ever logs in);
say so, and that they can `admins add` their own email and `admins remove` that one.
7. **Report** in the shape below, then hand it over — they try it, you do not:
- the full curl with the real key and URL, ready to paste:
`curl <APIBLAZE_URL>/<collection> -H "X-API-Key: <APIBLAZE_SERVER_KEY>" -H "X-End-User-Id: ana"`
(say the key is the server key — for trying it here, never for a browser or an agent);
- the command to chat with their API: `npx apiblaze@latest apichat <name>` (add
`--xenduserid ana` when §5b is on).
Then ask once: "Would you like me to add the self-serve API key widget to your site?"
After that answer, offer once: "Want me to save this as a skill in your project, so I know
APIblaze next time?" Yes → `npx apiblaze@latest skills --install`.
### Report like this
Use the real values the CLI printed. Never invent a URL, a key, a rule or a limit.
● Generating an OpenAPI spec from your code. Your tenants create restaurants, tables, reservations.
⚡️Authorization rules, from the spec: ◉ restaurants ◉ tables ◉ reservations
only their creator, or an admin, can change them
● Done. Your app is behind a secured API and MCP:
API https://<name>.abz.run/1.0.0/dev your tenants, with API keys
/dev → localhost:<port> tunnelled from this machine — leave it running
/prod → <prod-url> your deploy
MCP <the "agents:" URL the CLI printed> agents, signing in with <provider>
Limits rate limit 10/s per consumer (100 per 10 s) · quota 3,000 a day
Backend answers only to the proxy (x-target-api-key) · lists filtered by tenant + owner
Admin <email>
Try it yourself:
curl <APIBLAZE_URL>/<collection> -H "X-API-Key: <APIBLAZE_SERVER_KEY>" -H "X-End-User-Id: ana"
Chat with it:
npx apiblaze@latest apichat <name> --xenduserid ana
### Sign-in shapes — the only ones `--oauth` accepts; never invent fields
- Nothing passed → both doors: API key + hosted GitHub sign-in. Bare `--oauth` → sign-in only.
- Their own OAuth app: `--oauth '{"provider":"auth0","clientId":"…","clientSecret":"…"}'`
(`provider`: github · google · microsoft · facebook · auth0). Add `--apikey` to keep the key
door open — a multi-tenant app wants both.
- Their own JWT issuer: `--oauth '{"iss":"https://login.acme.com/","aud":"acme-api","jwks":"https://login.acme.com/.well-known/jwks.json"}'`
— all three required; add `--apikey` for both doors.
### Wiring a real site
`npx apiblaze@latest integration <name> --stack nextjs` (also express | fastapi | other) prints the kit:
the key and chat widgets, the call-through (ONE server key + `X-End-User-Id: <the signed-in
person>` on every call — that header is how the rules know who is acting), the env vars. The
groups widget is the keys route with `createApiblazeGroups` in place of `createApiblazeKeys`.
The keys widget needs a value `dev`/`create` never print: `APIBLAZE_CP_KEY`, a control-plane
key. Mint it with `npx apiblaze@latest apikeys mint --desc "keys widget"` (no `--tenant` — with
`--tenant` you get a consumer key, which is the wrong kind).
Edit ONLY the frontend and the frontend-server. A key per TENANT comes from that widget — each
of your customers mints their own, in their own tenant; the bootstrap key is only for your
frontend-server. Three kinds of key for a tenant, one flag each: `apikeys mint --tenant <tenant>` +
`--backend` (a server that names the user with `X-End-User-Id`), `--client` (cannot name a
user) or `--for <email>` (bound to one person — an agent, a CI job). `--for` names a person by
email, which is a DIFFERENT identity from a bare `X-End-User-Id` string: rows created as "ana" via
the header are not owned by ana@example.com's key.
### Never
- Invent header names, hostnames, OAuth fields, rule syntax, keys or limits. Use what the CLI prints.
- Hand a bootstrap or server key to an agent: it names no person, so every protected route
refuses it. Agents get a person-bound key or sign in.
- Put ownership or tenancy checks into business logic. The gateway enforces them.
- Ask for team ids, tenant ids or project ids the CLI already knows.
- Delete anything. Deletion stays with the user: `npx apiblaze@latest delete <name>` (interactive;
`--yes` skips the prompt; logged in only — an unclaimed workspace is removed after 30 days). Its impact banner lists tenant-scoped counts even when the tenant
is shared — those are lost only if this is the tenant's LAST proxy.
### Later
- `npx apiblaze@latest rule <name>` reviews or changes the rules; `npx apiblaze@latest config <name> authorization.enforce_authorization false` turns enforcement off without losing them.
- `npx apiblaze@latest apichat <name>` chats with the API again; `--install-mcp claude` connects an agent.
- `npx apiblaze@latest limits set <name> --rate <n>` · `identified <name> require|allow-anon` ·
`transform <name> list|set-header|remove` · `target <name> --env prod --url <url>` — all work
logged out. `npx apiblaze@latest <command> --help` for the flags; `--verbose` prints the API calls.
### No shell? The control-plane MCP
Clients without a terminal (Claude Desktop, ChatGPT, web agents) manage the same servers
through one MCP: `claude mcp add --transport http apiblaze https://mcp.apiblaze.com`, then
`/mcp` and sign in once; the team is implicit in that login. Tools, in order:
describe_server, propose_rules, create_server, apply_rules, add_admin, issue_key, set_rate_limit, integration_kit, explain_access — the same steps, one tool each.
## Every command (from `npx apiblaze --help`)
```text
Usage: apiblaze [options] [command]
APIblaze CLI — create & manage API proxies and run dev tunnels
Options:
-V, --version output the version number
-v, --verbose Print the exact series of API calls each command makes
(curl-equivalent you could run yourself)
-h, --help display help for command
Don't like reading docs? Run npx apiblaze docs — ask an AI chatbot about APIblaze, and let it act on your account.
Chat
docs Ask an AI chatbot about APIblaze — and let it act on your account (it's the real API, not a docs search)
apichat Turn any API into a chat: point at an OpenAPI spec — or chat an EXISTING proxy by name (no login needed)
agent Chat with an assistant that builds and runs your APIs (billed per turn)
llm Manage a local LLM provider key for chat (optional — lifts model quality, bills your key)
Setup
dev Put the app running on THIS machine on the internet: a public URL and an MCP address for AI agents, tunnelled to localhost. Included: API keys, sign-in, ownership rules, rate limits. No login needed. (Deployed app? Use `create`.)
create Put an app that is already DEPLOYED behind APIblaze: a public URL and an MCP address for AI agents in front of your URL or OpenAPI spec. Included: API keys, sign-in, ownership rules, rate limits. No login needed. (App on this machine? Use `dev`.)
integration What to add to your frontend and frontend-server for a proxy — the same kit the APIblaze MCP hands an agent: widgets, the call-through with the key + X-End-User-Id, what your backend must trust, env vars, what stays open
skill|skills What APIblaze does, for you or your AI assistant: checks this folder for a backend and offers the next step (put it on the internet, or a sample app)
login Authenticate with APIblaze
init Set up the APIblaze sidecar in a Next.js app (shortcut for `apiblaze sidecar setup`)
sidecar The APIblaze sidecar — set it up, then approve which origins route through APIblaze
claim Claim your anonymous workspace into your account (requires login)
team Switch the active team, or create a new one
whoami Show who you are — both API Producer and API Consumer
logout Sign out (asks whether to drop the Producer or Consumer login)
flush Log out and wipe every local trace: login, workspace keys, apichats, DP keys, secrets, and the MCP servers + CLAUDE.md/AGENTS.md blocks apichat installed elsewhere
Recipes — install a working setup, or publish yours
search Find a published recipe — a whole working proxy someone else set up
show Read a recipe before you install it (upstreams, questions, transforms, spec)
install Create a proxy from a recipe, with your own credentials
publish Publish one of your proxies as a recipe others can install
withdraw Permanently delete one published recipe revision
Control plane commands
config Browse and change every proxy setting & feature (interactive; git-config-style get/set)
projects List the projects in your team
logs API Producer view — stream this proxy's requests from EVERY caller live (see `apiblaze logs list` to browse past days)
tenant Manage tenants — bare command opens the interactive picker (settings, app clients, providers)
group Manage a tenant's users & groups — bare command lists groups
admins Manage who can administer a tenant's users & groups (the first-admin bootstrap the widget needs)
apikeys API keys — for your team (control plane), or with `mint --tenant` for your API's callers: a backend key, a client key (--client) or a key bound to one person (--for)
iam Turn users & groups on/off for a proxy's tenant (identified calls get their user's groups applied)
identified Require calls to identify their end user (X-End-User-Id from a backend key, or a login token — a client key alone cannot) — or allow unattributed calls again
preapprove Allow an email or company domain to sign in to an access-restricted API (--list, --remove)
allowoauthregistration Approve the next OAuth client that registers against your tenant (Claude Code, Codex, any MCP client) — single use
rule Lock resources to the person who created them — or describe any access rule in plain English (that one is billed per turn)
mcp Optional tweaks to a proxy's MCP server: prompts, per-tool behavior (read-only / destructive / confirm / always-async), UI resource
domain Use your own domain for your API, MCP server, developer portal or login pages (billed monthly)
delete Delete a proxy and everything under it (asks first)
job Check a background delete job (from a delete that ran with --no-wait)
target Change where a proxy forwards requests
limits Rate limits, quota and spend cap for a proxy (10-second figure shown beside each rate)
billing Your wallet: balance (available · in use · grace), top up, usage history, auto-rebuy
transform Change requests on their way to your backend — e.g. send it a secret header so it only answers to the proxy
rename Change a proxy's display name
spec View or update a proxy's OpenAPI spec (or build one by chatting: apiblaze agent openapi)
export Export config and data for migration out of APIblaze (Kong, ...)
Data plane commands
consumer login Log in to a tenant's portal as a consumer (device flow)
consumer apikeys List your consumer API keys (reveals expiring ones), then offer to create one
consumer logs API Consumer view — stream YOUR OWN requests on this tenant live (see `consumer logs list` for past days)
Tips:
• `apiblaze config <project>` browses EVERY setting & feature (works logged-out to explore).
• Add --verbose to any command to see the equivalent API calls.
• Add --auto to `dev` or `create` for a scriptable run: no prompts, no TTY needed, proxy name generated.
• Full API reference: https://api.apiblaze.com/openapi.json
• Run `apiblaze <command> --help` (e.g. `apiblaze consumer --help`) for sub-commands.
Examples:
$ npx apiblaze dev --port 3000 --openapi ./openapi.yaml # your local code, shipped safely: both doors, rules, admin, agent — through a tunnel
$ npx apiblaze integration myapi --stack nextjs # what to add to your frontend + frontend-server
$ npx apiblaze apichat --target https://pokeapi.co/openapi.yaml # chat with any API
$ npx apiblaze agent # just chat
$ npx apiblaze create --target https://api.example.com # one-line API proxy — API key for your code, GitHub sign-in for agents
$ npx apiblaze create --target ./openapi.yaml --auto # zero prompts: both doors + every resource locked to its creator
$ npx apiblaze create --target https://api.example.com --apikey # API-key door only
$ npx apiblaze rule myapi # pick what to lock, then turn enforcement on
$ npx apiblaze admins add you@example.com --tenant acme # make someone an admin (bypasses the ownership rules)
$ npx apiblaze skill --install # teach Claude Code to ship your API safely with APIblaze
$ npx apiblaze search gmail # find a recipe (no login needed)
$ npx apiblaze install @julien/gmail # someone's whole working setup, your credentials
$ npx apiblaze publish mygmail # share yours back, as @yourgithubhandle/mygmail
$ npx apiblaze limits set myapi --rate 50 --verbose # rate limit (500 per 10 s) + show the API call
$ npx apiblaze billing balance # available · in use · grace
$ npx apiblaze consumer login # act as a consumer of your API
$ npx apiblaze team --new "Acme Corp" # new team, and switch to it
```
Run `npx apiblaze <command> --help` for a command's own flags and sub-commands.