Developer Docs
Every image model behind one endpoint: your agent asks for an image; Pixfaro holds the provider accounts, keys, retries and format differences, and bills one prepaid balance.
https://api.pixfaro.comhttps://mcp.pixfaro.com/mcpllms.txtBase URL https://api.pixfaro.com. JSON everywhere. Errors use one envelope:
{ "error": { "code": "insufficient_balance", "message": "…", "request_id": "rq_a1c4f0" } }
Every response carries an x-request-id header — include it when you contact
support. Money is always a USD decimal string ("0.080", never a float).
Times are ISO 8601 UTC.
| Principal | How |
|---|---|
| API key | Authorization: Bearer pf_live_… |
| MCP | OAuth 2.1 at https://mcp.pixfaro.com (remote) or PIXFARO_KEY env (stdio) |
Keys are created on the dashboard. Scopes: generate
(default — image endpoints + balance) and full (adds billing, logos, and
brand-kit management).
Generate an image. Sync — the response is the finished image.
{
"model": "nano-banana-2",
"prompt": "a lighthouse at night, minimal flat style",
"aspect_ratio": "16:9",
"resolution": "1K",
"overlay": "default"
}
| Field | Required | Notes |
|---|---|---|
model |
yes | id from GET /v1/models |
prompt |
yes | 1–4000 chars |
aspect_ratio |
no | "w:h", e.g. "1:1" (default), "16:9", "9:16" |
resolution |
no | per-model tiers from GET /v1/models prices (default 1K) |
overlay |
no | corner branding: "default" applies your saved brand kit, or an explicit object (below) |
n > 1 and response_format other than "url" are not supported yet — one
image per request, delivered as a hosted URL (your agent's context never
carries base64).
200:
{
"id": "img_8f2a…", "url": "https://api.pixfaro.com/i/…", "model": "nano-banana-2",
"resolution": "1K", "latency_ms": 10400, "cost": "0.081", "balance_after": "12.32",
"overlay_applied": false, "request_id": "rq_a1c4f0"
}
Errors: 402 insufficient_balance (body includes balance, needed,
topup_url), 400 invalid_model / invalid_prompt / invalid_request,
409 model_disabled, 429 rate_limited (+ retry_after_s),
502 provider_failed — no charge, and the body says so explicitly:
"charged": false.
Brands a corner of the image with your handle or logo. Exactly one of text
(≤ 64 chars) or logo_id (a logo_… from POST /v1/logos):
{ "overlay": { "text": "@yourbrand", "position": "bottom-right", "opacity": 0.9 } }
Optional: position (default bottom-right), opacity (0.2–1.0), size,
margin, and for text font / weight / color ("auto" picks ink or paper
per corner brightness). Save your defaults once via PUT /v1/brand-kit, then
"overlay": "default" everywhere. A bad overlay fails the request before
generation — you are not charged.
Edit a previous generation with a natural-language instruction. Same response shape as generations.
{ "model": "nano-banana-2", "image": "img_8f2a…", "instruction": "make the sky darker" }
image takes an img_… id from a previous generation (URLs are not
accepted).instruction: 1–4000 chars — what to change; everything else stays put.aspect_ratio keeps the source image's shape (generations
default to 1:1).resolution inherits — and bills at — the source image's tier.Public, no auth. Cached ~5 min.
[{ "id": "nano-banana-2", "name": "Nano Banana 2",
"best_for": "general-purpose images: blog art, social posts, mockups",
"p50_ms": 10700, "p95_ms": 13600, "price": "0.080",
"prices": { "1K": "0.080", "2K": "0.121", "4K": "0.181" },
"mode": "sync", "enabled": true }]
price is the 1K figure; prices maps every supported resolution tier to its
retail price. enabled: false marks models that are coming soon (calling one
returns 409 model_disabled).
{ "balance": "12.32" }
full)| Endpoint | What |
|---|---|
POST /v1/topups |
{ "amount_usd": 25 } → { "checkout_url": … } (Stripe; integer 5–1000, default 10) |
GET/PATCH /v1/autoreload |
auto top-up: { enabled, threshold, amount, monthly_cap } — explicit opt-in |
POST /v1/logos |
upload a transparent PNG (≤ 1 MB, ≤ 2048px/side, ≤ 10 live logos) — raw body or multipart |
GET /v1/logos · DELETE /v1/logos/:id |
list / remove logos |
GET/PUT/DELETE /v1/brand-kit |
saved overlay defaults used by "overlay": "default" |
Top-ups, keys, and usage are also on the dashboard.
Public, no auth — report a generated image that violates our
acceptable use policy:
{ "image_url", "reason", "details"?, "reporter_email"? } — image_url must
be a Pixfaro-served image link (…/i/…).
Per key: 60 requests/min. Per account: 5 keys. 429 responses carry
retry_after_s. Need more? Ask — limits are raised case-by-case.
Path-versioned (/v1/). Additive changes (new optional fields) don't bump the
version; breaking changes go to /v2/ with 6 months of /v1/ support. The
x-pixfaro-deprecation header announces sunsets ahead of time.
One MCP connection gives your agent every major image model. Two ways in:
| Transport | For | How |
|---|---|---|
| Remote (streamable HTTP + OAuth 2.1) | claude.ai, Claude Desktop, any HTTP-capable client | add https://mcp.pixfaro.com/mcp — the client runs the OAuth flow, you sign in with your Pixfaro account |
| Local (stdio, npm) | Claude Code, Cursor, Windsurf, config-file setups | npx -y @pixfaro/mcp with PIXFARO_KEY in env |
Source: github.com/pixfaro/mcp — the client is intentionally small enough to read before you hand it a key.
Claude Code:
claude mcp add pixfaro -e PIXFARO_KEY=pf_live_… -- npx -y @pixfaro/mcp
Cursor / Windsurf / Claude Desktop (config file):
{
"mcpServers": {
"pixfaro": {
"command": "npx",
"args": ["-y", "@pixfaro/mcp"],
"env": { "PIXFARO_KEY": "pf_live_…" }
}
}
}
claude.ai / Claude Desktop connector (remote, no key in a file): add custom
connector with URL https://mcp.pixfaro.com/mcp.
| Tool | What it does |
|---|---|
generate_image |
prompt (+ optional model, aspect_ratio) → hosted image URL, with cost and remaining balance in the reply |
edit_image |
natural-language edit of a previous generation by its img_… id |
list_models |
live models with price, latency, and what each is best for |
get_balance |
current prepaid balance |
Replies are agent-readable text carrying a hosted URL — never base64, so your agent's context stays small. When the balance runs low, replies append a top-up warning.
| Variable | Meaning |
|---|---|
PIXFARO_KEY |
API key (pf_live_…) from pixfaro.com |
PIXFARO_API_URL |
endpoint override (staging / self-hosted) |
The same repo ships the pixfaro CLI for scripts, CI, and pipelines — the
literal one-command time-to-first-image:
export PIXFARO_KEY=pf_live_…
npx pixfaro gen "a lighthouse at night, minimal flat style" -a 16:9 -o cover.png
npx pixfaro edit img_8f2a… "make the sky darker" -o v2.png
npx pixfaro models
npx pixfaro balance
-o downloads the image; without it the CLI prints the hosted URL. A failed
download never swallows the URL you already paid for.