{
  "openapi": "3.1.0",
  "info": {
    "version": "1.0.0",
    "title": "TIGER FORM API Documentation",
    "description": "Public HTTP API for TIGER FORM — create forms, send or read submissions, download QR images, webhooks, and analytics.\n\n**New integrator?** [Getting Started](https://docs.form-qr-code-generator.com/v1/index.htm#getting-started) → [End-to-End Integration](https://docs.form-qr-code-generator.com/v1/index.htm#end-to-end-integration) (5 copy-paste steps).\n\n**Base URL:** `https://api.form-qr-code-generator.com/v1`\n\n**Authentication:** `Authorization: Bearer <API_KEY>` on every documented route.\n\n**JSON responses:** Success `{ \"status\": \"success\", \"data\": ... }`. Errors `{ \"status\": \"failed\", \"message\", \"code\", \"data\": {} }` (400, 401, 403, 404, 409, 429, 500). Exception: **`GET /forms/{qrId}/download`** returns a binary file, not JSON.\n\n**Typical submission flow:** (1) **`GET /forms/{qrId}/submission-schema`** for field keys, (2) optional **`POST /forms/{qrId}/uploads`** (`category=submission`) for files, (3) **`POST /forms/{qrId}/submissions`** with top-level **`answers`**. Optional **`Idempotency-Key`** on create. See [Create a Submission](https://docs.form-qr-code-generator.com/v1/index.htm#create-submission) and [Upload APIs Compared](https://docs.form-qr-code-generator.com/v1/index.htm#upload-apis-compared).\n\n**Plans & quota:** Each v1 request counts toward your account **monthly API request limit** (reference: Freemium **500**, Starter **10,000**, Business **30,000**, Professional **50,000** per month; **Enterprise** — [Contact us](https://www.form-qr-code-generator.com/contact-us) or tiger-form@qrtiger.helpscoutapp.com — [Rate Limits & Retries](https://docs.form-qr-code-generator.com/v1/index.htm#rate-limits)). Limit reached → HTTP **429**. Expired or cancelled paid subscriptions are **not** downgraded to Freemium — inactive subscription → **400** on most operations after the quota gate; renew to restore access. HTTP **429** means the monthly API request limit is exhausted (separate from inactive subscription). See [Rate Limits & Retries](https://docs.form-qr-code-generator.com/v1/index.htm#rate-limits) and [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).\n\n**More guides:** [Core Concepts](https://docs.form-qr-code-generator.com/v1/index.htm#core-concepts), [SDK Examples](https://docs.form-qr-code-generator.com/v1/index.htm#sdk-examples), [Webhooks](https://docs.form-qr-code-generator.com/v1/index.htm#webhook-api), [Versioning](https://docs.form-qr-code-generator.com/v1/index.htm#versioning). [Status](https://docs.form-qr-code-generator.com/v1/status.html) · [SLA](https://docs.form-qr-code-generator.com/v1/sla.html) · Support: tiger-form@qrtiger.helpscoutapp.com",
    "license": {
      "name": "Proprietary",
      "url": "https://www.form-qr-code-generator.com"
    },
    "contact": {
      "name": "TIGER FORM API Support",
      "email": "tiger-form@qrtiger.helpscoutapp.com",
      "url": "https://www.form-qr-code-generator.com/contact-us"
    },
    "termsOfService": "https://www.form-qr-code-generator.com/general-terms-and-conditions"
  },
  "externalDocs": {
    "description": "Status page and SLA policy",
    "url": "https://docs.form-qr-code-generator.com/v1/status.html"
  },
  "servers": [
    {
      "url": "https://api.form-qr-code-generator.com/v1",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "Logo uploads and webhook settings. Guide: [Webhooks](https://docs.form-qr-code-generator.com/v1/index.htm#webhook-api)."
    },
    {
      "name": "Form AI Builder",
      "description": "Optional — AI draft layout. Guide: [AI Form Builder](https://docs.form-qr-code-generator.com/v1/index.htm#ai-form-builder-api)."
    },
    {
      "name": "Form analytics",
      "description": "Scan analytics and CSV export. Guide: [Form Analytics](https://docs.form-qr-code-generator.com/v1/index.htm#form-analytics)."
    },
    {
      "name": "Form Template Categories",
      "description": "Optional. List categories for browsing public templates (`GET /form-templates/categories`)."
    },
    {
      "name": "Form Templates",
      "description": "Optional — marketplace templates. Guide: [Form Templates API](https://docs.form-qr-code-generator.com/v1/index.htm#form-templates-api)."
    },
    {
      "name": "Forms",
      "description": "Create, read, update, delete, archive, clone, share, download forms. Guide: [Create a Form](https://docs.form-qr-code-generator.com/v1/index.htm#create-form)."
    },
    {
      "name": "QR Design Templates",
      "description": "Optional — QR preset catalog. Guide: [Built-in QR Design Presets](https://docs.form-qr-code-generator.com/v1/index.htm#qr-design-templates-api)."
    },
    {
      "name": "Submissions",
      "description": "Create, validate, read, update, delete submissions. Guide: [Create a Submission](https://docs.form-qr-code-generator.com/v1/index.htm#create-submission)."
    },
    {
      "name": "Team",
      "description": "Team members (Business+ plan). Guide: [Team API](https://docs.form-qr-code-generator.com/v1/index.htm#team-api)."
    }
  ],
  "x-tagGroups": [
    {
      "name": "Core API",
      "tags": [
        "Forms",
        "Submissions",
        "Form analytics",
        "QR Design Templates"
      ]
    },
    {
      "name": "Account & team",
      "tags": [
        "Account",
        "Team"
      ]
    },
    {
      "name": "Form authoring",
      "tags": [
        "Form AI Builder",
        "Form Templates",
        "Form Template Categories"
      ]
    }
  ],
  "components": {
    "securitySchemes": {
      "Bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "TIGER FORM API key from Account → Integration. Send as header: Authorization: Bearer <your_api_key> (the token is an API key, not a JWT)."
      }
    },
    "schemas": {
      "ApiSuccessEnvelope": {
        "type": "object",
        "description": "Common shape for successful JSON responses from this API after normalization.",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "example": "success"
          },
          "data": {
            "description": "Payload after normalization. Can be an object, array, or empty object `{}`."
          }
        },
        "required": [
          "status",
          "data"
        ]
      },
      "ApiSuccessWithObjectData": {
        "type": "object",
        "description": "Success with an object `data` payload (handler-specific keys).",
        "required": [
          "status",
          "data"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ],
            "example": "success"
          },
          "data": {
            "type": "object",
            "additionalProperties": true,
            "description": "Endpoint-specific body after normalization; may be `{}`."
          }
        }
      },
      "ApiFailedResponse": {
        "type": "object",
        "description": "Normalized JSON error envelope for documented routes in this API.",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "failed"
            ],
            "example": "failed"
          },
          "message": {
            "type": "string",
            "description": "Human-readable text; may be localized."
          },
          "code": {
            "type": "integer",
            "description": "Typically matches the HTTP status code."
          },
          "data": {
            "type": "object",
            "additionalProperties": true,
            "description": "Usually `{}`; reserved for structured error details."
          }
        },
        "required": [
          "status",
          "message",
          "code",
          "data"
        ]
      },
      "ApiAuthError": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiFailedResponse"
          }
        ],
        "description": "HTTP **401** — missing or invalid `Authorization: Bearer <api_key>`. Same JSON shape as `ApiFailedResponse`."
      },
      "ApiRateLimitError": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiFailedResponse"
          }
        ],
        "description": "HTTP **429** — monthly API request limit reached (enforced as `apiLimit`), or upload throttling on `POST /forms/{qrId}/uploads` with `category=submission`.",
        "example": {
          "status": "failed",
          "message": "Sorry, your API request limit has been reached",
          "code": 429,
          "data": {}
        }
      },
      "DeleteFormSuccess": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "required": [
                  "result"
                ],
                "properties": {
                  "result": {
                    "type": "string",
                    "description": "Localized success message"
                  }
                }
              }
            }
          }
        ],
        "description": "Success with a localized message in `data.result` (form delete, archive, restore, and similar actions)."
      },
      "SubmissionUploadResult": {
        "type": "object",
        "description": "Payload inside `data` for a successful submission file upload.",
        "properties": {
          "fileUrl": {
            "type": "string",
            "format": "uri",
            "description": "CDN or bucket URL of the stored file"
          },
          "fileId": {
            "type": "string",
            "description": "Server-side file identifier"
          }
        },
        "required": [
          "fileUrl",
          "fileId"
        ]
      },
      "SubmissionUploadSuccess": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "$ref": "#/components/schemas/SubmissionUploadResult"
              }
            }
          }
        ],
        "description": "Normalized success body for file upload via POST /forms/{qrId}/uploads."
      },
      "SubmissionCreateBody": {
        "type": "object",
        "description": "Payload for a new response using the simplified **`answers`** map. Discover field keys and shapes via **`GET /forms/{qrId}/submission-schema`** or **`GET /forms/{qrId}`**. File fields: upload with **`POST /forms/{qrId}/uploads`** (`category=submission`), then pass **`fileId`** only in `answers` — the server resolves `fileUrl`.",
        "required": [
          "answers"
        ],
        "properties": {
          "answers": {
            "type": "object",
            "additionalProperties": true,
            "description": "Map of field `key` → simple answer value (string, string[], object, or `{ fileId }`). See **`GET /forms/{qrId}/submission-schema`** for per-field `valueType` and examples."
          },
          "timeSpentSeconds": {
            "type": "number",
            "description": "Optional; quiz forms may record time spent"
          },
          "timeExpired": {
            "type": "boolean",
            "description": "Optional; quiz flows may set when time ran out"
          }
        },
        "example": {
          "answers": {
            "1748000000_3": "Jane Doe",
            "1748000000_7": [
              "Option 1"
            ],
            "1748000000_12": {
              "fileId": "507f1f77bcf86cd799439011"
            }
          }
        }
      },
      "SubmissionEditBody": {
        "type": "object",
        "required": [
          "answers"
        ],
        "properties": {
          "answers": {
            "type": "object",
            "additionalProperties": true,
            "description": "Same simplified map as create. Replaces submission field values."
          },
          "timeSpentSeconds": {
            "type": "number"
          }
        }
      },
      "SubmissionValueType": {
        "type": "string",
        "enum": [
          "string",
          "string[]",
          "object",
          "fileId",
          "fileId[]",
          "array"
        ],
        "description": "Expected JSON type for `answers[fieldKey]`. Branch client code on this value."
      },
      "SubmissionSchemaField": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          },
          "options": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                }
              }
            }
          },
          "valueType": {
            "$ref": "#/components/schemas/SubmissionValueType"
          },
          "type": {
            "type": "string",
            "description": "Public field type (same as `type` on form field definitions), e.g. `shortText`, `checkbox`."
          }
        },
        "required": [
          "key",
          "type",
          "valueType"
        ]
      },
      "SubmissionSchemaResponse": {
        "type": "object",
        "required": [
          "status",
          "data"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "data": {
            "type": "object",
            "properties": {
              "qrId": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "fields": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/components/schemas/SubmissionSchemaField"
                }
              }
            }
          }
        }
      },
      "SubmissionMultipleDeleteBody": {
        "type": "object",
        "required": [
          "qrId",
          "submissionIds"
        ],
        "properties": {
          "qrId": {
            "type": "string",
            "pattern": "^[A-Z0-9]+$",
            "description": "Form id"
          },
          "submissionIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "submission ids of submissions to delete (must belong to this form)"
          }
        }
      },
      "SubmissionListResponse": {
        "type": "object",
        "description": "Successful paginated list of submissions for a form. Auth failures before the handler use HTTP **401** (`ApiAuthError`). Unknown `qrId`, wrong account, archived form, or blocked owner returns HTTP **400** with `ApiFailedResponse` (same as **`GET /forms/{qrId}`**). HTTP **200** with `data.items: []` and `data.total: 0` means the form exists but has no matching submissions.",
        "required": [
          "status",
          "data"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "data": {
            "type": "object",
            "required": [
              "items",
              "total",
              "page",
              "pageSize",
              "totalPages"
            ],
            "properties": {
              "total": {
                "type": "integer",
                "description": "Total submissions matching filters (all pages)"
              },
              "page": {
                "type": "integer",
                "description": "Current page number (1-based)"
              },
              "pageSize": {
                "type": "integer",
                "description": "Page size used for this request"
              },
              "totalPages": {
                "type": "integer",
                "description": "Ceiling of total / pageSize (0 when total is 0)"
              },
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SubmissionListItem"
                },
                "description": "Submission documents for this page (newest first). Each item includes top-level **`answers`** (same shape as create/edit)."
              }
            }
          },
          "form": {
            "type": "object",
            "properties": {
              "fields": {
                "type": "array",
                "description": "Form field definitions (array with `key`, `type`, `option`) — same shape as `GET /forms/{qrId}` `data.fields`.",
                "items": {
                  "$ref": "#/components/schemas/FormFieldRead"
                }
              },
              "title": {
                "type": "string"
              }
            }
          }
        },
        "example": {
          "status": "success",
          "data": {
            "total": 1,
            "page": 1,
            "pageSize": 50,
            "totalPages": 1,
            "items": [
              {
                "id": "507f1f77bcf86cd799439011",
                "qrId": "ABC123",
                "createdAt": "2025-06-01T10:00:00.000Z",
                "answers": {
                  "1748000000_3": "Jane Doe",
                  "1748000000_7": [
                    "Option 1",
                    "Option 2"
                  ],
                  "1748000000_12": {
                    "fileId": "507f1f77bcf86cd799439011",
                    "fileUrl": "https://cdn.example.com/files/abc.png"
                  }
                }
              }
            ]
          },
          "form": {
            "title": "Contact form",
            "fields": [
              {
                "key": "1748000000_3",
                "type": "shortText",
                "option": {
                  "label": "Name"
                }
              },
              {
                "key": "1748000000_7",
                "type": "checkbox",
                "option": {
                  "label": "Interests"
                }
              },
              {
                "key": "1748000000_12",
                "type": "picture",
                "option": {
                  "label": "Photo"
                }
              }
            ]
          }
        }
      },
      "SubmissionListItem": {
        "type": "object",
        "description": "One submission in **`GET /forms/{qrId}/submissions`** `data.items`. Returns **`answers`** only (simplified map for integrations).",
        "properties": {
          "id": {
            "type": "string",
            "description": "Submission id (same value as create response `submissionId`)."
          },
          "qrId": {
            "type": "string"
          },
          "answers": {
            "type": "object",
            "additionalProperties": true,
            "description": "Field key → value map (same as create/edit). File fields on read may include `{ fileId, fileUrl }`."
          },
          "quizData": {
            "type": "object",
            "additionalProperties": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SubmissionDetailResponse": {
        "type": "object",
        "description": "Single submission for a form the authenticated account can access. Unknown id, wrong account, archived form, or blocked owner returns HTTP **400** with `ApiFailedResponse`.",
        "required": [
          "status",
          "data"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "data": {
            "type": "object",
            "additionalProperties": true,
            "description": "Submission document (`id`, `qrId`, `answers`, optional `quizData`, `createdAt`, `updatedAt`, …)."
          },
          "form": {
            "type": "object",
            "properties": {
              "fields": {
                "type": "array",
                "description": "Form field definitions (array with `key`, `type`, `option`) — same shape as `GET /forms/{qrId}` `data.fields`.",
                "items": {
                  "$ref": "#/components/schemas/FormFieldRead"
                }
              },
              "title": {
                "type": "string"
              }
            }
          }
        }
      },
      "SubmissionFieldError": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "Machine-readable error code. `component_mismatch` means the answer value is incompatible with the field type.",
            "enum": [
              "unknown_field",
              "missing_entry",
              "component_mismatch",
              "invalid_shape",
              "required",
              "invalid_email",
              "invalid_option",
              "missing_file_ref",
              "file_not_found",
              "invalid_body"
            ]
          },
          "message": {
            "type": "string",
            "description": "Human-readable error for this field"
          },
          "type": {
            "type": "string",
            "description": "Public field type when the error relates to a known form field."
          }
        }
      },
      "SubmissionValidationFailedData": {
        "type": "object",
        "required": [
          "valid",
          "fieldErrors"
        ],
        "properties": {
          "valid": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "fieldErrors": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/SubmissionFieldError"
            },
            "description": "Map of form field `key` → error detail. Request-level errors use the key `_form`."
          }
        }
      },
      "SubmissionValidationSuccess": {
        "type": "object",
        "required": [
          "status",
          "data"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "data": {
            "type": "object",
            "required": [
              "valid"
            ],
            "properties": {
              "valid": {
                "type": "boolean",
                "enum": [
                  true
                ]
              }
            }
          }
        }
      },
      "SubmissionCreateQuizData": {
        "type": "object",
        "description": "Quiz fields inside `data` on `POST /forms/{qrId}/submissions` when the form is a quiz. Always includes `submissionId`. Score fields use `points` (same name as `quizData.points` on read). Filtering: when `quizConfig.showFinalScore` is false, `points`, `totalMarks`, `percentage`, and per-question `points`/`earnedPoints` are omitted; when `showAnswersResults` is false, `correctAnswer` is omitted from each `quizResult` item.",
        "required": [
          "submissionId"
        ],
        "properties": {
          "submissionId": {
            "type": "string",
            "description": "24-character hex id of the created submission."
          },
          "points": {
            "type": "number",
            "description": "Points earned (omitted when `quizConfig.showFinalScore` is false)."
          },
          "totalMarks": {
            "type": "number",
            "description": "Maximum points (omitted when `quizConfig.showFinalScore` is false)."
          },
          "percentage": {
            "type": "number"
          },
          "passed": {
            "type": "boolean"
          },
          "passingScore": {
            "type": "number"
          },
          "quizResult": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "timeSpentSeconds": {
            "type": "number"
          },
          "timeExpired": {
            "type": "boolean"
          }
        }
      },
      "SubmissionCreateQuizResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "$ref": "#/components/schemas/SubmissionCreateQuizData"
              }
            },
            "required": [
              "data"
            ]
          }
        ],
        "description": "Quiz form create success — standard envelope with `submissionId` and optional quiz score fields in `data`."
      },
      "SubmissionCreateNonQuizResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "required": [
                  "submissionId"
                ],
                "properties": {
                  "submissionId": {
                    "type": "string",
                    "description": "24-character hex id of the created submission."
                  }
                }
              }
            }
          }
        ]
      },
      "TeamMemberCreateBody": {
        "type": "object",
        "required": [
          "email",
          "password",
          "userType"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "password": {
            "type": "string",
            "minLength": 1
          },
          "userType": {
            "type": "string",
            "description": "Typically `Admin`, `Editor`, or `Viewer`."
          },
          "subDomainIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional sub-domain ids to assign to this member."
          }
        }
      },
      "TeamMemberUpdateBody": {
        "type": "object",
        "description": "Any provided fields are applied to the member.",
        "properties": {
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "block": {
            "type": "boolean",
            "description": "Block/unblock member."
          },
          "teamName": {
            "type": "string"
          },
          "userType": {
            "type": "string"
          },
          "pass": {
            "type": "string",
            "description": "Optional replacement password field."
          },
          "subDomainIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "TeamRenameBody": {
        "type": "object",
        "required": [
          "teamName",
          "password"
        ],
        "properties": {
          "teamName": {
            "type": "string"
          },
          "password": {
            "type": "string"
          }
        }
      },
      "TeamMemberResetPasswordBody": {
        "type": "object",
        "required": [
          "oldPass",
          "newPass",
          "confirmPass"
        ],
        "properties": {
          "oldPass": {
            "type": "string",
            "description": "Current password."
          },
          "newPass": {
            "type": "string",
            "description": "New password."
          },
          "confirmPass": {
            "type": "string",
            "description": "Must match `newPass`."
          }
        }
      },
      "TeamMemberPublic": {
        "type": "object",
        "description": "Team member returned by Team API success responses (passwords and API keys are never included).",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "userType": {
            "type": "string",
            "description": "Team role: `Admin`, `Editor`, or `Viewer`."
          },
          "blocked": {
            "type": "boolean"
          },
          "teamName": {
            "type": "string"
          }
        }
      },
      "TeamApiSuccessData": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "member": {
            "$ref": "#/components/schemas/TeamMemberPublic"
          },
          "teamName": {
            "type": "string",
            "description": "Present on team rename success."
          }
        }
      },
      "TeamApiSuccessResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "$ref": "#/components/schemas/TeamApiSuccessData"
              }
            }
          }
        ]
      },
      "TeamMemberListData": {
        "type": "object",
        "required": [
          "members"
        ],
        "properties": {
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TeamMemberPublic"
            }
          }
        }
      },
      "TeamMemberListResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "$ref": "#/components/schemas/TeamMemberListData"
              }
            }
          }
        ]
      },
      "CloneQrEntry": {
        "type": "object",
        "description": "One cloned form (new `qrId`) returned in `cloneData`.",
        "properties": {
          "data": {
            "type": "object",
            "description": "Parsed QR design body (`qrConfig` JSON)",
            "additionalProperties": true
          },
          "qrImgUrl": {
            "type": "string",
            "format": "uri",
            "description": "URL of rendered QR image"
          },
          "image": {
            "description": "Raw image buffer/metadata from generator (shape varies)"
          }
        }
      },
      "CloneFormResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "required": [
                  "cloneData"
                ],
                "properties": {
                  "cloneData": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/CloneQrEntry"
                    },
                    "description": "One item per successfully created form copy"
                  }
                }
              }
            }
          }
        ],
        "description": "Result of cloning one form into multiple new forms."
      },
      "EmptyDataSuccess": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {},
                "additionalProperties": false,
                "description": "Empty object `{}`."
              }
            }
          }
        ],
        "description": "Success with no payload (e.g. share sent, submission updated/deleted)."
      },
      "MultiDeleteFormsSuccess": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "required": [
                  "message"
                ],
                "properties": {
                  "message": {
                    "type": "string",
                    "description": "Localized confirmation, often includes account email"
                  }
                }
              }
            }
          }
        ]
      },
      "FormListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "qrId": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "shortText": {
            "type": "string"
          },
          "shortUrl": {
            "type": "string",
            "description": "Public short link to open the form. Format: `https://tgr.li/{qrId}` (uses the form's `qrId`)."
          },
          "previewImage": {
            "type": "string"
          },
          "qrImage": {
            "type": "string"
          },
          "svgQrImage": {
            "type": "string"
          },
          "scans": {
            "type": "integer"
          },
          "submissions": {
            "type": "integer"
          },
          "active": {
            "type": "boolean"
          },
          "starred": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string"
          },
          "updatedAt": {
            "type": "string"
          }
        }
      },
      "FormDetail": {
        "type": "object",
        "description": "Optional page styling and settings accepted on **`POST /forms`** / **`PUT /forms/{qrId}`** alongside **`FormCreate`**. These fields may not appear on **`GET /forms/{qrId}`** — use the create/update response for styling state.",
        "properties": {
          "title": {
            "type": "string"
          },
          "shortText": {
            "type": "string"
          },
          "locale": {
            "type": "string"
          },
          "fields": {
            "type": "array",
            "description": "Optional partial field list on update (`type` + `option` on create; include `key` only when updating existing fields).",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          },
          "backgroundType": {
            "type": "string",
            "enum": [
              "solid",
              "gradient",
              "image"
            ],
            "default": "solid"
          },
          "backgroundColor1": {
            "type": "string",
            "default": "0076d7"
          },
          "backgroundColor2": {
            "type": "string",
            "default": "3a74c5"
          },
          "appearance": {
            "type": "object",
            "properties": {
              "headerColor": {
                "type": "string",
                "default": "ffffff"
              },
              "buttonColor": {
                "type": "string",
                "default": "ffffff"
              }
            }
          },
          "logo": {
            "$ref": "#/components/schemas/File"
          },
          "backgroundImage": {
            "$ref": "#/components/schemas/File"
          },
          "backdrop": {
            "$ref": "#/components/schemas/File"
          },
          "previewImage": {
            "$ref": "#/components/schemas/File"
          },
          "qrConfig": {
            "$ref": "#/components/schemas/QRConfig"
          },
          "shortUrl": {
            "type": "string",
            "description": "Public short link to open the form. Format: `https://tgr.li/{qrId}` (uses the form's `qrId`)."
          },
          "owner": {
            "type": "string"
          },
          "qrId": {
            "type": "string"
          },
          "qrImage": {
            "type": "string"
          },
          "scans": {
            "type": "integer"
          },
          "submissions": {
            "type": "integer"
          },
          "active": {
            "type": "boolean"
          },
          "expiryDate": {
            "type": "string"
          },
          "expiryScans": {
            "type": "integer"
          },
          "expireByIP": {
            "type": "boolean"
          },
          "submissionNotification": {
            "type": "boolean",
            "default": true,
            "description": "When `true` (default), the form owner receives an email for each new submission. Set to `false` on **`POST /forms`** or **`PUT /forms/{qrId}`** to disable instant submission notification emails for this form. Independent of periodic scan summary emails and account-level monthly reports."
          },
          "blocked": {
            "type": "boolean"
          }
        }
      },
      "FormPublicDetail": {
        "type": "object",
        "description": "Form returned in **`GET /forms/{qrId}`** success `data` and on create/update success. Includes `qrId`, `title`, `fields`, `qrConfig`, and related metadata. Page styling fields sent on create/update may not all appear on GET — see guide [Create a Form](https://docs.form-qr-code-generator.com/v1/index.htm#create-form).",
        "properties": {
          "id": {
            "type": "string"
          },
          "qrId": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "shortText": {
            "type": "string"
          },
          "shortUrl": {
            "type": "string",
            "description": "Public short link to open the form. Format: `https://tgr.li/{qrId}` (uses the form's `qrId`)."
          },
          "previewImage": {
            "type": "string",
            "description": "Preview image URL (string), not a File object."
          },
          "qrImage": {
            "type": "string"
          },
          "svgQrImage": {
            "type": "string"
          },
          "scans": {
            "type": "integer"
          },
          "submissions": {
            "type": "integer"
          },
          "active": {
            "type": "boolean"
          },
          "fields": {
            "type": "array",
            "description": "List of fields. Each item is **`key`** plus public field definition (**`type`**, **`option`**). Use **`key`** in submission **`answers`**.",
            "items": {
              "$ref": "#/components/schemas/FormFieldRead"
            }
          },
          "qrConfig": {
            "$ref": "#/components/schemas/QRConfig",
            "description": "QR appearance object (parsed JSON). Same shape as request **`qrConfig`** on create/update."
          },
          "isQuiz": {
            "type": "boolean",
            "description": "When `true`, the form is a scored quiz. Submit/read behavior: guides [Create a Submission](https://docs.form-qr-code-generator.com/v1/index.htm#create-submission), [Read Submissions](https://docs.form-qr-code-generator.com/v1/index.htm#read-submissions). API authoring: [Quiz Forms](https://docs.form-qr-code-generator.com/v1/index.htm#quiz-forms)."
          },
          "quizConfig": {
            "$ref": "#/components/schemas/QuizFormConfig",
            "description": "Form-level quiz settings (passing score, time limit, display flags). Present when `isQuiz` is true. Per-field correct answers are not returned on GET."
          },
          "submissionNotification": {
            "type": "boolean",
            "default": true,
            "description": "When `true` (default), the form owner receives an email for each new submission. Set to `false` on `PUT /forms/{qrId}` to disable instant submission notification emails for this form."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Form": {
        "description": "Form detail in the public API success envelope (`data` on **`GET /forms/{qrId}`**, create, and update).",
        "$ref": "#/components/schemas/FormPublicDetail"
      },
      "FormCreate": {
        "type": "object",
        "description": "Request body for **`POST /forms`** and **`PUT /forms/{qrId}`**. Send **`title`**, **`shortText`**, and **`fields[]`** (`type` + `option` only — do not send `key`; the server assigns keys). Optional styling and quiz fields below.",
        "required": [
          "title",
          "shortText",
          "fields"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "shortText": {
            "type": "string"
          },
          "fields": {
            "type": "array",
            "description": "List of fields. Each item must be a Field object. See details in the Field definition.",
            "items": {
              "$ref": "#/components/schemas/Field"
            },
            "example": [
              {
                "type": "name",
                "option": {
                  "label": "Full Name",
                  "required": true
                }
              },
              {
                "type": "address",
                "option": {
                  "label": "Address",
                  "required": false
                }
              },
              {
                "type": "phone",
                "option": {
                  "label": "Phone Number",
                  "required": false
                }
              },
              {
                "type": "gender",
                "option": {
                  "label": "Gender",
                  "required": false
                }
              },
              {
                "type": "email",
                "option": {
                  "label": "Email",
                  "required": false
                }
              }
            ]
          },
          "backgroundType": {
            "type": "string",
            "enum": [
              "solid",
              "gradient",
              "image"
            ],
            "default": "solid"
          },
          "backgroundColor1": {
            "type": "string",
            "default": "0076d7"
          },
          "backgroundColor2": {
            "type": "string",
            "default": "3a74c5"
          },
          "appearance": {
            "type": "object",
            "properties": {
              "headerColor": {
                "type": "string",
                "default": "ffffff"
              },
              "buttonColor": {
                "type": "string",
                "default": "ffffff"
              }
            }
          },
          "logo": {
            "$ref": "#/components/schemas/File"
          },
          "backgroundImage": {
            "$ref": "#/components/schemas/File"
          },
          "backdrop": {
            "$ref": "#/components/schemas/File"
          },
          "previewImage": {
            "$ref": "#/components/schemas/File"
          },
          "qrConfig": {
            "$ref": "#/components/schemas/QRConfig",
            "description": "QR code appearance for the downloadable PNG. Send as a JSON **object** on **`POST /forms`** and **`PUT /forms/{qrId}`**. Responses on GET/create/update return the same object shape. Copy a built-in preset's `config` from **`GET /qr-design-templates`** here, or set fields manually (see guide [How to Customize Your QR Code](https://docs.form-qr-code-generator.com/v1/index.htm#customize-qr-code))."
          },
          "isQuiz": {
            "type": "boolean",
            "default": false,
            "description": "Optional. When `true`, create a scored quiz form (requires quiz features on your plan). Most integrations build quizzes in the web designer instead — see guide [Quiz Forms](https://docs.form-qr-code-generator.com/v1/index.htm#quiz-forms)."
          },
          "quizConfig": {
            "$ref": "#/components/schemas/QuizFormConfig",
            "description": "Optional. Form-level quiz settings when `isQuiz` is true. Each setting is validated against your subscription — HTTP **400** if not allowed on your plan. Guide: [Quiz Forms](https://docs.form-qr-code-generator.com/v1/index.htm#quiz-forms)."
          },
          "submissionNotification": {
            "type": "boolean",
            "default": true,
            "description": "When `true` (default), the form owner receives an email for each new submission. Set to `false` on **`POST /forms`** or **`PUT /forms/{qrId}`** to disable instant submission notification emails for this form."
          }
        }
      },
      "AccountWebhook": {
        "type": "object",
        "description": "Account-level outbound webhook for new submissions on **any form you own**. Configure via **`GET/PUT /account/webhook`** or the Integrations page in the web app (same place as your API key). Guide: [Webhooks](https://docs.form-qr-code-generator.com/v1/index.htm#webhook-api). When enabled, TIGER FORM **POST**s a signed JSON payload to `url` on each new submission (`submission.created`). Payload includes `qrId` so one endpoint can handle all forms. Verify with header **`X-TigerForm-Signature`** (`sha256=` HMAC of the raw body using `secret`). Respond with HTTP **2xx** within 10 seconds.",
        "properties": {
          "enabled": {
            "type": "boolean",
            "default": false,
            "description": "When `true` and `url` is set, delivery runs for each new submission."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS endpoint (HTTP allowed in local development only). Max 2048 characters."
          },
          "secret": {
            "type": "string",
            "readOnly": true,
            "description": "HMAC signing secret. Generated when `url` is first saved; returned on **`GET /account/webhook`** (`data.secret`). Changing `url` alone does not rotate the secret. Cleared when webhook is disabled (`enabled: false`, empty `url`). Rotate with **`PUT`** and `rotateSecret: true` (see guide [Webhooks](https://docs.form-qr-code-generator.com/v1/index.htm#webhook-api))."
          },
          "rotateSecret": {
            "type": "boolean",
            "writeOnly": true,
            "description": "**PUT only.** When `true` and the webhook is enabled with a non-empty `url`, the server generates a new `secret`. Use after a suspected leak. Not returned on GET."
          }
        }
      },
      "WebhookSubmissionCreatedEvent": {
        "type": "object",
        "description": "JSON body POSTed to your webhook URL on `submission.created`. Guide: [Webhooks](https://docs.form-qr-code-generator.com/v1/index.htm#webhook-api).",
        "required": [
          "event",
          "qrId",
          "submission"
        ],
        "example": {
          "event": "submission.created",
          "qrId": "ABC123",
          "formTitle": "Contact form",
          "submission": {
            "id": "507f1f77bcf86cd799439011",
            "createdAt": "2026-06-01T12:00:00.000Z",
            "updatedAt": "2026-06-01T12:00:00.000Z",
            "answers": {
              "1748000000_3": "Jane Doe",
              "1748000000_7": [
                "Option 1"
              ]
            }
          }
        },
        "properties": {
          "event": {
            "type": "string",
            "enum": [
              "submission.created"
            ]
          },
          "qrId": {
            "type": "string"
          },
          "formTitle": {
            "type": "string"
          },
          "submission": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time"
              },
              "answers": {
                "type": "object",
                "additionalProperties": true,
                "description": "Same simplified map as **`POST /forms/{qrId}/submissions`**."
              },
              "quizData": {
                "type": "object",
                "description": "Present on quiz forms. Full stored scoring payload (not filtered by `showFinalScore` / `showAnswersResults` unlike create responses). Includes `points`, `totalMarks`, `percentage`, `passed`, `passingScore`, and `quizResult[]` with `question`, `answer`, `correct`, `points`, `earnedPoints`, `correctAnswer`."
              }
            }
          }
        }
      },
      "File": {
        "type": "object",
        "properties": {
          "fileId": {
            "type": "string",
            "default": ""
          },
          "fileUrl": {
            "type": "string",
            "default": ""
          }
        }
      },
      "AccountLogoFile": {
        "type": "object",
        "description": "Logo uploaded via POST /account/uploads (category=logo).",
        "required": [
          "fileId",
          "fileUrl"
        ],
        "properties": {
          "fileId": {
            "type": "string",
            "description": "Server-side file identifier"
          },
          "fileUrl": {
            "type": "string",
            "format": "uri",
            "description": "CDN or bucket URL of the stored image"
          },
          "mime": {
            "type": "string",
            "description": "MIME type (for example image/png)"
          },
          "fileUsed": {
            "type": "boolean",
            "description": "True when referenced by a form or QR config"
          }
        }
      },
      "AccountLogoListResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AccountLogoFile"
                }
              }
            }
          }
        ],
        "description": "Success body for GET /account/uploads."
      },
      "QRConfig": {
        "type": "object",
        "description": "QR code appearance object. Send as top-level **`qrConfig`** on **`POST /forms`** and **`PUT /forms/{qrId}`**. Guides: [How to Customize Your QR Code](https://docs.form-qr-code-generator.com/v1/index.htm#customize-qr-code), [Built-in QR Design Presets](https://docs.form-qr-code-generator.com/v1/index.htm#qr-design-templates-api), [Create a Form](https://docs.form-qr-code-generator.com/v1/index.htm#create-form).",
        "properties": {
          "backgroundColor": {
            "type": "string",
            "example": "#ffffff"
          },
          "colorDark": {
            "type": "string",
            "example": "#054080"
          },
          "eye_inner": {
            "type": "string",
            "enum": [
              "eyeInner0",
              "eyeInner1",
              "eyeInner2",
              "eyeInner3",
              "eyeInner4",
              "eyeInner5",
              "eyeInner6",
              "eyeInner7",
              "eyeInner8",
              "eyeInner9",
              "eyeInner10"
            ],
            "example": "eyeInner1"
          },
          "eye_outer": {
            "type": "string",
            "enum": [
              "eyeOuter0",
              "eyeOuter1",
              "eyeOuter2",
              "eyeOuter3",
              "eyeOuter4",
              "eyeOuter5",
              "eyeOuter6",
              "eyeOuter7",
              "eyeOuter8",
              "eyeOuter9",
              "eyeOuter10",
              "eyeOuter11",
              "eyeOuter12"
            ],
            "example": "eyeOuter2"
          },
          "logo": {
            "type": "string",
            "format": "uri",
            "example": "https://media.form-qr-code-generator.com/images/qrform/site-logo.png"
          },
          "qrCategory": {
            "type": "string",
            "readOnly": true,
            "description": "May appear in GET responses. Do not send on create or update.",
            "example": "url"
          },
          "qrData": {
            "type": "string",
            "enum": [
              "pattern0",
              "pattern1",
              "pattern2",
              "pattern3",
              "pattern4",
              "pattern5",
              "pattern6",
              "pattern7",
              "pattern8",
              "pattern9",
              "pattern10",
              "pattern11",
              "pattern12",
              "pattern13",
              "pattern14"
            ],
            "example": "pattern0"
          },
          "size": {
            "type": "number",
            "description": "Size in pixels",
            "example": 500
          },
          "transparentBkg": {
            "type": "boolean",
            "example": false
          },
          "gradient": {
            "type": "boolean",
            "description": "Enable gradient. color01 and color02 will be used for gradient.",
            "example": true
          },
          "grdType": {
            "type": "string",
            "enum": [
              "linear",
              "upDown",
              "diagonal1",
              "diagonal2",
              "radial"
            ],
            "example": "linear"
          },
          "color01": {
            "type": "string",
            "example": "#054080"
          },
          "color02": {
            "type": "string",
            "description": "Gradient end color. Used when gradient is enabled.",
            "example": "#f30505"
          },
          "eye_color": {
            "type": "boolean",
            "description": "Enable eye color. eye_color01 and eye_color02 will be used.",
            "example": true
          },
          "eye_color01": {
            "type": "string",
            "example": "#054080"
          },
          "eye_color02": {
            "type": "string",
            "example": "#f30505"
          },
          "frame": {
            "type": "integer",
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6,
              7,
              8,
              9,
              10,
              11,
              12,
              13,
              14,
              15,
              16
            ],
            "example": 1
          },
          "frameText": {
            "type": "string",
            "example": "SCAN ME"
          },
          "frameTextFont": {
            "type": "string",
            "enum": [
              "Arial",
              "Arial Black",
              "Comic Sans MS",
              "Courier New",
              "Helvetica",
              "Impact",
              "Tahoma",
              "Times New Roman",
              "Verdana",
              "Roboto",
              "Lato",
              "Oswald",
              "Slabo 27px",
              "Roboto Condensed",
              "Montserrat",
              "Source Sans Pro",
              "RaleWay",
              "PT Sans"
            ],
            "example": "Arial"
          },
          "frameColor": {
            "type": "string",
            "example": "#054080"
          },
          "frameColor2": {
            "type": "string",
            "description": "Frame secondary color. Some frames support secondary color: 5, 6, 10, 13, 14",
            "example": "#3a74c5"
          },
          "frameColorType": {
            "type": "string",
            "description": "Frame color gradient type. Determines the gradient direction/style for frame colors when using gradient mode. If value is 'fill', frame color will be a solid color.",
            "enum": [
              "fill",
              "linear",
              "upDown",
              "downUp",
              "diagonal1",
              "diagonal2",
              "radial"
            ],
            "example": "fill"
          },
          "frameGradientStartColor": {
            "type": "string",
            "example": "#054080"
          },
          "frameGradientEndColor": {
            "type": "string",
            "example": "#f30505"
          }
        }
      },
      "QrDesignTemplate": {
        "type": "object",
        "description": "A built-in QR styling preset. Copy `config` into the top-level **`qrConfig`** field on **`POST /forms`** or **`PUT /forms/{qrId}`** (same shape as schema **`QRConfig`**).",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable preset id (same as the web app template gallery)."
          },
          "previewUrl": {
            "type": "string",
            "format": "uri",
            "description": "Preview image URL for the preset."
          },
          "config": {
            "$ref": "#/components/schemas/QRConfig"
          }
        },
        "required": [
          "id",
          "previewUrl",
          "config"
        ]
      },
      "QrDesignTemplateListSuccess": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/QrDesignTemplate"
                }
              }
            }
          }
        ]
      },
      "FormAiBuilderGenerateRequest": {
        "type": "object",
        "required": [
          "prompt"
        ],
        "properties": {
          "prompt": {
            "type": "string",
            "minLength": 10,
            "description": "Natural-language description of the form to generate or modify (minimum 10 characters).",
            "example": "Create a registration form for a web development conference with name, email, and dietary preferences."
          },
          "currentForm": {
            "type": "object",
            "description": "Optional existing draft to refine. Use the same shape as the response / **`FormCreate`** (`title`, `shortText`, `fields` with **`type`** + **`option`**).",
            "properties": {
              "title": {
                "type": "string"
              },
              "shortText": {
                "type": "string"
              },
              "locale": {
                "type": "string",
                "description": "Two-letter language code (e.g. `en`, `vi`)."
              },
              "fields": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Field"
                }
              }
            }
          }
        }
      },
      "FormAiBuilderDraftForm": {
        "type": "object",
        "description": "AI-generated form draft in **`FormCreate`**-compatible shape. Review and send as **`POST /forms`** (or merge into an update).",
        "properties": {
          "title": {
            "type": "string",
            "example": "Conference registration"
          },
          "shortText": {
            "type": "string",
            "example": "Please complete the form below."
          },
          "locale": {
            "type": "string",
            "example": "en"
          },
          "isQuiz": {
            "type": "boolean",
            "description": "Present when the draft includes quiz fields (`quizConfig` on items)."
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          }
        }
      },
      "FormAiBuilderGenerateSuccess": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "$ref": "#/components/schemas/FormAiBuilderDraftForm"
              }
            }
          }
        ]
      },
      "FormFieldRead": {
        "type": "object",
        "description": "Field definition on GET/list responses: **`key`**, **`type`**, and **`option`**. Use **`key`** in submission **`answers`**. Not the create payload shape (`type` + `option` only).",
        "required": [
          "key",
          "type",
          "option"
        ],
        "properties": {
          "key": {
            "type": "string",
            "description": "Stable field id; use as the key in submission answers."
          },
          "type": {
            "type": "string"
          },
          "option": {
            "type": "object",
            "additionalProperties": true
          },
          "quizConfig": {
            "type": "object",
            "additionalProperties": true,
            "description": "May appear on quiz forms; per-field correct answers are not returned on GET."
          }
        },
        "additionalProperties": true
      },
      "Field": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/FieldName"
          },
          {
            "$ref": "#/components/schemas/FieldAddress"
          },
          {
            "$ref": "#/components/schemas/FieldPhone"
          },
          {
            "$ref": "#/components/schemas/FieldGender"
          },
          {
            "$ref": "#/components/schemas/FieldEmail"
          },
          {
            "$ref": "#/components/schemas/FieldTitle"
          },
          {
            "$ref": "#/components/schemas/FieldDescription"
          },
          {
            "$ref": "#/components/schemas/FieldCalendar"
          },
          {
            "$ref": "#/components/schemas/FieldTime"
          },
          {
            "$ref": "#/components/schemas/FieldShortText"
          },
          {
            "$ref": "#/components/schemas/FieldLongText"
          },
          {
            "$ref": "#/components/schemas/FieldRadio"
          },
          {
            "$ref": "#/components/schemas/FieldCheckbox"
          },
          {
            "$ref": "#/components/schemas/FieldMultipleLevelSelect"
          },
          {
            "$ref": "#/components/schemas/FieldCheckList"
          },
          {
            "$ref": "#/components/schemas/FieldLocation"
          },
          {
            "$ref": "#/components/schemas/FieldSignature"
          },
          {
            "$ref": "#/components/schemas/FieldNumber"
          },
          {
            "$ref": "#/components/schemas/FieldSheet"
          },
          {
            "$ref": "#/components/schemas/FieldAudio"
          },
          {
            "$ref": "#/components/schemas/FieldDocument"
          },
          {
            "$ref": "#/components/schemas/FieldPicture"
          },
          {
            "$ref": "#/components/schemas/FieldVideo"
          }
        ],
        "discriminator": {
          "propertyName": "type"
        }
      },
      "FieldName": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "name"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default: ''",
                "default": ""
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldAddress": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "address"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default: ''",
                "default": ""
              },
              "states": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "States list (for Address). Optional. If omitted, system will use default: []",
                "default": []
              },
              "showFields": {
                "type": "object",
                "description": "Show/hide address subfields (for Address). Optional. If omitted, system will use default: {addressLine:true, city:true, state:true, zipcode:true, country:false}",
                "default": {
                  "addressLine": true,
                  "city": true,
                  "state": true,
                  "zipcode": true,
                  "country": false
                },
                "properties": {
                  "addressLine": {
                    "type": "boolean",
                    "default": true
                  },
                  "city": {
                    "type": "boolean",
                    "default": true
                  },
                  "state": {
                    "type": "boolean",
                    "default": true
                  },
                  "zipcode": {
                    "type": "boolean",
                    "default": true
                  },
                  "country": {
                    "type": "boolean",
                    "default": false
                  }
                }
              },
              "addressFormat": {
                "type": "string",
                "description": "Address format (for Address). Optional. If omitted, system will use default: '[addressLine]\n[city], [state] [zipcode]\n[country]'",
                "default": "[addressLine]\n[city], [state] [zipcode]\n[country]"
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldPhone": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "phone"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "mask": {
                "type": "string",
                "description": "Input mask (for Phone). Optional. If omitted, system will use default value: ''",
                "default": ""
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldGender": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "gender"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldEmail": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "email"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldTitle": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "title"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldDescription": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "description"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "description": {
                "type": "string",
                "description": "Description (for Description field). Optional. If omitted, system will use default value: ''",
                "default": ""
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldCalendar": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "calendar"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "dateFormat": {
                "type": "string",
                "description": "Date format (for Calendar). Optional. If omitted, system will use default value: 'mm/dd/yy'",
                "default": "mm/dd/yy"
              },
              "defaultToCurrentDate": {
                "type": "boolean",
                "description": "Default to current date (for Calendar). Optional. If omitted, system will use default value: true",
                "default": true
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldTime": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "time"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "dateFormat": {
                "type": "string",
                "description": "Date format (for Time). Optional. If omitted, system will use default value: 'mm/dd/yy'",
                "default": "mm/dd/yy"
              },
              "timeOnly": {
                "type": "boolean",
                "description": "Time only (for Time). Optional. If omitted, system will use default value: false",
                "default": false
              },
              "timeFormat": {
                "type": "string",
                "description": "Time format (for Time). Optional. If omitted, system will use default value: 'HH:mm'",
                "default": "HH:mm"
              },
              "hideThisField": {
                "type": "boolean",
                "description": "Hide this field (for Time). Optional. If omitted, system will use default value: false",
                "default": false
              },
              "defaultToCurrentDate": {
                "type": "boolean",
                "description": "Default to current date (for Time). Optional. If omitted, system will use default value: true",
                "default": true
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "QuizFormConfig": {
        "type": "object",
        "description": "Form-level quiz settings when `isQuiz` is true. Each setting is validated against your subscription on `POST /forms` and `PUT /forms/{qrId}`. HTTP **400** with `status: failed` if a setting is not allowed on your plan. See guide [Quiz Forms](https://docs.form-qr-code-generator.com/v1/index.htm#quiz-forms).",
        "properties": {
          "passingScore": {
            "type": "number",
            "description": "Minimum percentage to pass (default **70**). Values other than 70 may require Business plan or higher.",
            "default": 70
          },
          "distributeMarksEvenly": {
            "type": "boolean",
            "description": "Split total marks equally across questions. Requires Business plan or higher."
          },
          "enableTimeLimit": {
            "type": "boolean",
            "description": "Enforce a time limit for the quiz. Requires Business plan or higher."
          },
          "timeLimit": {
            "type": "integer",
            "description": "Time limit in seconds (default **1800** when enabled). Custom durations may require Business plan or higher.",
            "default": 1800
          },
          "shuffleQuestions": {
            "type": "boolean",
            "description": "Randomize question order per attempt. Requires Business plan or higher."
          },
          "showFinalScore": {
            "type": "boolean",
            "description": "Show final score at end. Availability varies by plan."
          },
          "showAnswersResults": {
            "type": "boolean",
            "description": "Reveal correct answers at end. Availability varies by plan."
          },
          "stepByStep": {
            "type": "boolean",
            "description": "Show one question at a time. Availability varies by plan."
          },
          "passMessage": {
            "type": "string",
            "description": "Custom message when the respondent passes. Availability varies by plan."
          },
          "failMessage": {
            "type": "string",
            "description": "Custom message when the respondent fails. Availability varies by plan."
          },
          "timeUpMessage": {
            "type": "string",
            "description": "Custom message when time expires. Availability varies by plan."
          }
        }
      },
      "QuizFieldConfig": {
        "type": "object",
        "description": "Per-question quiz settings on scored field types (`radio`, `checkbox`, `shortText`, `number`) when `option.disableQuiz` is **false**. Required on create/update: `points` and `correctAnswers` for each scored question.",
        "properties": {
          "points": {
            "type": "number",
            "description": "Marks awarded for a correct answer (may be **0**)."
          },
          "correctAnswers": {
            "description": "Expected answer(s). Radio: single string matching an option `value`. Checkbox: array of option values. Short text / number: string or array of acceptable values; the number of accepted values may be limited by plan.",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "number"
                    }
                  ]
                }
              }
            ]
          }
        },
        "required": [
          "points",
          "correctAnswers"
        ]
      },
      "FieldShortText": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "shortText"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "enableScan": {
                "type": "boolean",
                "description": "Enable scan (for ShortText). Optional. If omitted, system will use default value: false",
                "default": false
              },
              "disableQuiz": {
                "type": "boolean",
                "description": "When `isQuiz` is true: **false** marks this field as a scored question; **true** (default) excludes it from scoring.",
                "default": true
              }
            }
          },
          "quizConfig": {
            "$ref": "#/components/schemas/QuizFieldConfig",
            "description": "Required when `option.disableQuiz` is **false** on a quiz form."
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldLongText": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "longText"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "rows": {
                "type": "integer",
                "description": "Number of rows (for LongText). Optional. If omitted, system will use default value: 4",
                "default": 4
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldRadio": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "radio"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "options": {
                "type": "array",
                "description": "Options for Radio fields. Optional. If omitted, system will use default value: []",
                "default": [],
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "value": {
                      "type": "string"
                    },
                    "key": {
                      "type": "integer"
                    },
                    "image": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  }
                }
              },
              "layout": {
                "type": "string",
                "description": "Layout for options (list, dropdown, etc). Optional. If omitted, system will use default value: 'list'",
                "default": "list"
              },
              "disableQuiz": {
                "type": "boolean",
                "description": "When `isQuiz` is true: **false** marks this field as a scored question; **true** (default) excludes it from scoring.",
                "default": true
              }
            }
          },
          "quizConfig": {
            "$ref": "#/components/schemas/QuizFieldConfig",
            "description": "Required when `option.disableQuiz` is **false** on a quiz form."
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldCheckbox": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "checkbox"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "options": {
                "type": "array",
                "description": "Options for Checkbox fields. Optional. If omitted, system will use default value: []",
                "default": [],
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "value": {
                      "type": "string"
                    },
                    "key": {
                      "type": "integer"
                    },
                    "image": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  }
                }
              },
              "layout": {
                "type": "string",
                "description": "Layout for options (list, dropdown, etc). Optional. If omitted, system will use default value: 'list'",
                "default": "list"
              },
              "maxSelectable": {
                "description": "Max selectable options (for Checkbox). Optional. If omitted, system will use default value: null",
                "default": null,
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "disableQuiz": {
                "type": "boolean",
                "description": "When `isQuiz` is true: **false** marks this field as a scored question; **true** (default) excludes it from scoring.",
                "default": true
              }
            }
          },
          "quizConfig": {
            "$ref": "#/components/schemas/QuizFieldConfig",
            "description": "Required when `option.disableQuiz` is **false** on a quiz form."
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldMultipleLevelSelect": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "multipleLevelSelect"
            ],
            "description": "Cascade / multi-level select field type (camelCase)."
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "selectData": {
                "type": "string",
                "description": "Select data for MultipleLevelSelect. Optional. If omitted, system will use default value: 'select/select/select/select/'",
                "default": "select/select/select/select/"
              },
              "sapmleSelectData": {
                "type": "string",
                "description": "Sample select data for MultipleLevelSelect. Optional. If omitted, system will use default value: ''",
                "default": ""
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldCheckList": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "checkList"
            ],
            "description": "Checklist field type (camelCase)."
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "items": {
                "type": "array",
                "description": "Items for CheckList fields. Optional. If omitted, system will use default value: []",
                "default": [],
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    }
                  }
                }
              },
              "checkOptions": {
                "type": "array",
                "description": "Check options for CheckList fields. Optional. If omitted, system will use default value: ['_d1', '_d2', null]",
                "default": [
                  "_d1",
                  "_d2",
                  null
                ],
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "enableNeutral": {
                "type": "boolean",
                "description": "Enable neutral option (for CheckList). Optional. If omitted, system will use default value: false",
                "default": false
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldLocation": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "location"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldSignature": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "signature"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldNumber": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "number"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "min": {
                "description": "Minimum value (for Number). Optional. If omitted, system will use default value: null",
                "default": null,
                "anyOf": [
                  {
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "max": {
                "description": "Maximum value (for Number). Optional. If omitted, system will use default value: null",
                "default": null,
                "anyOf": [
                  {
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "enableScan": {
                "type": "boolean",
                "description": "Enable scan (for Number). Optional. If omitted, system will use default value: false",
                "default": false
              },
              "disableQuiz": {
                "type": "boolean",
                "description": "When `isQuiz` is true: **false** marks this field as a scored question; **true** (default) excludes it from scoring.",
                "default": true
              }
            }
          },
          "quizConfig": {
            "$ref": "#/components/schemas/QuizFieldConfig",
            "description": "Required when `option.disableQuiz` is **false** on a quiz form."
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldSheet": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "sheet"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "rowLabels": {
                "type": "array",
                "description": "Row labels for Sheet fields. Optional. If omitted, system will use default value: []",
                "default": [],
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldAudio": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "audio"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldDocument": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "document"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "maxFiles": {
                "type": "integer",
                "description": "Max files (for Document). Optional. If omitted, system will use default value: 10",
                "default": 10
              },
              "maxFileSize": {
                "type": "integer",
                "description": "Max file size in MB (for Document). Optional. If omitted, system will use default value: 20",
                "default": 20
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldPicture": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "picture"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              },
              "maxFiles": {
                "type": "integer",
                "description": "Max files (for Picture). Optional. If omitted, system will use default value: 10",
                "default": 10
              },
              "maxFileSize": {
                "type": "integer",
                "description": "Max file size in MB (for Picture). Optional. If omitted, system will use default value: 20",
                "default": 20
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "FieldVideo": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "video"
            ]
          },
          "option": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "description": "Field label. Optional. If omitted, system will use type value"
              },
              "required": {
                "type": "boolean",
                "description": "Is this field required? Optional. If omitted, system will use default value: false",
                "default": false
              },
              "hint": {
                "type": "string",
                "description": "Hint for the field. Optional. If omitted, system will use default value: ''",
                "default": ""
              }
            }
          }
        },
        "required": [
          "type"
        ]
      },
      "ApiNotFoundError": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiFailedResponse"
          }
        ],
        "description": "HTTP **404** when the request URL does not match any documented path or method in this specification. Wrong `qrId` or other ids on a valid route usually return **400**, not this schema."
      },
      "ApiServerError": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiFailedResponse"
          }
        ],
        "description": "HTTP **500** for unexpected errors on a documented route (normalized JSON body)."
      },
      "FormTemplatePreviewImage": {
        "type": "object",
        "description": "Preview image metadata inside a template list item.",
        "properties": {
          "fileUrl": {
            "type": "string",
            "format": "uri"
          },
          "fileId": {
            "type": "string"
          }
        }
      },
      "FormTemplateListItem": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "categoryId": {
            "type": "string"
          },
          "categoryName": {
            "type": "string"
          },
          "form": {
            "type": "object",
            "properties": {
              "previewImage": {
                "$ref": "#/components/schemas/FormTemplatePreviewImage"
              }
            }
          },
          "id": {
            "type": "string",
            "description": "Template id"
          }
        }
      },
      "FormTemplateDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FormTemplateListItem"
          },
          {
            "type": "object",
            "properties": {
              "metaTitle": {
                "type": "string"
              },
              "metaDescription": {
                "type": "string"
              },
              "h1": {
                "type": "string"
              },
              "isNew": {
                "type": "boolean",
                "description": "True when created within the last 90 days."
              },
              "form": {
                "type": "object",
                "additionalProperties": true,
                "description": "Full template form definition (`form.fields` object, styling, preview image, etc.). To create a live form, call **`GET /form-templates/{templateId}/form-create`** and pass `data` to **`POST /forms`**. Guide: [Form Templates API](https://docs.form-qr-code-generator.com/v1/index.htm#form-templates-api)."
              }
            }
          }
        ]
      },
      "FormTemplateListSuccess": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/FormTemplateListItem"
                }
              }
            }
          }
        ]
      },
      "FormTemplateDetailSuccess": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "$ref": "#/components/schemas/FormTemplateDetail"
              }
            }
          }
        ]
      },
      "FormTemplateFormCreateSuccess": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "$ref": "#/components/schemas/FormCreate",
                "description": "Ready-to-send body for **`POST /forms`**. Field map keys from the template are omitted; each item has `type` and `option` only.",
                "example": {
                  "title": "Contact form",
                  "shortText": "Get in touch",
                  "fields": [
                    {
                      "type": "shortText",
                      "option": {
                        "label": "Name",
                        "required": true
                      }
                    },
                    {
                      "type": "email",
                      "option": {
                        "label": "Email",
                        "required": true
                      }
                    }
                  ]
                }
              }
            }
          }
        ]
      },
      "FormTemplateCreateBody": {
        "type": "object",
        "required": [
          "categoryId",
          "title",
          "form"
        ],
        "properties": {
          "categoryId": {
            "type": "string",
            "description": "Category id (24-character hex string)."
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "form": {
            "type": "object",
            "additionalProperties": true,
            "description": "Template form layout (`form.fields` as an object keyed by field id). Use **`GET /form-templates/{templateId}/form-create`** to obtain a `POST /forms` body. Guide: [Form Templates API](https://docs.form-qr-code-generator.com/v1/index.htm#form-templates-api)."
          }
        }
      },
      "FormTemplateShareBody": {
        "type": "object",
        "required": [
          "recipients"
        ],
        "properties": {
          "recipients": {
            "type": "string",
            "description": "Comma-separated recipient emails (max 5)."
          },
          "fromName": {
            "type": "string",
            "description": "Optional sender display name. When omitted, the server may use the name from the authenticated account."
          }
        }
      },
      "FormTemplateCategoryListSuccess": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/FormTemplateCategory"
                }
              }
            }
          }
        ]
      },
      "FormTemplateCategory": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Category id (24-character hex string)."
          },
          "name": {
            "type": "string"
          },
          "parentId": {
            "type": "string",
            "description": "\"0\" for root categories."
          },
          "h1": {
            "type": "string"
          },
          "metaTitle": {
            "type": "string"
          },
          "metaDescription": {
            "type": "string"
          },
          "formTemplates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FormTemplateListItem"
            },
            "description": "Present on root categories when `items=1`."
          }
        }
      },
      "SubmissionCreateResponse": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/SubmissionCreateNonQuizResponse"
          },
          {
            "$ref": "#/components/schemas/SubmissionCreateQuizResponse"
          }
        ],
        "description": "Success after creating a submission. Non-quiz: `{ status, data: { submissionId } }`. Quiz: optional score fields in `data`."
      },
      "FormsListSuccessResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "required": [
                  "items",
                  "total",
                  "page",
                  "pageSize",
                  "totalPages"
                ],
                "properties": {
                  "total": {
                    "type": "integer",
                    "description": "Total matching forms (all pages)"
                  },
                  "page": {
                    "type": "integer",
                    "description": "Current page number"
                  },
                  "pageSize": {
                    "type": "integer",
                    "description": "Page size used for this request"
                  },
                  "totalPages": {
                    "type": "integer",
                    "description": "Ceiling of total / pageSize"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/FormListItem"
                    },
                    "description": "Forms for this page"
                  }
                }
              }
            },
            "required": [
              "data"
            ]
          }
        ],
        "description": "Paginated form list (`GET /forms`). HTTP **200** with `data.items: []` and `data.total: 0` when the account has no forms."
      },
      "FormAnalyticsSuccessResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "$ref": "#/components/schemas/PublicDataAnalyticsResponse"
              }
            },
            "required": [
              "data"
            ]
          }
        ],
        "description": "JSON analytics summary for `GET /forms/{qrId}/analytics` (when `export` is not `1`).",
        "example": {
          "status": "success",
          "data": {
            "form": {
              "qrId": "ABC123",
              "title": "Contact form"
            },
            "period": "month",
            "submissionFilter": false,
            "scans": 42,
            "uniqueScans": 38,
            "timeseries": {
              "all": [
                {
                  "count": 12,
                  "bucket": {
                    "year": 2025,
                    "month": 6,
                    "day": 1
                  },
                  "date": "2025-06-01"
                }
              ],
              "unique": [
                {
                  "count": 10,
                  "bucket": {
                    "year": 2025,
                    "month": 6,
                    "day": 1
                  },
                  "date": "2025-06-01"
                }
              ]
            },
            "devices": [
              {
                "device": "mobile",
                "count": 30
              }
            ],
            "countries": [
              {
                "country": "US",
                "count": 20
              }
            ],
            "cities": [
              {
                "city": "Bangkok",
                "count": 15
              }
            ],
            "geoBreakdown": [
              {
                "device": "mobile",
                "country": "US",
                "city": "Bangkok",
                "count": 5
              }
            ],
            "topLocations": [
              {
                "city": "Bangkok",
                "device": "mobile",
                "count": 10
              }
            ],
            "socialButtons": []
          }
        }
      },
      "FormAnalyticsExportSuccessResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiSuccessEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "$ref": "#/components/schemas/PublicDataExportResponse"
              }
            },
            "required": [
              "data"
            ]
          }
        ],
        "description": "CSV export link when `export=1` on `GET /forms/{qrId}/analytics`."
      },
      "AnalyticsTimeseriesPoint": {
        "type": "object",
        "description": "One bucket in `timeseries.all` or `timeseries.unique` on analytics responses.",
        "properties": {
          "count": {
            "type": "integer"
          },
          "bucket": {
            "type": "object",
            "description": "Time grouping key; shape depends on `period` (day/month may include `year`, `month`, `day`; hour buckets may include `hour`).",
            "properties": {
              "year": {
                "type": "integer"
              },
              "month": {
                "type": "integer"
              },
              "day": {
                "type": "integer"
              },
              "hour": {
                "type": "integer"
              }
            }
          },
          "date": {
            "type": "string",
            "description": "Calendar date when the bucket maps to a day (YYYY-MM-DD)."
          }
        }
      },
      "PublicDataAnalyticsResponse": {
        "type": "object",
        "description": "Scan analytics summary for a form (`GET /forms/{qrId}/analytics`).",
        "properties": {
          "form": {
            "type": "object",
            "properties": {
              "qrId": {
                "type": "string"
              },
              "title": {
                "type": "string"
              }
            }
          },
          "period": {
            "type": "string"
          },
          "submissionFilter": {
            "type": "boolean"
          },
          "scans": {
            "type": "integer"
          },
          "uniqueScans": {
            "type": "integer"
          },
          "timeseries": {
            "type": "object",
            "properties": {
              "all": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AnalyticsTimeseriesPoint"
                }
              },
              "unique": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AnalyticsTimeseriesPoint"
                }
              }
            }
          },
          "devices": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "countries": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "cities": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "geoBreakdown": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "topLocations": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "socialButtons": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "PublicDataExportResponse": {
        "type": "object",
        "description": "CSV export response when `export=1` is passed on `GET /forms/{qrId}/analytics`.",
        "properties": {
          "csvUrl": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS URL to download scan rows as a CSV file for the selected period and filters."
          }
        }
      },
      "FormAnalyticsResponse": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/FormAnalyticsSuccessResponse"
          },
          {
            "$ref": "#/components/schemas/FormAnalyticsExportSuccessResponse"
          }
        ],
        "description": "JSON analytics summary (default) or CSV export link when `export=1`. See component examples on each branch schema."
      }
    },
    "responses": {
      "PlanApiQuota429": {
        "description": "Monthly API request limit reached (enforced as `apiLimit`)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiRateLimitError"
            }
          }
        }
      },
      "RoleForbidden403": {
        "description": "Authenticated but not allowed for this action. Common cases: **Viewer** on `POST /forms`; **Editor** or **Viewer** on account webhook routes; **Editor** or **Viewer** on team management routes. See guide [Core Concepts](https://docs.form-qr-code-generator.com/v1/index.htm#core-concepts).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiFailedResponse"
            }
          }
        }
      },
      "IdempotencyConflict409": {
        "description": "Idempotency-Key reused with a different request body on `POST /forms/{qrId}/submissions`",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiFailedResponse"
            },
            "example": {
              "status": "failed",
              "message": "Idempotency-Key was already used with a different request body.",
              "code": 409,
              "data": {}
            }
          }
        }
      }
    }
  },
  "paths": {
    "/forms": {
      "get": {
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "required": false,
            "description": "Page index (1-based). Default: 1."
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "default": 5,
              "minimum": 1
            },
            "required": false,
            "description": "Page size (forms per page). Default: 5."
          },
          {
            "in": "query",
            "name": "archive",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "required": false,
            "description": "If true, list archived forms instead of active ones."
          },
          {
            "in": "query",
            "name": "sort",
            "schema": {
              "type": "integer",
              "enum": [
                1,
                2,
                3
              ],
              "default": 1
            },
            "required": false,
            "description": "Sort order: `1` = newest first (`createdAt` desc), `2` = by name (A→Z), `3` = by scan count desc."
          }
        ],
        "operationId": "getFormsList",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "Bearer": []
          }
        ],
        "summary": "List forms",
        "description": "Paginated list of forms on your account. Guide: [Manage Forms](https://docs.form-qr-code-generator.com/v1/index.htm#manage-forms).",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormsListSuccessResponse"
                },
                "examples": {
                  "withItems": {
                    "summary": "One page with forms",
                    "value": {
                      "status": "success",
                      "data": {
                        "total": 2,
                        "page": 1,
                        "pageSize": 5,
                        "totalPages": 1,
                        "items": [
                          {
                            "id": "507f1f77bcf86cd799439011",
                            "qrId": "ABC123",
                            "title": "Contact form",
                            "shortText": "Contact us",
                            "shortUrl": "https://tgr.li/ABC123",
                            "previewImage": "https://cdn.example.com/previews/abc.png",
                            "scans": 120,
                            "submissions": 45,
                            "active": true,
                            "createdAt": "2025-06-01T10:00:00.000Z",
                            "updatedAt": "2025-06-15T08:30:00.000Z"
                          }
                        ]
                      }
                    }
                  },
                  "empty": {
                    "summary": "No forms on this account",
                    "value": {
                      "status": "success",
                      "data": {
                        "total": 0,
                        "page": 1,
                        "pageSize": 5,
                        "totalPages": 0,
                        "items": []
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or server validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createForm",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "Bearer": []
          }
        ],
        "summary": "Create form",
        "description": "Create a new form (`title`, `shortText`, `fields`). Viewer role → **403**. Sending existing `qrId` in body updates that form (legacy) — prefer **PUT**. Guide: [Create a Form](https://docs.form-qr-code-generator.com/v1/index.htm#create-form).",
        "requestBody": {
          "description": "Body must match `FormCreate`. Additional fields may apply for specific form types (see schema and your account capabilities).",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FormCreate"
              },
              "example": {
                "title": "Contact form",
                "shortText": "Please fill out the form",
                "fields": [
                  {
                    "type": "shortText",
                    "option": {
                      "label": "Name",
                      "required": true
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Form created or draft updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "success"
                      ],
                      "example": "success"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Form"
                    }
                  },
                  "required": [
                    "status",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error, GPS config error, QR generation failure, or other bad input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/RoleForbidden403"
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Forms"
        ],
        "operationId": "deleteMultipleForms",
        "summary": "Delete multiple forms",
        "description": "Delete forms you own. Pass `ids` as repeated query params (`?ids=A&ids=B`). Viewer cannot delete.",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ids",
            "in": "query",
            "required": true,
            "description": "Form ids (`qrId`) to delete; repeat the query param for each id (e.g. `?ids=ABC&ids=DEF`). At least one non-empty value is required.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "style": "form",
            "explode": true
          }
        ],
        "responses": {
          "200": {
            "description": "Deletion completed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MultiDeleteFormsSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Missing or empty **`ids`** query; **no matching** form ids; **permission denied** (e.g. **Viewer**, or **Editor** deleting another member's form); or other validation error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/forms/{qrId}/submission-schema": {
      "get": {
        "operationId": "getFormSubmissionSchema",
        "tags": [
          "Forms"
        ],
        "summary": "Get submission answer schema for a form",
        "description": "Field keys and `valueType` for building `answers`. Guide: [Create a Submission](https://docs.form-qr-code-generator.com/v1/index.htm#create-submission).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "qrId",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            },
            "description": "Form id"
          }
        ],
        "responses": {
          "200": {
            "description": "Submission schema",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionSchemaResponse"
                },
                "example": {
                  "status": "success",
                  "data": {
                    "qrId": "ABC123",
                    "title": "API demo form",
                    "fields": {
                      "1748000000_3": {
                        "key": "1748000000_3",
                        "label": "Name",
                        "required": true,
                        "valueType": "string",
                        "type": "shortText"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid `qrId` or form not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/forms/{qrId}": {
      "get": {
        "operationId": "getFormById",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "Bearer": []
          }
        ],
        "summary": "Get form by qrId",
        "description": "Form detail including `fields[].key`. Unknown qrId → **400**. Guide: [Manage Forms](https://docs.form-qr-code-generator.com/v1/index.htm#manage-forms).",
        "parameters": [
          {
            "in": "path",
            "name": "qrId",
            "required": true,
            "description": "Public form identifier (uppercase letters and digits)",
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            }
          },
          {
            "in": "query",
            "name": "scan",
            "required": false,
            "description": "Set to `1` to count this request as a scan when the form exists and rules allow.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Form detail",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "success"
                      ],
                      "example": "success"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Form"
                    }
                  },
                  "required": [
                    "status",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid `qrId` format, or form does not exist / owner blocked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateFormById",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "Bearer": []
          }
        ],
        "summary": "Update form",
        "description": "Update an existing form (partial body, same shape as create). **Prefer this over POST with qrId.** Viewer → **400**. Guide: [Manage Forms](https://docs.form-qr-code-generator.com/v1/index.htm#manage-forms).",
        "parameters": [
          {
            "in": "path",
            "name": "qrId",
            "required": true,
            "description": "Form identifier",
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            }
          }
        ],
        "requestBody": {
          "description": "Same general shape as create; include fields you want to persist.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/FormCreate"
                  },
                  {
                    "$ref": "#/components/schemas/FormDetail"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated form",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "success"
                      ],
                      "example": "success"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Form"
                    }
                  },
                  "required": [
                    "status",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error, not found, not allowed (e.g. Viewer), or GPS config error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteFormById",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "Bearer": []
          }
        ],
        "summary": "Delete form",
        "description": "Delete one form (scan count and role rules apply). Viewer cannot delete.",
        "parameters": [
          {
            "in": "path",
            "name": "qrId",
            "required": true,
            "description": "Form identifier",
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Form deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteFormSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Not allowed (e.g. Viewer) or business rule failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unhandled error (e.g. constraint failed after series step)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          }
        }
      }
    },
    "/account/uploads": {
      "get": {
        "operationId": "listAccountUploads",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "Bearer": []
          }
        ],
        "summary": "List uploaded account logos",
        "description": "List account logo uploads. Guide: [Account API](https://docs.form-qr-code-generator.com/v1/index.htm#account-api).",
        "parameters": [
          {
            "in": "query",
            "name": "category",
            "required": false,
            "description": "Only `logo` is supported on the public API.",
            "schema": {
              "type": "string",
              "enum": [
                "logo"
              ],
              "default": "logo"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Logo list (may be empty)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountLogoListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Unsupported category value",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected error while loading the list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "uploadAccountFile",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "Bearer": []
          }
        ],
        "summary": "Upload account logo",
        "description": "Upload account logo (`category=logo`, multipart `userFile`, max 20 MB). Guide: [Upload APIs Compared](https://docs.form-qr-code-generator.com/v1/index.htm#upload-apis-compared).",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "userFile",
                  "category"
                ],
                "properties": {
                  "userFile": {
                    "type": "string",
                    "format": "binary",
                    "description": "The File to Upload"
                  },
                  "category": {
                    "type": "string",
                    "enum": [
                      "logo"
                    ],
                    "description": "Category of the file"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Logo stored; returns normalized `File` record in public envelope when applicable",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "success"
                      ],
                      "example": "success"
                    },
                    "data": {
                      "$ref": "#/components/schemas/File"
                    }
                  },
                  "required": [
                    "status",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Missing file or unsupported image type",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected failure while storing the file, or file exceeds 20 MB (`message`: `uploaded file is too large`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/account/webhook": {
      "get": {
        "operationId": "getAccountWebhook",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "Bearer": []
          }
        ],
        "summary": "Get account webhook settings",
        "description": "Read webhook URL and signing secret. Owner/Admin only. Guide: [Webhooks](https://docs.form-qr-code-generator.com/v1/index.htm#webhook-api).",
        "responses": {
          "200": {
            "description": "Webhook settings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "data"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "success"
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/AccountWebhook"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/RoleForbidden403"
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          }
        }
      },
      "put": {
        "operationId": "updateAccountWebhook",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "Bearer": []
          }
        ],
        "summary": "Update account webhook settings",
        "description": "Enable, disable, or rotate webhook secret. Owner/Admin only. Guide: [Webhooks](https://docs.form-qr-code-generator.com/v1/index.htm#webhook-api).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccountWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated webhook settings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "data"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "success"
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/AccountWebhook"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid URL or payload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/RoleForbidden403"
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          }
        }
      }
    },
    "/forms/{qrId}/uploads": {
      "post": {
        "operationId": "uploadFormFile",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "qrId",
            "required": true,
            "description": "Target form id",
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            }
          },
          {
            "in": "query",
            "name": "cat",
            "required": false,
            "description": "Use `submission` for submission attachments, `form` for assets belonging to the form itself.",
            "schema": {
              "type": "string",
              "enum": [
                "form",
                "submission"
              ],
              "default": "submission"
            }
          }
        ],
        "summary": "Upload file for a form or submission",
        "description": "Upload form asset or submission file (`category=form` or `submission`). Multipart `userFile`, max 20 MB. Unknown form → **404**. Guide: [Upload APIs Compared](https://docs.form-qr-code-generator.com/v1/index.htm#upload-apis-compared).",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "userFile",
                  "category"
                ],
                "properties": {
                  "userFile": {
                    "type": "string",
                    "format": "binary",
                    "description": "The File to Upload"
                  },
                  "category": {
                    "type": "string",
                    "enum": [
                      "form",
                      "submission"
                    ],
                    "description": "Category of the file"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upload succeeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionUploadSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Missing file or unsupported file type for the category",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (same Bearer API-key auth as other public routes)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Form not found for this API key, archived, or owner blocked (integration handler). A malformed `qrId` (not matching `^[A-Z0-9]+$`) may also return **404** on POST — unlike DELETE, which returns **400** for invalid format before lookup.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded for `category=submission` uploads (200 requests per 5 minutes per client IP and `qrId`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "500": {
            "description": "Server error while saving the file, or file exceeds 20 MB (`message`: `uploaded file is too large`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/forms/{qrId}/uploads/{fileId}": {
      "delete": {
        "operationId": "deleteFormFile",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "Bearer": []
          }
        ],
        "summary": "Delete an uploaded form or submission file",
        "description": "Delete a file uploaded with POST /forms/{qrId}/uploads. Invalid qrId format → **400**.",
        "parameters": [
          {
            "in": "path",
            "name": "qrId",
            "required": true,
            "description": "Target form id",
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            }
          },
          {
            "in": "path",
            "name": "fileId",
            "required": true,
            "description": "File id from upload response `data.fileId`",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File deleted (or already absent; idempotent success)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiSuccessEnvelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid `qrId` format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Form not found for this API key, or file not found for this form",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected error while deleting the file",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/forms/{qrId}/archive": {
      "put": {
        "tags": [
          "Forms"
        ],
        "operationId": "archiveForm",
        "summary": "Archive form",
        "description": "Archive a form (hidden from default list).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "name": "qrId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            },
            "description": "Form identifier (`qrId`, e.g. `ABC123`)."
          }
        ],
        "responses": {
          "200": {
            "description": "Archived (or idempotent message if already archived)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteFormSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Not found, not allowed, or processing error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/forms/{qrId}/restore": {
      "put": {
        "tags": [
          "Forms"
        ],
        "operationId": "restoreArchivedForm",
        "summary": "Restore archived form",
        "description": "Restore an archived form.",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "name": "qrId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            },
            "description": "Form identifier (`qrId`, e.g. `ABC123`)."
          }
        ],
        "responses": {
          "200": {
            "description": "Restored or already active",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteFormSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Not found, not allowed, or save error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/forms/{qrId}/download": {
      "get": {
        "tags": [
          "Forms"
        ],
        "operationId": "downloadFormQrImage",
        "summary": "Download form QR image (custom format)",
        "description": "Download QR image (binary response, not JSON). Requires `format` query param. Guide: [End-to-End Integration](https://docs.form-qr-code-generator.com/v1/index.htm#end-to-end-integration) Step 5.",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "name": "qrId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            },
            "description": "Form id (`qrId`)"
          },
          {
            "name": "format",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "png",
                "svg",
                "pdf",
                "eps"
              ],
              "example": "png"
            },
            "description": "Output format: `png`, `svg`, `pdf`, or `eps`."
          },
          {
            "name": "resolution",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "example": 500
            },
            "description": "Pixel size when rasterizing from SVG (used for png, pdf, eps, and svg viewBox sizing)"
          }
        ],
        "responses": {
          "200": {
            "description": "Binary file body. `Content-Type` matches the requested `format` (e.g. `image/png` for `format=png`).",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/svg+xml": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/postscript": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            },
            "headers": {
              "Content-Type": {
                "description": "MIME type for the requested format",
                "schema": {
                  "type": "string",
                  "example": "image/png"
                }
              },
              "Content-Disposition": {
                "description": "Attachment filename",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Length": {
                "description": "Size of the binary body in bytes",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "400": {
            "description": "Missing parameters or client error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Form not found or render failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          }
        }
      }
    },
    "/forms/{qrId}/clone": {
      "post": {
        "tags": [
          "Forms"
        ],
        "operationId": "cloneForm",
        "summary": "Clone form(s)",
        "description": "Create one or more copies of a form.",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "name": "qrId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            },
            "description": "Form identifier (`qrId`, e.g. `ABC123`)."
          },
          {
            "name": "numberofCopies",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1,
              "maximum": 20
            },
            "description": "How many clones to create"
          }
        ],
        "responses": {
          "200": {
            "description": "Clones created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CloneFormResponse"
                }
              }
            }
          },
          "400": {
            "description": "Quota, permission, or pipeline error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/forms/{qrId}/share": {
      "post": {
        "tags": [
          "Forms"
        ],
        "operationId": "shareFormByEmail",
        "summary": "Share form by email",
        "description": "Email form link to recipients (comma-separated string, max 5).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "name": "qrId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            },
            "description": "Form identifier (`qrId`, e.g. `ABC123`)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "recipients"
                ],
                "properties": {
                  "recipients": {
                    "type": "string",
                    "description": "Comma-separated emails, max 5",
                    "example": "a@example.com,b@example.com"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmptyDataSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Invalid recipients, not found, or mail error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/forms/{qrId}/submissions": {
      "get": {
        "operationId": "submissionListByForm",
        "tags": [
          "Submissions"
        ],
        "summary": "List submissions for a form",
        "description": "Paginated submissions for a form. Optional `since` / `until`. Empty list → **200** with `items: []`. Guide: [Read Submissions](https://docs.form-qr-code-generator.com/v1/index.htm#read-submissions).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "qrId",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            },
            "description": "Form id"
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "required": false,
            "description": "Page index (1-based). Default: 1."
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "required": false,
            "description": "Page size (submissions per page). Default: 50. Maximum: 100."
          },
          {
            "in": "query",
            "name": "since",
            "schema": {
              "type": "string"
            },
            "required": false,
            "description": "Include submissions with `createdAt` on or after this time. ISO 8601 (e.g. `2025-01-01T00:00:00Z`) or Unix timestamp (seconds or milliseconds)."
          },
          {
            "in": "query",
            "name": "until",
            "schema": {
              "type": "string"
            },
            "required": false,
            "description": "Include submissions with `createdAt` on or before this time. Same formats as `since`."
          }
        ],
        "responses": {
          "200": {
            "description": "List result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionListResponse"
                },
                "examples": {
                  "withItems": {
                    "summary": "One submission on this page",
                    "value": {
                      "status": "success",
                      "data": {
                        "total": 1,
                        "page": 1,
                        "pageSize": 50,
                        "totalPages": 1,
                        "items": [
                          {
                            "id": "507f1f77bcf86cd799439011",
                            "qrId": "ABC123",
                            "createdAt": "2025-06-01T10:00:00.000Z",
                            "answers": {
                              "1748000000_3": "Jane Doe",
                              "1748000000_7": [
                                "Option 1",
                                "Option 2"
                              ],
                              "1748000000_12": {
                                "fileId": "507f1f77bcf86cd799439011",
                                "fileUrl": "https://cdn.example.com/files/abc.png"
                              }
                            }
                          }
                        ]
                      },
                      "form": {
                        "title": "Contact form",
                        "fields": [
                          {
                            "key": "1748000000_3",
                            "type": "shortText",
                            "option": {
                              "label": "Name"
                            }
                          },
                          {
                            "key": "1748000000_7",
                            "type": "checkbox",
                            "option": {
                              "label": "Interests"
                            }
                          },
                          {
                            "key": "1748000000_12",
                            "type": "picture",
                            "option": {
                              "label": "Photo"
                            }
                          }
                        ]
                      }
                    }
                  },
                  "empty": {
                    "summary": "Form exists, no submissions yet",
                    "value": {
                      "status": "success",
                      "data": {
                        "total": 0,
                        "page": 1,
                        "pageSize": 50,
                        "totalPages": 0,
                        "items": []
                      },
                      "form": {
                        "title": "Contact form",
                        "fields": [
                          {
                            "key": "1748000000_3",
                            "type": "shortText",
                            "option": {
                              "label": "Name"
                            }
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid `qrId` format, unknown form, wrong account, archived form, or blocked owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid `Authorization: Bearer` API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "submissionCreatePublic",
        "tags": [
          "Submissions"
        ],
        "summary": "Create a submission",
        "description": "Create a response with `answers` map. Optional `Idempotency-Key` header. Call `submission-schema` first. Guide: [Create a Submission](https://docs.form-qr-code-generator.com/v1/index.htm#create-submission).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "qrId",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            },
            "description": "Form id"
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Optional. Same key + identical request body replays the original success response (24h TTL). Same key + different body returns HTTP **409**."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmissionCreateBody"
              },
              "examples": {
                "textFieldsOnly": {
                  "summary": "Text fields only (no upload)",
                  "value": {
                    "answers": {
                      "1748000000_3": "Jane Doe"
                    }
                  }
                },
                "submissionWithPicture": {
                  "summary": "Picture field after upload",
                  "value": {
                    "answers": {
                      "1748000000_3": "Jane Doe",
                      "1748000000_12": {
                        "fileId": "507f1f77bcf86cd799439011"
                      }
                    }
                  }
                },
                "submissionWithSignature": {
                  "summary": "Signature field (fileId only)",
                  "value": {
                    "answers": {
                      "1748000000_20": "507f1f77bcf86cd799439012"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionCreateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation, plan limit, or form missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict409"
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/forms/{qrId}/submissions/validate": {
      "post": {
        "operationId": "submissionValidate",
        "tags": [
          "Submissions"
        ],
        "summary": "Validate submission payload (dry run)",
        "description": "Dry-run validate `answers` without creating a row. Counts toward API quota. Guide: [Create a Submission](https://docs.form-qr-code-generator.com/v1/index.htm#create-submission).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "qrId",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            },
            "description": "Form id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmissionCreateBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payload is valid for this form",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionValidationSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed — see `data.fieldErrors`",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiFailedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/SubmissionValidationFailedData"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "status": "failed",
                  "message": "Submission validation failed.",
                  "code": 400,
                  "data": {
                    "valid": false,
                    "fieldErrors": {
                      "1748000000_5": {
                        "code": "invalid_option",
                        "message": "Value \"foo\" is not a valid option for this field.",
                        "type": "checkbox"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid `Authorization: Bearer` API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/forms/{qrId}/submissions/batch-delete": {
      "post": {
        "operationId": "submissionDeleteMany",
        "tags": [
          "Submissions"
        ],
        "summary": "Delete multiple submissions",
        "description": "Batch delete submissions by id (Admin only). Guide: [Manage Submissions](https://docs.form-qr-code-generator.com/v1/index.htm#manage-submissions).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmissionMultipleDeleteBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmptyDataSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Not admin, invalid body (**`qrId`** missing or **`submissionIds`** not an array), **form not found** for this account, or other validation error (`ApiFailedResponse`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid `Authorization: Bearer` API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "qrId",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            },
            "description": "Form id"
          }
        ]
      }
    },
    "/submissions/{submissionId}": {
      "get": {
        "operationId": "submissionGetById",
        "tags": [
          "Submissions"
        ],
        "summary": "Get one submission",
        "description": "Fetch one submission by id. Unknown id → **400**. Guide: [Read Submissions](https://docs.form-qr-code-generator.com/v1/index.htm#read-submissions).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "submissionId",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-fA-F0-9]{24}$"
            },
            "description": "Submission id (24-character hex submission id)"
          }
        ],
        "responses": {
          "200": {
            "description": "Submission found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionDetailResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid id format, submission not found, or not allowed to view",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid `Authorization: Bearer` API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "submissionEdit",
        "tags": [
          "Submissions"
        ],
        "summary": "Update a submission",
        "description": "Update submission `answers`. Viewer cannot edit. Guide: [Manage Submissions](https://docs.form-qr-code-generator.com/v1/index.htm#manage-submissions).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "submissionId",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Submission id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmissionEditBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmptyDataSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Not allowed or validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid `Authorization: Bearer` API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "submissionDelete",
        "tags": [
          "Submissions"
        ],
        "summary": "Delete one submission",
        "description": "Delete one submission (Admin only). Guide: [Manage Submissions](https://docs.form-qr-code-generator.com/v1/index.htm#manage-submissions).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "submissionId",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Submission identifier (24-character hex string)."
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmptyDataSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Not allowed or error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid `Authorization: Bearer` API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/team/members": {
      "get": {
        "operationId": "teamMemberList",
        "tags": [
          "Team"
        ],
        "summary": "List team members",
        "description": "List team members. Owner/Admin only. Guide: [Team API](https://docs.form-qr-code-generator.com/v1/index.htm#team-api).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamMemberListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error or owner not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/RoleForbidden403"
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "teamMemberCreate",
        "tags": [
          "Team"
        ],
        "summary": "Create team member",
        "description": "Add team member (Business+ plan, Owner/Admin only). Guide: [Team API](https://docs.form-qr-code-generator.com/v1/index.htm#team-api).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamMemberCreateBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamApiSuccessResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error, plan limit, or duplicate user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/RoleForbidden403"
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/team": {
      "patch": {
        "operationId": "teamUpdateName",
        "tags": [
          "Team"
        ],
        "summary": "Update team name",
        "description": "Rename team (requires account password). Owner/Admin only. Guide: [Team API](https://docs.form-qr-code-generator.com/v1/index.htm#team-api).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamRenameBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamApiSuccessResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation or password mismatch",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/RoleForbidden403"
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/form-templates": {
      "post": {
        "operationId": "formTemplateCreate",
        "tags": [
          "Form Templates"
        ],
        "summary": "Create a form template",
        "description": "Save private reusable layout on your account. Guide: [Form Templates API](https://docs.form-qr-code-generator.com/v1/index.htm#form-templates-api).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FormTemplateCreateBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Template created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamApiSuccessResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business rule failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "formTemplateListByCategory",
        "tags": [
          "Form Templates"
        ],
        "summary": "List public templates in a category",
        "description": "Returns public templates for `categoryId`, including templates in child categories. Response items include preview image metadata only (not full field definitions).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "name": "categoryId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Category id (24-character hex string)."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "Maximum templates to return; `0` means no limit."
          }
        ],
        "responses": {
          "200": {
            "description": "Template list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormTemplateListSuccess"
                },
                "example": {
                  "status": "success",
                  "data": [
                    {
                      "id": "507f1f77bcf86cd799439013",
                      "title": "Contact form basic",
                      "categoryName": "Business",
                      "form": {
                        "previewImage": {
                          "fileUrl": "https://cdn.example.com/templates/contact.png"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation or business rule failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/form-templates/favorites": {
      "get": {
        "operationId": "formTemplateListFavorites",
        "tags": [
          "Form Templates"
        ],
        "summary": "List favorite templates",
        "description": "Returns favorite template ids, or full list items when `data=1`.",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "name": "data",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ]
            },
            "description": "When `1`, include template metadata (same shape as list). Otherwise returns an array of template ids in `data`."
          }
        ],
        "responses": {
          "200": {
            "description": "Favorites",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormTemplateListSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business rule failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/form-templates/mine": {
      "get": {
        "operationId": "formTemplateListMine",
        "tags": [
          "Form Templates"
        ],
        "summary": "List templates created by the caller",
        "description": "Templates owned by the account tied to the API key (preview metadata per item).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Owned templates",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormTemplateListSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business rule failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/qr-design-templates": {
      "get": {
        "operationId": "listQrDesignTemplates",
        "tags": [
          "QR Design Templates"
        ],
        "summary": "List QR design presets",
        "description": "Built-in QR styling presets — copy `config` into `qrConfig`. Guide: [Built-in QR Design Presets](https://docs.form-qr-code-generator.com/v1/index.htm#qr-design-templates-api).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Preset list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QrDesignTemplateListSuccess"
                },
                "example": {
                  "status": "success",
                  "data": [
                    {
                      "id": "624d46ee76af630e61194567",
                      "previewUrl": "https://media.qrtiger.com/templates/1649231598229-250.png",
                      "config": {
                        "size": 500,
                        "colorDark": "rgb(42,45,87)",
                        "eye_outer": "eyeOuter7",
                        "eye_inner": "eyeInner7",
                        "qrData": "pattern3",
                        "backgroundColor": "rgb(255,255,255)",
                        "transparentBkg": false,
                        "eye_color": true,
                        "eye_color01": "rgb(124,130,180)",
                        "eye_color02": "rgb(61,68,127)",
                        "frame": 1,
                        "frameText": "SCAN ME",
                        "frameColor": "#3d447f"
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation or business rule failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "description": "Monthly API quota exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiRateLimitError"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/form-ai-builder/generate": {
      "post": {
        "operationId": "formAiBuilderGenerate",
        "tags": [
          "Form AI Builder"
        ],
        "summary": "Generate form draft from prompt",
        "description": "Draft form layout from natural-language prompt. Review output, then POST /forms. Guide: [AI Form Builder](https://docs.form-qr-code-generator.com/v1/index.htm#ai-form-builder-api).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FormAiBuilderGenerateRequest"
              },
              "example": {
                "prompt": "Create a simple pizza order form with size, toppings, and delivery address."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generated form draft",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormAiBuilderGenerateSuccess"
                },
                "example": {
                  "status": "success",
                  "data": {
                    "title": "Pizza order",
                    "shortText": "Place your order below.",
                    "locale": "en",
                    "fields": [
                      {
                        "type": "radio",
                        "option": {
                          "label": "Pizza size",
                          "required": true,
                          "options": [
                            {
                              "name": "Small",
                              "value": "Small",
                              "key": 1,
                              "image": null
                            },
                            {
                              "name": "Medium",
                              "value": "Medium",
                              "key": 2,
                              "image": null
                            },
                            {
                              "name": "Large",
                              "value": "Large",
                              "key": 3,
                              "image": null
                            }
                          ]
                        }
                      },
                      {
                        "type": "shortText",
                        "option": {
                          "label": "Delivery address",
                          "required": true
                        }
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or too-short prompt, or invalid AI response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "description": "Monthly API quota exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiRateLimitError"
                }
              }
            }
          },
          "500": {
            "description": "AI service or server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/form-templates/categories": {
      "get": {
        "operationId": "formTemplateCategoryList",
        "tags": [
          "Form Template Categories"
        ],
        "summary": "List template categories",
        "description": "Returns all categories. Pass `items=1` to embed up to six public templates per root category (cached).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "name": "items",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ]
            },
            "description": "When `1`, include `formTemplates` on root categories."
          }
        ],
        "responses": {
          "200": {
            "description": "Categories",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormTemplateCategoryListSuccess"
                },
                "example": {
                  "status": "success",
                  "data": [
                    {
                      "id": "507f1f77bcf86cd799439012",
                      "name": "Business"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation or business rule failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/form-templates/{templateId}": {
      "get": {
        "operationId": "formTemplateGetById",
        "tags": [
          "Form Templates"
        ],
        "summary": "Get template by id",
        "description": "Full template metadata. To create a live form: `GET .../form-create` → `POST /forms`. Guide: [Form Templates API](https://docs.form-qr-code-generator.com/v1/index.htm#form-templates-api).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "templateId",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Template id (24-character hex string from list responses)."
          }
        ],
        "responses": {
          "200": {
            "description": "Template detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormTemplateDetailSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business rule failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/form-templates/{templateId}/form-create": {
      "get": {
        "operationId": "formTemplateFormCreate",
        "tags": [
          "Form Templates"
        ],
        "summary": "Convert template to POST /forms body",
        "description": "Returns `POST /forms` body from template id. Use hex `id`, not URL slug. Guide: [Form Templates API](https://docs.form-qr-code-generator.com/v1/index.htm#form-templates-api).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "templateId",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Template id (24-character hex string from list responses)."
          }
        ],
        "responses": {
          "200": {
            "description": "Form create body derived from the template",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormTemplateFormCreateSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Invalid template id or template not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/form-templates/{templateId}/share": {
      "post": {
        "operationId": "formTemplateShare",
        "tags": [
          "Form Templates"
        ],
        "summary": "Email a template link",
        "description": "Emails a template gallery link to up to five comma-separated addresses. Provide `fromName` when the caller has no display name on the account.",
        "security": [
          {
            "Bearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FormTemplateShareBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Share email queued or sent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiSuccessEnvelope"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business rule failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "templateId",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Template id (24-character hex string from list responses)."
          }
        ]
      }
    },
    "/form-templates/{templateId}/favorite": {
      "put": {
        "operationId": "formTemplateFavoriteAdd",
        "tags": [
          "Form Templates"
        ],
        "summary": "Add template to favorites",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "name": "templateId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Template id (24-character hex string from list responses)."
          }
        ],
        "responses": {
          "200": {
            "description": "Favorite updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiSuccessWithObjectData"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business rule failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        },
        "description": "Adds a public template to your account favorites. Use template **id** from list responses."
      },
      "delete": {
        "operationId": "formTemplateFavoriteRemove",
        "tags": [
          "Form Templates"
        ],
        "summary": "Remove template from favorites",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "name": "templateId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Template id (24-character hex string from list responses)."
          }
        ],
        "responses": {
          "200": {
            "description": "Favorite updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiSuccessWithObjectData"
                }
              }
            }
          },
          "400": {
            "description": "Validation or business rule failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        },
        "description": "Removes a template from your account favorites. Use template **id** from list responses."
      }
    },
    "/forms/{qrId}/analytics": {
      "get": {
        "tags": [
          "Form analytics"
        ],
        "operationId": "getFormAnalytics",
        "summary": "Form analytics",
        "description": "`period` must be an enum (`month`, `year`, …) — not a day count. `export=1` returns CSV link. Guide: [Form Analytics](https://docs.form-qr-code-generator.com/v1/index.htm#form-analytics).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "name": "qrId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Z0-9]+$"
            },
            "description": "Form id (`qrId`); uppercase letters and digits only."
          },
          {
            "name": "submission",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ]
            },
            "description": "Filter submission-linked rows when `1`"
          },
          {
            "name": "export",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Set to `1` to return a CSV download link in `data.csvUrl` instead of JSON analytics. Uses the same period and filters."
          },
          {
            "name": "period",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "month",
              "enum": [
                "day",
                "week",
                "month",
                "months",
                "year",
                "years",
                "custom"
              ]
            },
            "description": "Aggregation period. Invalid values return HTTP **400** (`Invalid period…`). When `day`, pass `timestamp` (epoch seconds). When `custom`, also pass `endTimestamp`. Guide: [Form Analytics](https://docs.form-qr-code-generator.com/v1/index.htm#form-analytics)."
          },
          {
            "name": "tz",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "IANA timezone for bucketing scan timestamps (for example `Asia/Bangkok`). Defaults to `UTC` when omitted."
          },
          {
            "name": "timestamp",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Start of range as Unix epoch **seconds** (string). Required when `period=day`; start bound when `period=custom`."
          },
          {
            "name": "endTimestamp",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "End of range as Unix epoch **seconds** (string). Required when `period=custom`."
          }
        ],
        "responses": {
          "200": {
            "description": "JSON analytics summary, or a CSV download link when `export=1`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormAnalyticsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid **`qrId`** pattern, form not found for this account, **blocked** owner, invalid **`period`** (or missing **`timestamp`** when `period=day`, or missing **`timestamp`** / **`endTimestamp`** when `period=custom`), or other bad request (same envelope style as **`GET /forms/{qrId}`** failures).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/team/members/{memberId}": {
      "put": {
        "operationId": "teamMemberUpdate",
        "tags": [
          "Team"
        ],
        "summary": "Update team member",
        "description": "Update member name, email, role, or blocked status. Owner/Admin only. Guide: [Team API](https://docs.form-qr-code-generator.com/v1/index.htm#team-api).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "memberId",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Team member user id (from `GET /team/members`)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamMemberUpdateBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamApiSuccessResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error or member not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/RoleForbidden403"
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "teamMemberDelete",
        "tags": [
          "Team"
        ],
        "summary": "Delete team member",
        "description": "Remove team member. Owner/Admin only. Guide: [Team API](https://docs.form-qr-code-generator.com/v1/index.htm#team-api).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "memberId",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Team member user id (from `GET /team/members`)."
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamApiSuccessResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error or member not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/RoleForbidden403"
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    },
    "/team/members/{memberId}/reset-password": {
      "post": {
        "operationId": "teamMemberResetPassword",
        "tags": [
          "Team"
        ],
        "summary": "Reset member password",
        "description": "Member changes their own password (`oldPass`, `newPass`, `confirmPass`). Use that member's API key. Guide: [Team API](https://docs.form-qr-code-generator.com/v1/index.htm#team-api).",
        "security": [
          {
            "Bearer": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "memberId",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Team member user id (from `GET /team/members`)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TeamMemberResetPasswordBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Password updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamApiSuccessResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation or password mismatch",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiFailedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Undocumented path or method. Wrong qrId on a valid route usually returns **400**, not 404 — see [Error Model](https://docs.form-qr-code-generator.com/v1/index.htm#error-model).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiNotFoundError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/PlanApiQuota429"
          },
          "500": {
            "description": "Unexpected server error on a documented route (normalized JSON body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiServerError"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "submissionCreated": {
      "post": {
        "operationId": "webhookSubmissionCreated",
        "tags": [
          "Account"
        ],
        "security": [],
        "summary": "Outbound webhook: submission.created",
        "description": "TIGER FORM **POST**s this JSON to your configured account webhook URL when a new submission is saved on any form you own. Configure via **`GET/PUT /account/webhook`**. Verify with header **`X-TigerForm-Signature`** (`sha256=` HMAC of the raw body using your webhook `secret`). Respond with HTTP **2xx** within 10 seconds. Guide: [Webhooks](https://docs.form-qr-code-generator.com/v1/index.htm#webhook-api).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookSubmissionCreatedEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Your endpoint acknowledged the event (any **2xx** status is treated as success)."
          }
        }
      }
    }
  }
}
