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
- /llms.txt — concise machine guide
- /openapi.json (YAML) — full contract
- /agent-skill (alias /agent-skill.md) — copy-paste system prompt / skill
- /llms-full.txt — expanded guide
- /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
- 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.
- 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. - 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.
POST /api/v1/responseswith Bearer orx-api-key.- Always send
routing— prefersmartfor production. Recommended flow on a new domain/task:learningandlearning-allexist to teach the router the best path, so calibrate withrouting: "learning"first (learning-allonce for the full-catalog sweep), verifybanana_peel.learning_rankingon the completed run, then switch tosmart. 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 uselearning-allfor every production job. - Provide
input(task text) and/orurl. - 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— runnpx -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 /keysinvalid_routing— sendsmart, a named runner, a category pool, or a chainmissing_input— provideinputand/orurlunsafe_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— whennormalizeis enabled, passoutput_schema(or a schema viatext.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"— readbanana_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 siteslearning/learning-all— paid calibration: run first on a new domain/task, verifybanana_peel.learning_ranking, then switch tosmart- 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
- Set
BANANA_PEEL_API_KEY(aliasBANANAPEEL_API_KEY) or reuse~/.bananapeel/credentials. If absent,npx -y @banana-peel/cli init --agent --json - Load
/openapi.json(or this page +/llms.txt) - Call
POST /api/v1/responseswithrouting: smart - Branch on
error.code/hint/doc_url - Persist
id; list history via/api/v1/runs - Do not call
/api/v2/*(mock playground, not the product API) - Drop /agent-skill into your agent's skill / system prompt when automating further calls
Discovery files
- /robots.txt — allows crawlers and points at llms.txt
- /.well-known/ai-plugin.json — OpenAPI plugin manifest (real spec URL)