{
    "openapi": "3.1.0",
    "info": {
        "title": "scan.io.vn QR API",
        "version": "1.0.0",
        "summary": "Free QR code and VietQR bank transfer QR API. No API key.",
        "description": "Generate QR codes (link, text, Wi-Fi, vCard, email, SMS, phone, calendar, location) with custom colors and shapes, and VietQR bank transfer codes for Vietnamese bank accounts. Free, no key, no watermark; nothing you send is stored. Rate limit: 60 requests per minute per IP. The /dynamic-qr endpoints manage your own dynamic QR codes and need a personal API token (Authorization: Bearer sqr_…) from https://scan.io.vn/dashboard/api-tokens. Docs: https://scan.io.vn/developers",
        "contact": {
            "email": "support@scan.io.vn",
            "url": "https://scan.io.vn/developers"
        },
        "termsOfService": "https://scan.io.vn/dieu-khoan-su-dung"
    },
    "servers": [
        {
            "url": "https://scan.io.vn/api/v1"
        }
    ],
    "paths": {
        "/qr": {
            "get": {
                "operationId": "generateQrCode",
                "summary": "Generate a QR code",
                "description": "All options are query parameters, so the URL itself can be used as an image source.",
                "parameters": [
                    {
                        "name": "type",
                        "in": "query",
                        "description": "Content type. Omit it to encode `data` exactly as given.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "link",
                                "text",
                                "wifi",
                                "vcard",
                                "email",
                                "sms",
                                "phone",
                                "calendar",
                                "geo"
                            ]
                        }
                    },
                    {
                        "name": "data",
                        "in": "query",
                        "description": "Raw content to encode (text, or a link for type=link). Required when no structured type is used.",
                        "schema": {
                            "type": "string",
                            "maxLength": 1273
                        },
                        "example": "https://scan.io.vn"
                    },
                    {
                        "name": "url",
                        "in": "query",
                        "description": "Link to open (type=link) or the website on a business card (type=vcard). (type: link, vcard)",
                        "schema": {
                            "type": "string",
                            "format": "uri"
                        }
                    },
                    {
                        "name": "ssid",
                        "in": "query",
                        "description": "Wi-Fi network name. (type: wifi)",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "password",
                        "in": "query",
                        "description": "Wi-Fi password (ignored when security=nopass). (type: wifi)",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "security",
                        "in": "query",
                        "description": "Wi-Fi security: WPA (also WPA2/WPA3), WEP or nopass. (type: wifi)",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "WPA",
                                "WEP",
                                "nopass"
                            ],
                            "default": "WPA"
                        }
                    },
                    {
                        "name": "hidden",
                        "in": "query",
                        "description": "The network does not broadcast its name. (type: wifi)",
                        "schema": {
                            "type": "boolean",
                            "default": false
                        }
                    },
                    {
                        "name": "first_name",
                        "in": "query",
                        "description": "First name (first or last name is required). (type: vcard)",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "last_name",
                        "in": "query",
                        "description": "Last name. (type: vcard)",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "org",
                        "in": "query",
                        "description": "Company or organisation. (type: vcard)",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "email",
                        "in": "query",
                        "description": "Email address on the business card. (type: vcard)",
                        "schema": {
                            "type": "string",
                            "format": "email"
                        }
                    },
                    {
                        "name": "phone",
                        "in": "query",
                        "description": "Phone number. (type: vcard, sms, phone)",
                        "schema": {
                            "type": "string"
                        },
                        "example": "+84901234567"
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "description": "Recipient email address. (type: email)",
                        "schema": {
                            "type": "string",
                            "format": "email"
                        }
                    },
                    {
                        "name": "subject",
                        "in": "query",
                        "description": "Email subject. (type: email)",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "body",
                        "in": "query",
                        "description": "Email body. (type: email)",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "message",
                        "in": "query",
                        "description": "Pre-filled text message. (type: sms)",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "title",
                        "in": "query",
                        "description": "Event title. (type: calendar)",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "start",
                        "in": "query",
                        "description": "Event start, local time (YYYY-MM-DDTHH:MM). (type: calendar)",
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        },
                        "example": "2026-10-01T09:00"
                    },
                    {
                        "name": "end",
                        "in": "query",
                        "description": "Event end, local time. (type: calendar)",
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        }
                    },
                    {
                        "name": "location",
                        "in": "query",
                        "description": "Event location. (type: calendar)",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "description",
                        "in": "query",
                        "description": "Event description. (type: calendar)",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "lat",
                        "in": "query",
                        "description": "Latitude. (type: geo)",
                        "schema": {
                            "type": "number",
                            "minimum": -90,
                            "maximum": 90
                        }
                    },
                    {
                        "name": "lng",
                        "in": "query",
                        "description": "Longitude. (type: geo)",
                        "schema": {
                            "type": "number",
                            "minimum": -180,
                            "maximum": 180
                        }
                    },
                    {
                        "name": "format",
                        "in": "query",
                        "description": "Image format.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "svg",
                                "png",
                                "webp"
                            ],
                            "default": "png"
                        }
                    },
                    {
                        "name": "size",
                        "in": "query",
                        "description": "Width and height in pixels, border included.",
                        "schema": {
                            "type": "integer",
                            "minimum": 128,
                            "maximum": 2048,
                            "default": 512
                        }
                    },
                    {
                        "name": "border",
                        "in": "query",
                        "description": "Quiet zone around the code: 0 none, 2 thin, 4 medium, 6 thick.",
                        "schema": {
                            "type": "integer",
                            "enum": [
                                0,
                                2,
                                4,
                                6
                            ],
                            "default": 4
                        }
                    },
                    {
                        "name": "color",
                        "in": "query",
                        "description": "Module color (hex).",
                        "schema": {
                            "type": "string",
                            "default": "#000000"
                        }
                    },
                    {
                        "name": "background",
                        "in": "query",
                        "description": "Background color (hex).",
                        "schema": {
                            "type": "string",
                            "default": "#ffffff"
                        }
                    },
                    {
                        "name": "eye_color",
                        "in": "query",
                        "description": "Color of the three corner eyes (hex). Defaults to the module color.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "module_shape",
                        "in": "query",
                        "description": "Shape of the modules.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "square",
                                "rounded",
                                "dots"
                            ],
                            "default": "square"
                        }
                    },
                    {
                        "name": "eye_frame_shape",
                        "in": "query",
                        "description": "Shape of the corner eye frames.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "square",
                                "rounded",
                                "circle"
                            ],
                            "default": "square"
                        }
                    },
                    {
                        "name": "eye_pupil_shape",
                        "in": "query",
                        "description": "Shape of the corner eye pupils.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "square",
                                "rounded",
                                "circle"
                            ],
                            "default": "square"
                        }
                    },
                    {
                        "name": "error_correction",
                        "in": "query",
                        "description": "Error correction level: high (~30% of the code can be damaged or covered), quartile (~25%), medium (~15%) or low (~7%). Lower levels give fewer, larger modules; keep high or quartile with a center logo.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "high",
                                "quartile",
                                "medium",
                                "low"
                            ],
                            "default": "high"
                        }
                    },
                    {
                        "name": "label",
                        "in": "query",
                        "description": "Caption drawn below the code.",
                        "schema": {
                            "type": "string",
                            "maxLength": 100
                        }
                    },
                    {
                        "name": "label_size",
                        "in": "query",
                        "description": "Caption font size.",
                        "schema": {
                            "type": "integer",
                            "minimum": 8,
                            "maximum": 72,
                            "default": 20
                        }
                    },
                    {
                        "name": "label_align",
                        "in": "query",
                        "description": "Caption alignment.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "left",
                                "center",
                                "right"
                            ],
                            "default": "center"
                        }
                    },
                    {
                        "name": "label_color",
                        "in": "query",
                        "description": "Caption color (hex).",
                        "schema": {
                            "type": "string",
                            "default": "#000000"
                        }
                    },
                    {
                        "name": "logo_url",
                        "in": "query",
                        "description": "Public https URL of a PNG, JPG, GIF or WebP logo (up to 2 MB) for the center. Downloaded by our server and cached for an hour.",
                        "schema": {
                            "type": "string",
                            "format": "uri",
                            "maxLength": 2048
                        }
                    },
                    {
                        "name": "logo_size",
                        "in": "query",
                        "description": "Width of the center logo in pixels (logo from logo_url, or uploaded as a multipart `logo` file on POST).",
                        "schema": {
                            "type": "integer",
                            "minimum": 16,
                            "maximum": 1024,
                            "default": 40
                        }
                    },
                    {
                        "name": "response",
                        "in": "query",
                        "description": "image returns the file itself; json returns the encoded content and the image as a base64 data URI.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "image",
                                "json"
                            ],
                            "default": "image"
                        }
                    },
                    {
                        "name": "download",
                        "in": "query",
                        "description": "Send the image as an attachment (Content-Disposition) instead of inline.",
                        "schema": {
                            "type": "boolean",
                            "default": false
                        }
                    },
                    {
                        "name": "filename",
                        "in": "query",
                        "description": "File name without extension for downloads (letters, digits, dot, dash, underscore).",
                        "schema": {
                            "type": "string",
                            "maxLength": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The image (default) or, with response=json, a JSON envelope.",
                        "content": {
                            "image/png": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            },
                            "image/svg+xml": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            },
                            "image/webp": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            },
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/QrResult"
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            },
            "post": {
                "operationId": "generateQrCodeWithLogo",
                "summary": "Generate a QR code (JSON or multipart, optional logo upload)",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "enum": [
                                            "link",
                                            "text",
                                            "wifi",
                                            "vcard",
                                            "email",
                                            "sms",
                                            "phone",
                                            "calendar",
                                            "geo"
                                        ],
                                        "description": "Content type. Omit it to encode `data` exactly as given."
                                    },
                                    "data": {
                                        "type": "string",
                                        "maxLength": 1273,
                                        "description": "Raw content to encode (text, or a link for type=link). Required when no structured type is used."
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to open (type=link) or the website on a business card (type=vcard). (type: link, vcard)"
                                    },
                                    "ssid": {
                                        "type": "string",
                                        "description": "Wi-Fi network name. (type: wifi)"
                                    },
                                    "password": {
                                        "type": "string",
                                        "description": "Wi-Fi password (ignored when security=nopass). (type: wifi)"
                                    },
                                    "security": {
                                        "type": "string",
                                        "enum": [
                                            "WPA",
                                            "WEP",
                                            "nopass"
                                        ],
                                        "default": "WPA",
                                        "description": "Wi-Fi security: WPA (also WPA2/WPA3), WEP or nopass. (type: wifi)"
                                    },
                                    "hidden": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "The network does not broadcast its name. (type: wifi)"
                                    },
                                    "first_name": {
                                        "type": "string",
                                        "description": "First name (first or last name is required). (type: vcard)"
                                    },
                                    "last_name": {
                                        "type": "string",
                                        "description": "Last name. (type: vcard)"
                                    },
                                    "org": {
                                        "type": "string",
                                        "description": "Company or organisation. (type: vcard)"
                                    },
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "Email address on the business card. (type: vcard)"
                                    },
                                    "phone": {
                                        "type": "string",
                                        "description": "Phone number. (type: vcard, sms, phone)"
                                    },
                                    "to": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "Recipient email address. (type: email)"
                                    },
                                    "subject": {
                                        "type": "string",
                                        "description": "Email subject. (type: email)"
                                    },
                                    "body": {
                                        "type": "string",
                                        "description": "Email body. (type: email)"
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "Pre-filled text message. (type: sms)"
                                    },
                                    "title": {
                                        "type": "string",
                                        "description": "Event title. (type: calendar)"
                                    },
                                    "start": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Event start, local time (YYYY-MM-DDTHH:MM). (type: calendar)"
                                    },
                                    "end": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Event end, local time. (type: calendar)"
                                    },
                                    "location": {
                                        "type": "string",
                                        "description": "Event location. (type: calendar)"
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "Event description. (type: calendar)"
                                    },
                                    "lat": {
                                        "type": "number",
                                        "minimum": -90,
                                        "maximum": 90,
                                        "description": "Latitude. (type: geo)"
                                    },
                                    "lng": {
                                        "type": "number",
                                        "minimum": -180,
                                        "maximum": 180,
                                        "description": "Longitude. (type: geo)"
                                    },
                                    "format": {
                                        "type": "string",
                                        "enum": [
                                            "svg",
                                            "png",
                                            "webp"
                                        ],
                                        "default": "png",
                                        "description": "Image format."
                                    },
                                    "size": {
                                        "type": "integer",
                                        "minimum": 128,
                                        "maximum": 2048,
                                        "default": 512,
                                        "description": "Width and height in pixels, border included."
                                    },
                                    "border": {
                                        "type": "integer",
                                        "enum": [
                                            0,
                                            2,
                                            4,
                                            6
                                        ],
                                        "default": 4,
                                        "description": "Quiet zone around the code: 0 none, 2 thin, 4 medium, 6 thick."
                                    },
                                    "color": {
                                        "type": "string",
                                        "default": "#000000",
                                        "description": "Module color (hex)."
                                    },
                                    "background": {
                                        "type": "string",
                                        "default": "#ffffff",
                                        "description": "Background color (hex)."
                                    },
                                    "eye_color": {
                                        "type": "string",
                                        "description": "Color of the three corner eyes (hex). Defaults to the module color."
                                    },
                                    "module_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "dots"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the modules."
                                    },
                                    "eye_frame_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "circle"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the corner eye frames."
                                    },
                                    "eye_pupil_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "circle"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the corner eye pupils."
                                    },
                                    "error_correction": {
                                        "type": "string",
                                        "enum": [
                                            "high",
                                            "quartile",
                                            "medium",
                                            "low"
                                        ],
                                        "default": "high",
                                        "description": "Error correction level: high (~30% of the code can be damaged or covered), quartile (~25%), medium (~15%) or low (~7%). Lower levels give fewer, larger modules; keep high or quartile with a center logo."
                                    },
                                    "label": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "Caption drawn below the code."
                                    },
                                    "label_size": {
                                        "type": "integer",
                                        "minimum": 8,
                                        "maximum": 72,
                                        "default": 20,
                                        "description": "Caption font size."
                                    },
                                    "label_align": {
                                        "type": "string",
                                        "enum": [
                                            "left",
                                            "center",
                                            "right"
                                        ],
                                        "default": "center",
                                        "description": "Caption alignment."
                                    },
                                    "label_color": {
                                        "type": "string",
                                        "default": "#000000",
                                        "description": "Caption color (hex)."
                                    },
                                    "logo_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Public https URL of a PNG, JPG, GIF or WebP logo (up to 2 MB) for the center. Downloaded by our server and cached for an hour."
                                    },
                                    "logo_size": {
                                        "type": "integer",
                                        "minimum": 16,
                                        "maximum": 1024,
                                        "default": 40,
                                        "description": "Width of the center logo in pixels (logo from logo_url, or uploaded as a multipart `logo` file on POST)."
                                    },
                                    "response": {
                                        "type": "string",
                                        "enum": [
                                            "image",
                                            "json"
                                        ],
                                        "default": "image",
                                        "description": "image returns the file itself; json returns the encoded content and the image as a base64 data URI."
                                    },
                                    "download": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "Send the image as an attachment (Content-Disposition) instead of inline."
                                    },
                                    "filename": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "File name without extension for downloads (letters, digits, dot, dash, underscore)."
                                    }
                                }
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "enum": [
                                            "link",
                                            "text",
                                            "wifi",
                                            "vcard",
                                            "email",
                                            "sms",
                                            "phone",
                                            "calendar",
                                            "geo"
                                        ],
                                        "description": "Content type. Omit it to encode `data` exactly as given."
                                    },
                                    "data": {
                                        "type": "string",
                                        "maxLength": 1273,
                                        "description": "Raw content to encode (text, or a link for type=link). Required when no structured type is used."
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to open (type=link) or the website on a business card (type=vcard). (type: link, vcard)"
                                    },
                                    "ssid": {
                                        "type": "string",
                                        "description": "Wi-Fi network name. (type: wifi)"
                                    },
                                    "password": {
                                        "type": "string",
                                        "description": "Wi-Fi password (ignored when security=nopass). (type: wifi)"
                                    },
                                    "security": {
                                        "type": "string",
                                        "enum": [
                                            "WPA",
                                            "WEP",
                                            "nopass"
                                        ],
                                        "default": "WPA",
                                        "description": "Wi-Fi security: WPA (also WPA2/WPA3), WEP or nopass. (type: wifi)"
                                    },
                                    "hidden": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "The network does not broadcast its name. (type: wifi)"
                                    },
                                    "first_name": {
                                        "type": "string",
                                        "description": "First name (first or last name is required). (type: vcard)"
                                    },
                                    "last_name": {
                                        "type": "string",
                                        "description": "Last name. (type: vcard)"
                                    },
                                    "org": {
                                        "type": "string",
                                        "description": "Company or organisation. (type: vcard)"
                                    },
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "Email address on the business card. (type: vcard)"
                                    },
                                    "phone": {
                                        "type": "string",
                                        "description": "Phone number. (type: vcard, sms, phone)"
                                    },
                                    "to": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "Recipient email address. (type: email)"
                                    },
                                    "subject": {
                                        "type": "string",
                                        "description": "Email subject. (type: email)"
                                    },
                                    "body": {
                                        "type": "string",
                                        "description": "Email body. (type: email)"
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "Pre-filled text message. (type: sms)"
                                    },
                                    "title": {
                                        "type": "string",
                                        "description": "Event title. (type: calendar)"
                                    },
                                    "start": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Event start, local time (YYYY-MM-DDTHH:MM). (type: calendar)"
                                    },
                                    "end": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Event end, local time. (type: calendar)"
                                    },
                                    "location": {
                                        "type": "string",
                                        "description": "Event location. (type: calendar)"
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "Event description. (type: calendar)"
                                    },
                                    "lat": {
                                        "type": "number",
                                        "minimum": -90,
                                        "maximum": 90,
                                        "description": "Latitude. (type: geo)"
                                    },
                                    "lng": {
                                        "type": "number",
                                        "minimum": -180,
                                        "maximum": 180,
                                        "description": "Longitude. (type: geo)"
                                    },
                                    "format": {
                                        "type": "string",
                                        "enum": [
                                            "svg",
                                            "png",
                                            "webp"
                                        ],
                                        "default": "png",
                                        "description": "Image format."
                                    },
                                    "size": {
                                        "type": "integer",
                                        "minimum": 128,
                                        "maximum": 2048,
                                        "default": 512,
                                        "description": "Width and height in pixels, border included."
                                    },
                                    "border": {
                                        "type": "integer",
                                        "enum": [
                                            0,
                                            2,
                                            4,
                                            6
                                        ],
                                        "default": 4,
                                        "description": "Quiet zone around the code: 0 none, 2 thin, 4 medium, 6 thick."
                                    },
                                    "color": {
                                        "type": "string",
                                        "default": "#000000",
                                        "description": "Module color (hex)."
                                    },
                                    "background": {
                                        "type": "string",
                                        "default": "#ffffff",
                                        "description": "Background color (hex)."
                                    },
                                    "eye_color": {
                                        "type": "string",
                                        "description": "Color of the three corner eyes (hex). Defaults to the module color."
                                    },
                                    "module_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "dots"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the modules."
                                    },
                                    "eye_frame_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "circle"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the corner eye frames."
                                    },
                                    "eye_pupil_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "circle"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the corner eye pupils."
                                    },
                                    "error_correction": {
                                        "type": "string",
                                        "enum": [
                                            "high",
                                            "quartile",
                                            "medium",
                                            "low"
                                        ],
                                        "default": "high",
                                        "description": "Error correction level: high (~30% of the code can be damaged or covered), quartile (~25%), medium (~15%) or low (~7%). Lower levels give fewer, larger modules; keep high or quartile with a center logo."
                                    },
                                    "label": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "Caption drawn below the code."
                                    },
                                    "label_size": {
                                        "type": "integer",
                                        "minimum": 8,
                                        "maximum": 72,
                                        "default": 20,
                                        "description": "Caption font size."
                                    },
                                    "label_align": {
                                        "type": "string",
                                        "enum": [
                                            "left",
                                            "center",
                                            "right"
                                        ],
                                        "default": "center",
                                        "description": "Caption alignment."
                                    },
                                    "label_color": {
                                        "type": "string",
                                        "default": "#000000",
                                        "description": "Caption color (hex)."
                                    },
                                    "logo_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Public https URL of a PNG, JPG, GIF or WebP logo (up to 2 MB) for the center. Downloaded by our server and cached for an hour."
                                    },
                                    "logo_size": {
                                        "type": "integer",
                                        "minimum": 16,
                                        "maximum": 1024,
                                        "default": 40,
                                        "description": "Width of the center logo in pixels (logo from logo_url, or uploaded as a multipart `logo` file on POST)."
                                    },
                                    "response": {
                                        "type": "string",
                                        "enum": [
                                            "image",
                                            "json"
                                        ],
                                        "default": "image",
                                        "description": "image returns the file itself; json returns the encoded content and the image as a base64 data URI."
                                    },
                                    "download": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "Send the image as an attachment (Content-Disposition) instead of inline."
                                    },
                                    "filename": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "File name without extension for downloads (letters, digits, dot, dash, underscore)."
                                    },
                                    "logo": {
                                        "type": "string",
                                        "format": "binary",
                                        "description": "Center logo: PNG, JPG, GIF or WebP, up to 2 MB."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The image (default) or, with response=json, a JSON envelope.",
                        "content": {
                            "image/png": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            },
                            "image/svg+xml": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            },
                            "image/webp": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            },
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/QrResult"
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/qr/batch": {
            "post": {
                "operationId": "generateQrCodesBatch",
                "summary": "Generate up to 50 QR codes with one design (ZIP or JSON)",
                "description": "items: strings (encoded as-is) or objects with the content fields of /qr and an optional filename. Design fields apply to every code. With multipart (logo upload) send items as a JSON string. Rate limit: 10 batches per minute per IP.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "items"
                                ],
                                "properties": {
                                    "items": {
                                        "type": "array",
                                        "minItems": 1,
                                        "maxItems": 50,
                                        "items": {
                                            "oneOf": [
                                                {
                                                    "type": "string"
                                                },
                                                {
                                                    "type": "object",
                                                    "properties": {
                                                        "type": {
                                                            "type": "string",
                                                            "enum": [
                                                                "link",
                                                                "text",
                                                                "wifi",
                                                                "vcard",
                                                                "email",
                                                                "sms",
                                                                "phone",
                                                                "calendar",
                                                                "geo"
                                                            ],
                                                            "description": "Content type. Omit it to encode `data` exactly as given."
                                                        },
                                                        "data": {
                                                            "type": "string",
                                                            "maxLength": 1273,
                                                            "description": "Raw content to encode (text, or a link for type=link). Required when no structured type is used."
                                                        },
                                                        "url": {
                                                            "type": "string",
                                                            "format": "uri",
                                                            "description": "Link to open (type=link) or the website on a business card (type=vcard). (type: link, vcard)"
                                                        },
                                                        "ssid": {
                                                            "type": "string",
                                                            "description": "Wi-Fi network name. (type: wifi)"
                                                        },
                                                        "password": {
                                                            "type": "string",
                                                            "description": "Wi-Fi password (ignored when security=nopass). (type: wifi)"
                                                        },
                                                        "security": {
                                                            "type": "string",
                                                            "enum": [
                                                                "WPA",
                                                                "WEP",
                                                                "nopass"
                                                            ],
                                                            "default": "WPA",
                                                            "description": "Wi-Fi security: WPA (also WPA2/WPA3), WEP or nopass. (type: wifi)"
                                                        },
                                                        "hidden": {
                                                            "type": "boolean",
                                                            "default": false,
                                                            "description": "The network does not broadcast its name. (type: wifi)"
                                                        },
                                                        "first_name": {
                                                            "type": "string",
                                                            "description": "First name (first or last name is required). (type: vcard)"
                                                        },
                                                        "last_name": {
                                                            "type": "string",
                                                            "description": "Last name. (type: vcard)"
                                                        },
                                                        "org": {
                                                            "type": "string",
                                                            "description": "Company or organisation. (type: vcard)"
                                                        },
                                                        "email": {
                                                            "type": "string",
                                                            "format": "email",
                                                            "description": "Email address on the business card. (type: vcard)"
                                                        },
                                                        "phone": {
                                                            "type": "string",
                                                            "description": "Phone number. (type: vcard, sms, phone)"
                                                        },
                                                        "to": {
                                                            "type": "string",
                                                            "format": "email",
                                                            "description": "Recipient email address. (type: email)"
                                                        },
                                                        "subject": {
                                                            "type": "string",
                                                            "description": "Email subject. (type: email)"
                                                        },
                                                        "body": {
                                                            "type": "string",
                                                            "description": "Email body. (type: email)"
                                                        },
                                                        "message": {
                                                            "type": "string",
                                                            "description": "Pre-filled text message. (type: sms)"
                                                        },
                                                        "title": {
                                                            "type": "string",
                                                            "description": "Event title. (type: calendar)"
                                                        },
                                                        "start": {
                                                            "type": "string",
                                                            "format": "date-time",
                                                            "description": "Event start, local time (YYYY-MM-DDTHH:MM). (type: calendar)"
                                                        },
                                                        "end": {
                                                            "type": "string",
                                                            "format": "date-time",
                                                            "description": "Event end, local time. (type: calendar)"
                                                        },
                                                        "location": {
                                                            "type": "string",
                                                            "description": "Event location. (type: calendar)"
                                                        },
                                                        "description": {
                                                            "type": "string",
                                                            "description": "Event description. (type: calendar)"
                                                        },
                                                        "lat": {
                                                            "type": "number",
                                                            "minimum": -90,
                                                            "maximum": 90,
                                                            "description": "Latitude. (type: geo)"
                                                        },
                                                        "lng": {
                                                            "type": "number",
                                                            "minimum": -180,
                                                            "maximum": 180,
                                                            "description": "Longitude. (type: geo)"
                                                        },
                                                        "filename": {
                                                            "type": "string",
                                                            "maxLength": 100
                                                        }
                                                    }
                                                }
                                            ]
                                        }
                                    },
                                    "format": {
                                        "type": "string",
                                        "enum": [
                                            "svg",
                                            "png",
                                            "webp"
                                        ],
                                        "default": "png",
                                        "description": "Image format."
                                    },
                                    "size": {
                                        "type": "integer",
                                        "minimum": 128,
                                        "maximum": 2048,
                                        "default": 512,
                                        "description": "Width and height in pixels, border included."
                                    },
                                    "border": {
                                        "type": "integer",
                                        "enum": [
                                            0,
                                            2,
                                            4,
                                            6
                                        ],
                                        "default": 4,
                                        "description": "Quiet zone around the code: 0 none, 2 thin, 4 medium, 6 thick."
                                    },
                                    "color": {
                                        "type": "string",
                                        "default": "#000000",
                                        "description": "Module color (hex)."
                                    },
                                    "background": {
                                        "type": "string",
                                        "default": "#ffffff",
                                        "description": "Background color (hex)."
                                    },
                                    "eye_color": {
                                        "type": "string",
                                        "description": "Color of the three corner eyes (hex). Defaults to the module color."
                                    },
                                    "module_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "dots"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the modules."
                                    },
                                    "eye_frame_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "circle"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the corner eye frames."
                                    },
                                    "eye_pupil_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "circle"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the corner eye pupils."
                                    },
                                    "error_correction": {
                                        "type": "string",
                                        "enum": [
                                            "high",
                                            "quartile",
                                            "medium",
                                            "low"
                                        ],
                                        "default": "high",
                                        "description": "Error correction level: high (~30% of the code can be damaged or covered), quartile (~25%), medium (~15%) or low (~7%). Lower levels give fewer, larger modules; keep high or quartile with a center logo."
                                    },
                                    "label": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "Caption drawn below the code."
                                    },
                                    "label_size": {
                                        "type": "integer",
                                        "minimum": 8,
                                        "maximum": 72,
                                        "default": 20,
                                        "description": "Caption font size."
                                    },
                                    "label_align": {
                                        "type": "string",
                                        "enum": [
                                            "left",
                                            "center",
                                            "right"
                                        ],
                                        "default": "center",
                                        "description": "Caption alignment."
                                    },
                                    "label_color": {
                                        "type": "string",
                                        "default": "#000000",
                                        "description": "Caption color (hex)."
                                    },
                                    "logo_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Public https URL of a PNG, JPG, GIF or WebP logo (up to 2 MB) for the center. Downloaded by our server and cached for an hour."
                                    },
                                    "logo_size": {
                                        "type": "integer",
                                        "minimum": 16,
                                        "maximum": 1024,
                                        "default": 40,
                                        "description": "Width of the center logo in pixels (logo from logo_url, or uploaded as a multipart `logo` file on POST)."
                                    },
                                    "response": {
                                        "type": "string",
                                        "enum": [
                                            "image",
                                            "json"
                                        ],
                                        "default": "image",
                                        "description": "image returns the file itself; json returns the encoded content and the image as a base64 data URI."
                                    },
                                    "download": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "Send the image as an attachment (Content-Disposition) instead of inline."
                                    },
                                    "filename": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "File name without extension for downloads (letters, digits, dot, dash, underscore)."
                                    }
                                }
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "items"
                                ],
                                "properties": {
                                    "items": {
                                        "type": "string",
                                        "description": "JSON array of items."
                                    },
                                    "logo": {
                                        "type": "string",
                                        "format": "binary",
                                        "description": "Center logo: PNG, JPG, GIF or WebP, up to 2 MB."
                                    },
                                    "format": {
                                        "type": "string",
                                        "enum": [
                                            "svg",
                                            "png",
                                            "webp"
                                        ],
                                        "default": "png",
                                        "description": "Image format."
                                    },
                                    "size": {
                                        "type": "integer",
                                        "minimum": 128,
                                        "maximum": 2048,
                                        "default": 512,
                                        "description": "Width and height in pixels, border included."
                                    },
                                    "border": {
                                        "type": "integer",
                                        "enum": [
                                            0,
                                            2,
                                            4,
                                            6
                                        ],
                                        "default": 4,
                                        "description": "Quiet zone around the code: 0 none, 2 thin, 4 medium, 6 thick."
                                    },
                                    "color": {
                                        "type": "string",
                                        "default": "#000000",
                                        "description": "Module color (hex)."
                                    },
                                    "background": {
                                        "type": "string",
                                        "default": "#ffffff",
                                        "description": "Background color (hex)."
                                    },
                                    "eye_color": {
                                        "type": "string",
                                        "description": "Color of the three corner eyes (hex). Defaults to the module color."
                                    },
                                    "module_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "dots"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the modules."
                                    },
                                    "eye_frame_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "circle"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the corner eye frames."
                                    },
                                    "eye_pupil_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "circle"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the corner eye pupils."
                                    },
                                    "error_correction": {
                                        "type": "string",
                                        "enum": [
                                            "high",
                                            "quartile",
                                            "medium",
                                            "low"
                                        ],
                                        "default": "high",
                                        "description": "Error correction level: high (~30% of the code can be damaged or covered), quartile (~25%), medium (~15%) or low (~7%). Lower levels give fewer, larger modules; keep high or quartile with a center logo."
                                    },
                                    "label": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "Caption drawn below the code."
                                    },
                                    "label_size": {
                                        "type": "integer",
                                        "minimum": 8,
                                        "maximum": 72,
                                        "default": 20,
                                        "description": "Caption font size."
                                    },
                                    "label_align": {
                                        "type": "string",
                                        "enum": [
                                            "left",
                                            "center",
                                            "right"
                                        ],
                                        "default": "center",
                                        "description": "Caption alignment."
                                    },
                                    "label_color": {
                                        "type": "string",
                                        "default": "#000000",
                                        "description": "Caption color (hex)."
                                    },
                                    "logo_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Public https URL of a PNG, JPG, GIF or WebP logo (up to 2 MB) for the center. Downloaded by our server and cached for an hour."
                                    },
                                    "logo_size": {
                                        "type": "integer",
                                        "minimum": 16,
                                        "maximum": 1024,
                                        "default": 40,
                                        "description": "Width of the center logo in pixels (logo from logo_url, or uploaded as a multipart `logo` file on POST)."
                                    },
                                    "response": {
                                        "type": "string",
                                        "enum": [
                                            "image",
                                            "json"
                                        ],
                                        "default": "image",
                                        "description": "image returns the file itself; json returns the encoded content and the image as a base64 data URI."
                                    },
                                    "download": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "Send the image as an attachment (Content-Disposition) instead of inline."
                                    },
                                    "filename": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "File name without extension for downloads (letters, digits, dot, dash, underscore)."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "A ZIP of the images, or with response=json the images as data URIs.",
                        "content": {
                            "application/zip": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            },
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/vietqr": {
            "get": {
                "operationId": "generateVietQr",
                "summary": "Generate a VietQR bank transfer QR code (PNG)",
                "parameters": [
                    {
                        "name": "bank",
                        "in": "query",
                        "required": true,
                        "description": "Bank BIN (e.g. 970436), code (e.g. VCB) or short name (e.g. Vietcombank). See /api/v1/banks.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "VCB"
                    },
                    {
                        "name": "account",
                        "in": "query",
                        "required": true,
                        "description": "Account number, digits only.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "0123456789"
                    },
                    {
                        "name": "amount",
                        "in": "query",
                        "description": "Fixed amount in VND. Omit it for a reusable code where the payer types the amount.",
                        "schema": {
                            "type": "integer",
                            "minimum": 2000,
                            "maximum": 99999999
                        }
                    },
                    {
                        "name": "note",
                        "in": "query",
                        "description": "Transfer note. Punctuation is replaced by spaces.",
                        "schema": {
                            "type": "string",
                            "maxLength": 89
                        }
                    },
                    {
                        "name": "size",
                        "in": "query",
                        "description": "Width and height of the PNG in pixels.",
                        "schema": {
                            "type": "integer",
                            "minimum": 200,
                            "maximum": 1000,
                            "default": 400
                        }
                    },
                    {
                        "name": "response",
                        "in": "query",
                        "description": "image returns the file itself; json returns the encoded content and the image as a base64 data URI.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "image",
                                "json"
                            ],
                            "default": "image"
                        }
                    },
                    {
                        "name": "download",
                        "in": "query",
                        "description": "Send the image as an attachment (Content-Disposition) instead of inline.",
                        "schema": {
                            "type": "boolean",
                            "default": false
                        }
                    },
                    {
                        "name": "filename",
                        "in": "query",
                        "description": "File name without extension for downloads (letters, digits, dot, dash, underscore).",
                        "schema": {
                            "type": "string",
                            "maxLength": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The image (default) or, with response=json, a JSON envelope.",
                        "content": {
                            "image/png": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            },
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/VietQrResult"
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/banks": {
            "get": {
                "operationId": "listBanks",
                "summary": "List banks that accept VietQR transfers",
                "parameters": [
                    {
                        "name": "q",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "maxLength": 50
                        },
                        "description": "Filter by BIN prefix, code or name."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Banks",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BankList"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/dynamic-qr": {
            "get": {
                "operationId": "listDynamicQrCodes",
                "summary": "List your dynamic QR codes",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "active",
                                "paused",
                                "blocked"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Your codes",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DynamicQrList"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing, invalid or expired token.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Unverified account, or a read-only token used for a change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No dynamic QR with this code in your account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "createDynamicQrCode",
                "summary": "Create a dynamic QR code (write token)",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "target_url"
                                ],
                                "properties": {
                                    "target_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Where scans are redirected (http/https). Can be changed later without reprinting the code."
                                    },
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Label to recognise the code in your dashboard. Defaults to the link's domain."
                                    },
                                    "format": {
                                        "type": "string",
                                        "enum": [
                                            "svg",
                                            "png",
                                            "webp"
                                        ],
                                        "default": "png",
                                        "description": "Image format."
                                    },
                                    "size": {
                                        "type": "integer",
                                        "minimum": 128,
                                        "maximum": 2048,
                                        "default": 512,
                                        "description": "Width and height in pixels, border included."
                                    },
                                    "border": {
                                        "type": "integer",
                                        "enum": [
                                            0,
                                            2,
                                            4,
                                            6
                                        ],
                                        "default": 4,
                                        "description": "Quiet zone around the code: 0 none, 2 thin, 4 medium, 6 thick."
                                    },
                                    "color": {
                                        "type": "string",
                                        "default": "#000000",
                                        "description": "Module color (hex)."
                                    },
                                    "background": {
                                        "type": "string",
                                        "default": "#ffffff",
                                        "description": "Background color (hex)."
                                    },
                                    "eye_color": {
                                        "type": "string",
                                        "description": "Color of the three corner eyes (hex). Defaults to the module color."
                                    },
                                    "module_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "dots"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the modules."
                                    },
                                    "eye_frame_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "circle"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the corner eye frames."
                                    },
                                    "eye_pupil_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "circle"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the corner eye pupils."
                                    },
                                    "error_correction": {
                                        "type": "string",
                                        "enum": [
                                            "high",
                                            "quartile",
                                            "medium",
                                            "low"
                                        ],
                                        "default": "high",
                                        "description": "Error correction level: high (~30% of the code can be damaged or covered), quartile (~25%), medium (~15%) or low (~7%). Lower levels give fewer, larger modules; keep high or quartile with a center logo."
                                    },
                                    "label": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "Caption drawn below the code."
                                    },
                                    "label_size": {
                                        "type": "integer",
                                        "minimum": 8,
                                        "maximum": 72,
                                        "default": 20,
                                        "description": "Caption font size."
                                    },
                                    "label_align": {
                                        "type": "string",
                                        "enum": [
                                            "left",
                                            "center",
                                            "right"
                                        ],
                                        "default": "center",
                                        "description": "Caption alignment."
                                    },
                                    "label_color": {
                                        "type": "string",
                                        "default": "#000000",
                                        "description": "Caption color (hex)."
                                    },
                                    "logo_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Public https URL of a PNG, JPG, GIF or WebP logo (up to 2 MB) for the center. Downloaded by our server and cached for an hour."
                                    },
                                    "logo_size": {
                                        "type": "integer",
                                        "minimum": 16,
                                        "maximum": 1024,
                                        "default": 40,
                                        "description": "Width of the center logo in pixels (logo from logo_url, or uploaded as a multipart `logo` file on POST)."
                                    }
                                }
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "target_url"
                                ],
                                "properties": {
                                    "target_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Where scans are redirected (http/https). Can be changed later without reprinting the code."
                                    },
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Label to recognise the code in your dashboard. Defaults to the link's domain."
                                    },
                                    "format": {
                                        "type": "string",
                                        "enum": [
                                            "svg",
                                            "png",
                                            "webp"
                                        ],
                                        "default": "png",
                                        "description": "Image format."
                                    },
                                    "size": {
                                        "type": "integer",
                                        "minimum": 128,
                                        "maximum": 2048,
                                        "default": 512,
                                        "description": "Width and height in pixels, border included."
                                    },
                                    "border": {
                                        "type": "integer",
                                        "enum": [
                                            0,
                                            2,
                                            4,
                                            6
                                        ],
                                        "default": 4,
                                        "description": "Quiet zone around the code: 0 none, 2 thin, 4 medium, 6 thick."
                                    },
                                    "color": {
                                        "type": "string",
                                        "default": "#000000",
                                        "description": "Module color (hex)."
                                    },
                                    "background": {
                                        "type": "string",
                                        "default": "#ffffff",
                                        "description": "Background color (hex)."
                                    },
                                    "eye_color": {
                                        "type": "string",
                                        "description": "Color of the three corner eyes (hex). Defaults to the module color."
                                    },
                                    "module_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "dots"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the modules."
                                    },
                                    "eye_frame_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "circle"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the corner eye frames."
                                    },
                                    "eye_pupil_shape": {
                                        "type": "string",
                                        "enum": [
                                            "square",
                                            "rounded",
                                            "circle"
                                        ],
                                        "default": "square",
                                        "description": "Shape of the corner eye pupils."
                                    },
                                    "error_correction": {
                                        "type": "string",
                                        "enum": [
                                            "high",
                                            "quartile",
                                            "medium",
                                            "low"
                                        ],
                                        "default": "high",
                                        "description": "Error correction level: high (~30% of the code can be damaged or covered), quartile (~25%), medium (~15%) or low (~7%). Lower levels give fewer, larger modules; keep high or quartile with a center logo."
                                    },
                                    "label": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "Caption drawn below the code."
                                    },
                                    "label_size": {
                                        "type": "integer",
                                        "minimum": 8,
                                        "maximum": 72,
                                        "default": 20,
                                        "description": "Caption font size."
                                    },
                                    "label_align": {
                                        "type": "string",
                                        "enum": [
                                            "left",
                                            "center",
                                            "right"
                                        ],
                                        "default": "center",
                                        "description": "Caption alignment."
                                    },
                                    "label_color": {
                                        "type": "string",
                                        "default": "#000000",
                                        "description": "Caption color (hex)."
                                    },
                                    "logo_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Public https URL of a PNG, JPG, GIF or WebP logo (up to 2 MB) for the center. Downloaded by our server and cached for an hour."
                                    },
                                    "logo_size": {
                                        "type": "integer",
                                        "minimum": 16,
                                        "maximum": 1024,
                                        "default": 40,
                                        "description": "Width of the center logo in pixels (logo from logo_url, or uploaded as a multipart `logo` file on POST)."
                                    },
                                    "logo": {
                                        "type": "string",
                                        "format": "binary",
                                        "description": "Center logo: PNG, JPG, GIF or WebP, up to 2 MB."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DynamicQrResult"
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "401": {
                        "description": "Missing, invalid or expired token.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Unverified account, or a read-only token used for a change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No dynamic QR with this code in your account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/dynamic-qr/{code}": {
            "parameters": [
                {
                    "name": "code",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "string"
                    },
                    "description": "Short code of the dynamic QR (after /r/ in its link)."
                }
            ],
            "get": {
                "operationId": "getDynamicQrCode",
                "summary": "Show a dynamic QR code with scan summary and recent destination changes",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The code",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DynamicQrResult"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing, invalid or expired token.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Unverified account, or a read-only token used for a change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No dynamic QR with this code in your account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            },
            "patch": {
                "operationId": "updateDynamicQrCode",
                "summary": "Change the destination, rename, pause or resume (write token)",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "target_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Where scans are redirected (http/https). Can be changed later without reprinting the code."
                                    },
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Label to recognise the code in your dashboard. Defaults to the link's domain."
                                    },
                                    "is_active": {
                                        "type": "boolean",
                                        "description": "false pauses the code (scans see a notice), true resumes it."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Saved",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DynamicQrResult"
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "401": {
                        "description": "Missing, invalid or expired token.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Unverified account, or a read-only token used for a change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No dynamic QR with this code in your account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "operationId": "deleteDynamicQrCode",
                "summary": "Delete a dynamic QR code; printed copies stop working (write token)",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Deleted",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing, invalid or expired token.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Unverified account, or a read-only token used for a change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No dynamic QR with this code in your account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/dynamic-qr/{code}/stats": {
            "get": {
                "operationId": "getDynamicQrStats",
                "summary": "Scan statistics for a period",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "code",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Short code of the dynamic QR (after /r/ in its link)."
                    },
                    {
                        "name": "range",
                        "in": "query",
                        "description": "Last 7, 30 or 90 days, or custom with from/to.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "7",
                                "30",
                                "90",
                                "custom"
                            ],
                            "default": "30"
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "description": "Start date (YYYY-MM-DD) when range=custom.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "description": "End date (YYYY-MM-DD) when range=custom; at most 366 days after from.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Daily series, totals and breakdowns by country, city, device, OS and app",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing, invalid or expired token.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Unverified account, or a read-only token used for a change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No dynamic QR with this code in your account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/dynamic-qr/{code}/image": {
            "get": {
                "operationId": "getDynamicQrImage",
                "summary": "The dynamic QR image in its saved design",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "code",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Short code of the dynamic QR (after /r/ in its link)."
                    },
                    {
                        "name": "format",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "svg",
                                "png",
                                "webp"
                            ]
                        }
                    },
                    {
                        "name": "size",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 128,
                            "maximum": 2048
                        }
                    },
                    {
                        "name": "download",
                        "in": "query",
                        "schema": {
                            "type": "boolean"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The image",
                        "content": {
                            "image/png": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            },
                            "image/svg+xml": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            },
                            "image/webp": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing, invalid or expired token.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Unverified account, or a read-only token used for a change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No dynamic QR with this code in your account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "description": "Personal API token (sqr_…) created at https://scan.io.vn/dashboard/api-tokens. Only needed for /dynamic-qr."
            }
        },
        "schemas": {
            "DynamicQr": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "short_url": {
                        "type": "string",
                        "description": "The link encoded in the QR."
                    },
                    "target_url": {
                        "type": "string",
                        "description": "Where scans are redirected."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "active",
                            "paused",
                            "blocked"
                        ]
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "scans": {
                        "type": "integer"
                    },
                    "unique_scans": {
                        "type": "integer"
                    },
                    "last_scanned_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "style": {
                        "type": "object"
                    },
                    "has_logo": {
                        "type": "boolean"
                    },
                    "image_url": {
                        "type": "string"
                    },
                    "dashboard_url": {
                        "type": "string"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "DynamicQrResult": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Envelope"
                    },
                    {
                        "type": "object",
                        "properties": {
                            "data": {
                                "type": "object",
                                "properties": {
                                    "dynamic_qr": {
                                        "$ref": "#/components/schemas/DynamicQr"
                                    }
                                }
                            }
                        }
                    }
                ]
            },
            "DynamicQrList": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Envelope"
                    },
                    {
                        "type": "object",
                        "properties": {
                            "data": {
                                "type": "object",
                                "properties": {
                                    "dynamic_qr_codes": {
                                        "type": "array",
                                        "items": {
                                            "$ref": "#/components/schemas/DynamicQr"
                                        }
                                    },
                                    "total": {
                                        "type": "integer"
                                    },
                                    "limit": {
                                        "type": "integer"
                                    },
                                    "remaining": {
                                        "type": "integer"
                                    }
                                }
                            }
                        }
                    }
                ]
            },
            "Envelope": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string",
                        "description": "\"00\" success, \"01\" error, \"02\" validation error."
                    },
                    "message": {
                        "type": "string"
                    },
                    "data": {
                        "type": "object"
                    },
                    "extra_data": {
                        "type": "array"
                    }
                }
            },
            "QrResult": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Envelope"
                    },
                    {
                        "type": "object",
                        "properties": {
                            "data": {
                                "type": "object",
                                "properties": {
                                    "content": {
                                        "type": "string",
                                        "description": "The exact string encoded in the QR code."
                                    },
                                    "format": {
                                        "type": "string"
                                    },
                                    "mime_type": {
                                        "type": "string"
                                    },
                                    "image": {
                                        "type": "string",
                                        "description": "data: URI (base64)."
                                    },
                                    "image_url": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "description": "GET URL that renders the same image (null when a logo was uploaded)."
                                    }
                                }
                            }
                        }
                    }
                ]
            },
            "Bank": {
                "type": "object",
                "properties": {
                    "bin": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "code": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "short_name": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "swift_code": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "logo": {
                        "type": [
                            "string",
                            "null"
                        ]
                    }
                }
            },
            "VietQrResult": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Envelope"
                    },
                    {
                        "type": "object",
                        "properties": {
                            "data": {
                                "type": "object",
                                "properties": {
                                    "bank": {
                                        "$ref": "#/components/schemas/Bank"
                                    },
                                    "account": {
                                        "type": "string"
                                    },
                                    "amount": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    },
                                    "note": {
                                        "type": "string"
                                    },
                                    "payload": {
                                        "type": "string",
                                        "description": "EMVCo / NAPAS payload encoded in the QR code."
                                    },
                                    "mime_type": {
                                        "type": "string"
                                    },
                                    "image": {
                                        "type": "string",
                                        "description": "data: URI (base64)."
                                    },
                                    "image_url": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                ]
            },
            "BankList": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Envelope"
                    },
                    {
                        "type": "object",
                        "properties": {
                            "data": {
                                "type": "object",
                                "properties": {
                                    "banks": {
                                        "type": "array",
                                        "items": {
                                            "$ref": "#/components/schemas/Bank"
                                        }
                                    },
                                    "total": {
                                        "type": "integer"
                                    }
                                }
                            }
                        }
                    }
                ]
            }
        },
        "responses": {
            "ValidationError": {
                "description": "Invalid parameters; `data` maps each field to its messages.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Envelope"
                        }
                    }
                }
            },
            "TooManyRequests": {
                "description": "Rate limit reached (60/min per IP). Retry after the Retry-After seconds.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Envelope"
                        }
                    }
                }
            }
        }
    }
}