# 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.
