For AI agents

Call Banana Peel without hand-holding

Built for Cursor, Claude Code, Codex, and any HTTP-capable agent. One base URL, one create endpoint, one routing field (optional — defaults to smart, but send it explicitly), and errors that tell you exactly what to fix next.

Read these first

  1. /llms.txt — concise machine guide
  2. /openapi.json (YAML) — full contract
  3. /agent-skill (alias /agent-skill.md) — copy-paste system prompt / skill
  4. /llms-full.txt — expanded guide
  5. /docs/mcp — official MCP server (Claude Code / Cursor / Codex / VS Code / Windsurf / Claude Desktop)

Base URL

Production host: https://bananapeel.com. Set BANANA_PEEL_BASE if you deploy your own instance.

How to call Banana Peel as an agent

  1. Check for BANANA_PEEL_API_KEY / BANANAPEEL_API_KEY (whichever is set) or ~/.bananapeel/credentials. If a key exists, reuse it. Do not mint another account.
  2. If absent, follow /docs/agents/signup: run `npx -y @banana-peel/cli init --agent --json`. Banana Peel detects your agent environment and configures itself. Stdout is only status, claim_url, has_existing, and configured — never the API key. Never paste the key into chat. If npx/the CLI is unavailable, use the supported HTTP fallback (challenge → signup) documented on /docs/agents/signup. See Agent-native signup. Command: npx -y @banana-peel/cli init --agent --json. If npx is unavailable, the raw HTTP flow (GET /api/v1/agent-signup/challenge POST /api/v1/agent-signup) is a supported fallback.
  3. Never ask the human to create an account manually. Console /keys is an optional advanced path for humans who already have an account — not step 1 for agents.
  4. POST /api/v1/responses with Bearer or x-api-key.
  5. Always send routing — prefer smart for production. Recommended flow on a new domain/task: learning and learning-all exist to teach the router the best path, so calibrate with routing: "learning" first (learning-all once for the full-catalog sweep), verify banana_peel.learning_ranking on the completed run, then switch to smart. Smart works out of the box too — learning-first buys the best first-run reliability on that site, not a requirement. Learning bills every executed attempt ($20 default ceiling; account cap 3 concurrent Learning runs). Do not use learning-all for every production job.
  6. Provide input (task text) and/or url.
  7. On failure, branch on error.code / hint / doc_url — then retry.

Minimal request

export BANANA_PEEL_BASE=https://bananapeel.com
export BANANA_PEEL_API_KEY=bp_live_…

curl -s "$BANANA_PEEL_BASE/api/v1/responses" \
  -H "Authorization: Bearer $BANANA_PEEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "banana-peel",
    "input": "Extract the title from https://example.com",
    "routing": "smart"
  }'

Downloadable one-pagers: curl.sh, create-response.ts, create_response.py, thin helper bananapeel-client.ts.

Success shape

{
  "id": "resp_…",
  "object": "response",
  "status": "completed",
  "output_text": "…",
  "banana_peel": {
    "schema": "banana_peel.run/v1",
    "runner": "browserbase",
    "ranked_runners": ["browserbase", "steel", "…"],
    "routing": "smart",
    "timing_ms": 4200
  }
}

Inspect banana_peel.runner, ranked_runners, session links, and artifacts. Same keys for every runner (null when unused).

MFA / OTP

When a target site asks for MFA, 2FA, or an OTP, the run pauses immediately and asks the user for the code. It does not keep trying other runners.

Poll GET /api/v1/responses/:id until status is requires_action (or handle the response.requires_action webhook). MCP create_response waits until that pause and returns human_action_required plus required_action. Submit the code with POST /api/v1/responses/{id}/input { "code": "123456" } (or { "answer": "…" } for text/confirm). MCP: submit_input({ id, code }). Then keep polling until completed or failed. CAPTCHA and other bot-detection gates (reCAPTCHA, hCaptcha, Turnstile, DataDome, Cloudflare challenge, “prove you are human”) are solved, re-routed, or end blocked with reason bot_challenge. They never become a human text prompt. If the vault credential (or request totp_secret) includes a base32 TOTP seed, OTP asks are answered in-process and the run does not pause. Username/password alone is not enough — the run still pauses for the code. In Cursor / MCP: ASK THE HUMAN IN CHAT NOW for the site MFA/OTP code. Call submit_input with their code. Do not retry the task or pick another runner. Full guide: MFA / OTP.

Output normalization (+$0.10)

Optional post-run reshape into a JSON schema you define. Pass normalize: true with output_schema (or OpenAI text.format / response_format). Flat $0.10 on that run (every executed run is billed). Schema builder: Console → Normalize. Request example and estimate notes: Create a response → Output normalization.

Error recovery

{
  "error": {
    "message": "Missing or invalid Banana Peel API key. …",
    "type": "authentication_error",
    "code": "invalid_api_key",
    "param": null,
    "doc_url": "https://bananapeel.com/docs/agents",
    "hint": "npx -y @banana-peel/cli init --agent --json",
    "remediation": "Run `npx -y @banana-peel/cli init --agent --json` to mint a key, or if npx is unavailable use the supported HTTP fallback: GET /api/v1/agent-signup/challenge → solve the instruction → POST /api/v1/agent-signup with {challenge_id, challenge_answer} (see /docs/agents/signup). Then pass Authorization: Bearer bp_live_…"
  }
}
  • invalid_api_key — run npx -y @banana-peel/cli init --agent --json (or, when npx is unavailable, the HTTP signup fallback); do not ask the human to mint a key at /keys
  • invalid_routing — send smart, a named runner, a category pool, or a chain
  • missing_input — provide input and/or url
  • unsafe_url — target is private, link-local, metadata, or a name that resolves there (including nip.io / sslip.io). Same 400 on every path.
  • payload_too_large — create body over 1 MB. HTTP 413; no gRPC internals.
  • missing_output_schema — when normalize is enabled, pass output_schema (or a schema via text.format / response_format)
  • insufficient_credits (402) — top up Billing; runs debit runner price + 5% (+$0.10 when Output normalization is enabled)
  • HTTP 200 with status: "failed" — read banana_peel.error; retry with smart or another chain

Full reference: Errors.

Routing cheat sheet

  • smart — production; live benchmarks + fallback; works out of the box on never-seen sites
  • learning / learning-all — paid calibration: run first on a new domain/task, verify banana_peel.learning_ranking, then switch to smart
  • Named runners: browserbase, steel, browser-use, skyvern, hyperbrowser, playwright, deck, …
  • Chain: ["steel", "skyvern", "hyperbrowser"]
  • Categories SOC2 / HIPAA / EU — MVP fixed runner lists only, not attestation

Wrappers (only if you already use a provider SDK)

Browserbase sessions: /api/v1/sessions (not /api/wrappers/browserbase). Others under /api/wrappers/…. A session is a live browser you drive yourself over CDP — not a routed run (Runs vs. sessions). New work should use Responses. See wrappers.

Recommended integration checklist

  1. Set BANANA_PEEL_API_KEY (alias BANANAPEEL_API_KEY) or reuse ~/.bananapeel/credentials. If absent, npx -y @banana-peel/cli init --agent --json
  2. Load /openapi.json (or this page + /llms.txt)
  3. Call POST /api/v1/responses with routing: smart
  4. Branch on error.code / hint / doc_url
  5. Persist id; list history via /api/v1/runs
  6. Do not call /api/v2/* (mock playground, not the product API)
  7. Drop /agent-skill into your agent's skill / system prompt when automating further calls

Discovery files

Command Palette

Search for a command to run...