{
  "openapi": "3.1.1",
  "info": {
    "title": "QRBeam QR Code API",
    "version": "1.0.0",
    "description": "Generates a QR code as an SVG. One endpoint, no API key, no account.\n\nRate limited to 60 requests a minute per IP. The limiter is in-memory and per server instance, so treat the figure as a guide rather than a contract.\n\nCORS: every response carries `Access-Control-Allow-Origin: *` and `Cross-Origin-Resource-Policy: cross-origin`, because the endpoint is designed to be embedded directly as an `<img>` from another origin.\n\nTwo deliberate omissions, so you do not go looking for them:\n\n- **No PNG output.** The serverless runtime has no canvas implementation. Rasterise the SVG yourself if you need pixels.\n- **No logo parameter.** Embedding a caller-supplied image would mean fetching a URL or accepting a blob, which is an SSRF and stored-XSS vector. Logos are a browser-side feature of the web app.\n\nStructured payloads (Wi-Fi, vCard, calendar) must be encoded into `data` yourself. The field formats are published at https://qrcodebeam.com/capabilities.json, and the MCP server at https://qrcodebeam.com/api/mcp exposes a `build_qr_payload` tool that does it for you.",
    "contact": {
      "name": "Orbion Teknoloji",
      "email": "hello@qrcodebeam.com"
    },
    "license": {
      "name": "Free to use",
      "url": "https://qrcodebeam.com/terms"
    }
  },
  "servers": [
    {
      "url": "https://qrcodebeam.com"
    }
  ],
  "paths": {
    "/api/qr": {
      "get": {
        "operationId": "generateQrCodeFromQuery",
        "summary": "Generate a QR code",
        "description": "Returns an SVG. Cacheable, and safe to use directly as an image source.",
        "parameters": [
          {
            "name": "data",
            "in": "query",
            "required": true,
            "description": "The text to encode. Any string — a URL, a WIFI: payload, a vCard. Use /api/mcp's build_qr_payload, or the format tables in /api-docs, to construct structured payloads.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 2000,
              "description": "The text to encode. Any string — a URL, a WIFI: payload, a vCard. Use /api/mcp's build_qr_payload, or the format tables in /api-docs, to construct structured payloads.",
              "examples": [
                "https://example.com"
              ]
            }
          },
          {
            "name": "size",
            "in": "query",
            "required": false,
            "description": "Width and height of the rendered SVG, in pixels.",
            "schema": {
              "default": 512,
              "description": "Width and height of the rendered SVG, in pixels.",
              "type": "integer",
              "minimum": 64,
              "maximum": 2048
            }
          },
          {
            "name": "ecc",
            "in": "query",
            "required": false,
            "description": "Error correction level. L recovers ~7% of a damaged symbol, M ~15%, Q ~25%, H ~30%. Higher levels make the symbol denser.",
            "schema": {
              "default": "M",
              "description": "Error correction level. L recovers ~7% of a damaged symbol, M ~15%, Q ~25%, H ~30%. Higher levels make the symbol denser.",
              "type": "string",
              "enum": [
                "L",
                "M",
                "Q",
                "H"
              ]
            }
          },
          {
            "name": "margin",
            "in": "query",
            "required": false,
            "description": "Quiet zone width in modules. Four is the specification minimum; below that, scanners struggle to find the symbol.",
            "schema": {
              "default": 4,
              "description": "Quiet zone width in modules. Four is the specification minimum; below that, scanners struggle to find the symbol.",
              "type": "integer",
              "minimum": 0,
              "maximum": 16
            }
          },
          {
            "name": "dark",
            "in": "query",
            "required": false,
            "description": "Colour of the dark modules.",
            "schema": {
              "default": "#0f172a",
              "description": "Colour of the dark modules.",
              "type": "string",
              "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
            }
          },
          {
            "name": "light",
            "in": "query",
            "required": false,
            "description": "Background colour.",
            "schema": {
              "default": "#ffffff",
              "description": "Background colour.",
              "type": "string",
              "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
            }
          },
          {
            "name": "dotStyle",
            "in": "query",
            "required": false,
            "description": "Module shape.",
            "schema": {
              "default": "square",
              "description": "Module shape.",
              "type": "string",
              "enum": [
                "square",
                "rounded",
                "dots",
                "classy"
              ]
            }
          },
          {
            "name": "eyeStyle",
            "in": "query",
            "required": false,
            "description": "Finder pattern shape.",
            "schema": {
              "default": "square",
              "description": "Finder pattern shape.",
              "type": "string",
              "enum": [
                "square",
                "rounded",
                "circle",
                "leaf"
              ]
            }
          },
          {
            "name": "transparent",
            "in": "query",
            "required": false,
            "description": "Omit the background rectangle entirely.",
            "schema": {
              "default": false,
              "description": "Omit the background rectangle entirely.",
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The rendered QR code.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted per window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "Cache-Control": {
                "schema": {
                  "type": "string"
                },
                "description": "public, max-age=3600, s-maxage=86400"
              },
              "Access-Control-Allow-Origin": {
                "schema": {
                  "type": "string"
                }
              },
              "Cross-Origin-Resource-Policy": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "image/svg+xml": {
                "schema": {
                  "type": "string",
                  "contentMediaType": "image/svg+xml"
                }
              }
            }
          },
          "400": {
            "description": "A parameter failed validation.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted per window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The payload does not fit in a QR symbol at the requested error correction level.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted per window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted per window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted per window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "generateQrCodeFromJson",
        "summary": "Generate a QR code from a JSON body",
        "description": "Identical to GET. The body is capped at 8192 bytes, measured by reading the stream rather than trusting Content-Length.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QrRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The rendered QR code.",
            "content": {
              "image/svg+xml": {
                "schema": {
                  "type": "string",
                  "contentMediaType": "image/svg+xml"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON, or a parameter failed validation.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted per window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Request body too large.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted per window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The payload does not fit in a QR symbol.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted per window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted per window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted per window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests left in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "options": {
        "operationId": "qrPreflight",
        "summary": "CORS preflight",
        "description": "Returns 204 with the permitted methods and headers.",
        "responses": {
          "204": {
            "description": "Preflight response."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "QrRequest": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "data": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000,
            "description": "The text to encode. Any string — a URL, a WIFI: payload, a vCard. Use /api/mcp's build_qr_payload, or the format tables in /api-docs, to construct structured payloads.",
            "examples": [
              "https://example.com"
            ]
          },
          "size": {
            "default": 512,
            "description": "Width and height of the rendered SVG, in pixels.",
            "type": "integer",
            "minimum": 64,
            "maximum": 2048
          },
          "ecc": {
            "default": "M",
            "description": "Error correction level. L recovers ~7% of a damaged symbol, M ~15%, Q ~25%, H ~30%. Higher levels make the symbol denser.",
            "type": "string",
            "enum": [
              "L",
              "M",
              "Q",
              "H"
            ]
          },
          "margin": {
            "default": 4,
            "description": "Quiet zone width in modules. Four is the specification minimum; below that, scanners struggle to find the symbol.",
            "type": "integer",
            "minimum": 0,
            "maximum": 16
          },
          "dark": {
            "default": "#0f172a",
            "description": "Colour of the dark modules.",
            "type": "string",
            "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
          },
          "light": {
            "default": "#ffffff",
            "description": "Background colour.",
            "type": "string",
            "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
          },
          "dotStyle": {
            "default": "square",
            "description": "Module shape.",
            "type": "string",
            "enum": [
              "square",
              "rounded",
              "dots",
              "classy"
            ]
          },
          "eyeStyle": {
            "default": "square",
            "description": "Finder pattern shape.",
            "type": "string",
            "enum": [
              "square",
              "rounded",
              "circle",
              "leaf"
            ]
          },
          "transparent": {
            "default": false,
            "description": "Omit the background rectangle entirely.",
            "type": "boolean"
          }
        },
        "required": [
          "data",
          "size",
          "ecc",
          "margin",
          "dark",
          "light",
          "dotStyle",
          "eyeStyle",
          "transparent"
        ],
        "additionalProperties": false
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable failure reason."
          },
          "issues": {
            "type": "array",
            "description": "Present on validation failures only. Never echoes submitted values.",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        },
        "required": [
          "error"
        ]
      }
    }
  },
  "externalDocs": {
    "description": "Human-readable documentation",
    "url": "https://qrcodebeam.com/api-docs"
  }
}