# BananaSplit QR code generator for AI agents

Canonical guide: https://bananasplit.net/qr-code/developers/

OpenAPI 3.1: https://bananasplit.net/openapi.json

Endpoint: `https://bananasplit.net/api/qr-code`

## Direct answer

Use `format=json` as the default for agents. Fetch-only clients often reject `image/png` and `image/svg+xml` by content type. Fetch with `Accept: application/json`. `format=json` always returns JSON. Show the QR by decoding `png_base64`, writing `svg` to a file, or emitting `markdown` (it points at `/api/qr-code.png`). Do not paste raw Base64 or SVG source as the user-visible answer.

Canonical encoded example:

`https://bananasplit.net/api/qr-code?type=url&url=https%3A%2F%2Fferlar.pt&format=json`

Shortcut: `https://bananasplit.net/api/qr-code/url?url=https%3A%2F%2Fferlar.pt&format=json`

If your client cannot retrieve the response — including failed DNS resolution or a blocked fetch — that is your environment, not this API. Reply with a markdown link to `https://bananasplit.net/api/qr-code.png?type=url&url=...` and tell the user to open it. That URL returns PNG. Do not silently substitute a locally generated QR code.

Fetch-only agents should use `format=json` and should not start with `curl`. Prefer POST JSON for structured payloads and GET for simple URL/text QR codes. Do not use web.open, browser navigation, or URL-preview tools to retrieve the image when a direct HTTP/file-download tool is available. `format=png` and `format=svg` are for clients that can write binary.

The API default is `logo=none`. Pass `logo=banana` only when the user wants BananaSplit branding. Compact SVG can look blank in chat and ImageMagick; decode `png_base64` from JSON, or use `format=png` if your client can save files.

Percent-encode the target URL, including any nested query string. JSON responses are `application/json` with `Content-Disposition: inline; filename="bananasplit-qr-code.json"`, including `png_base64`, `png_data_url`, `image_url`, and `markdown`. PNG remains available with `format=png`. No API key is required. Codes are static, carry no watermark, have no scan limit, and do not depend on a BananaSplit redirect or subscription.

GET accepts `type=url`, `type=text`, raw `?data=`, plus `color`, `background`, `logo`, `corners`, `size` and `format=json|svg|png`. Use JSON `POST` for Wi-Fi, vCard, email, SMS, and any secret. Check `X-QR-Payload-Type`, `X-QR-Payload`, `X-QR-Logo` and `X-QR-Size` on success. JSON bodies omit `payload` for secrets.

## Structured types

| Type | Required field | Optional type fields |
| --- | --- | --- |
| `url` | `url` | — |
| `wifi` | `ssid` | `password`, `security`, `hidden` |
| `vcard` | `name` | `organization`, `jobTitle`, `phone`, `email`, `website` |
| `email` | `to` | `subject`, `message` |
| `sms` | `phone` | `message` |
| `text` | `text` | — |

All types also accept `color`, `background`, `logo`, `corners`, `size` and `download`.

## URL example

```bash
curl --get --fail \
  --data 'type=url' \
  --data-urlencode 'url=https://ferlar.pt' \
  --data 'logo=none' \
  --data 'format=png' \
  --data 'size=1024' \
  https://bananasplit.net/api/qr-code \
  --output bananasplit-qr-code.png
```

That is the same request as:

`https://bananasplit.net/api/qr-code?type=url&url=https%3A%2F%2Fferlar.pt&logo=none&format=png&size=1024`

## Wi-Fi example

Use `WPA` for WPA, WPA2 and WPA3, `WEP` only for legacy WEP, and `nopass` for an open network. The API escapes special characters in the SSID and password.

```bash
curl --fail https://bananasplit.net/api/qr-code \
  --header 'Content-Type: application/json' \
  --data '{
    "type": "wifi",
    "ssid": "Banana Guest",
    "password": "split-with-friends",
    "security": "WPA",
    "hidden": false,
    "logo": "none"
  }' \
  --output wifi-qr-code.svg
```

## vCard example

```bash
curl --fail https://bananasplit.net/api/qr-code \
  --header 'Content-Type: application/json' \
  --data '{
    "type": "vcard",
    "name": "Ana Split",
    "organization": "BananaSplit",
    "phone": "+351910000000",
    "email": "ana@example.com"
  }' \
  --output contact-qr-code.svg
```

## Appearance and response contract

- `color` and `background`: six-digit hex with or without `#`.
- `logo`: `banana` or `none`. Default is `none`; pass `banana` for BananaSplit branding.
- `corners`: `square` or `rounded`.
- `size`: integer from 128 to 2048; default 1024.
- `format`: `json`, `svg`, or `png`. JSON is the fetch-only agent format; PNG is binary preview; SVG is print.
- `download`: boolean; adds an attachment filename.
- Successful response: `200 application/json`, `200 image/png`, or `200 image/svg+xml` with `Cache-Control: private, no-store`, plus `X-QR-Payload-Type`, `X-QR-Logo`, `X-QR-Size` and `X-QR-Format`.
- Custom uploaded logos still require https://bananasplit.net/en/qr-code-generator/.

### Colour and built-in logo example

```bash
curl --fail https://bananasplit.net/api/qr-code \
  --header 'Content-Type: application/json' \
  --data '{
    "type": "url",
    "url": "https://bananasplit.net",
    "color": "1288C8",
    "background": "FFF9E8",
    "logo": "banana",
    "corners": "rounded",
    "size": 1024
  }' \
  --output coloured-qr-code.svg
```

Use `logo=banana` for the built-in BananaSplit mark or `logo=none` for no centre logo. The API does not accept arbitrary uploaded logos, base64 logo files, or remote logo URLs. Use the browser generator for custom logos.

## Privacy and limits

The endpoint receives the fields over HTTPS, processes them in memory, and does not store them in BananaSplit application storage. Static scans go directly to the encoded destination. Production requests are limited to 60 generated codes per minute per caller and Cloudflare edge location.

Treat Wi-Fi passwords and other secrets as sensitive. Use the API only when the user intends those values to be sent to the BananaSplit endpoint. The browser generator creates codes locally when client-side-only processing is required.

## Error handling

- `400`: fix the request using the stable JSON `code` and `hint`, then retry once.
- `413` or `422`: shorten the payload or encode a stable URL you control.
- `415`: send `Content-Type: application/json`.
- `429`: wait for `Retry-After`; do not retry in a tight loop.

Always scan-test the returned SVG in the final layout before a print run.

## ChatGPT MCP

Remote MCP endpoint: `https://bananasplit.net/mcp`

The server speaks Streamable HTTP and exposes one tool, `generate_qr`. It is the same BananaSplit QR generator: static codes, no stored payloads, no scan tracking, no redirect layer. ChatGPT custom apps can connect this URL in Developer Mode without a Plugin Directory listing. Public directory submission is optional later.

`generate_qr` accepts structured fields only (`type=url|wifi|vcard|email|sms|text`). It rejects raw `data` strings, `javascript:` / `data:` URLs, and unknown properties. Default `logo=none`. In ChatGPT the tool result opens the BananaSplit QR studio, so users can restyle and export PNG or SVG in the chat. Secret payloads stay off public GET URLs.

Discovery: https://bananasplit.net/.well-known/mcp.json

## More resources

- Skill: https://bananasplit.net/skills/bananasplit-qr-code/SKILL.md
- MCP: https://bananasplit.net/mcp
- Supported QR types: https://bananasplit.net/en/qr-code-types/
- Print guide: https://bananasplit.net/en/qr-code-print-size/
- Troubleshooting: https://bananasplit.net/en/qr-code-not-working/
- AI Catalog: https://bananasplit.net/.well-known/ai-catalog.json
