{"openapi":"3.1.0","info":{"title":"QuizGen API","version":"1","summary":"Create live, hosted quizzes and forms by POSTing JSON, then read the responses back.","description":"The QuizGen REST API is a headless quiz/form service. Create a quiz with one call and it is immediately live at a short URL like `https://quizgen.dev/q/x7km2p` — mobile-friendly, autosaving, no account needed for respondents. No SDK required: plain HTTPS + JSON.\n\n**Sandbox (no key):** `POST /quizzes` with no `Authorization` header creates a sandbox quiz — live instantly, expires in 72 hours, caps at 10 responses, can't be updated or read back. The response includes a `claim_url` to keep it.\n\n**Authorized:** MCP clients connect `https://quizgen.dev/mcp` and authorize in the browser (OAuth); the issued access token rides the same `Authorization: Bearer` header. Server-to-server integrations can instead issue an API key (`qg_live_...`) from the [dashboard](https://quizgen.dev/dashboard) and send it as a bearer token.\n\nThe full agent-oriented reference (conventions, question-type guidance, worked examples) is at [/llms.txt](https://quizgen.dev/llms.txt). The raw quiz JSON Schema is at [/schema/v1.json](https://quizgen.dev/schema/v1.json).","contact":{"name":"QuizGen support","email":"sales@quizgen.dev"}},"servers":[{"url":"https://quizgen.dev/api/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Account","description":"Key check and plan headroom."},{"name":"Quizzes","description":"Create, read, replace, and manage quizzes."},{"name":"Responses","description":"Read the answers your quizzes collect."},{"name":"Delivery","description":"Email a quiz and track per-recipient progress (paid plans)."},{"name":"Webhooks","description":"Get POSTed on every completed response."}],"paths":{"/me":{"get":{"tags":["Account"],"operationId":"getMe","summary":"Auth check — call this first","description":"Confirms authorization works and reports the account email, plan limits, and current usage so you know the headroom before creating anything.","responses":{"200":{"description":"Account plan, limits, and usage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/quizzes":{"get":{"tags":["Quizzes"],"operationId":"listQuizzes","summary":"List quizzes","description":"Lists the account's quizzes (id, slug, title, status, response_count). Optionally paginated; JSON includes `total`, `has_more`, and `next_offset`.","parameters":[{"$ref":"#/components/parameters/PageLimit"},{"$ref":"#/components/parameters/PageOffset"}],"responses":{"200":{"description":"The account's quizzes.","content":{"application/json":{"schema":{"type":"object","properties":{"quizzes":{"type":"array","items":{"$ref":"#/components/schemas/QuizListItem"}},"total":{"type":"integer","description":"Total quizzes on the account."},"count":{"type":"integer","description":"Items in this page."},"offset":{"type":"integer"},"has_more":{"type":"boolean"},"next_offset":{"type":"integer","description":"Offset for the next page. Present only when `has_more` is true."}},"required":["quizzes","total","count","offset","has_more"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Quizzes"],"operationId":"createQuiz","summary":"Create a quiz","description":"Creates a quiz from a JSON definition. The quiz is live immediately.\n\nOmit the `Authorization` header entirely to create a **sandbox** quiz (no account needed): it expires in 72 hours, caps at 10 responses, and returns a `claim_url` to keep it. A wrong or revoked key still returns 401 — sandbox only triggers when no `Authorization` header is present.","security":[{"bearerAuth":[]},{}],"parameters":[{"name":"X-Creator-Email","in":"header","required":false,"description":"Sandbox only. Email the claim link to this address immediately, plus one reminder before expiry. Never send an address the user didn't give you (422 `invalid_creator_email`).","schema":{"type":"string","format":"email"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Safely retry a create without duplicating the quiz.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuizDefinition"}}}},"responses":{"201":{"description":"Quiz created and live.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedQuiz"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimit"},"422":{"$ref":"#/components/responses/InvalidQuiz"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/quizzes/{id}":{"parameters":[{"$ref":"#/components/parameters/QuizId"}],"get":{"tags":["Quizzes"],"operationId":"getQuiz","summary":"Fetch one quiz","description":"Fetches one quiz including its full `definition`.","responses":{"200":{"description":"The quiz and its definition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuizDetail"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Quizzes"],"operationId":"replaceQuiz","summary":"Replace the definition","description":"Replaces the definition. Bumps `definition_version`; existing responses keep the version they answered.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuizDefinition"}}}},"responses":{"200":{"description":"Definition replaced.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedQuiz"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimit"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/InvalidQuiz"}}},"patch":{"tags":["Quizzes"],"operationId":"setQuizStatus","summary":"Close or reopen","description":"Closes or reopens the quiz.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["live","closed"]}},"required":["status"]}}}},"responses":{"200":{"description":"Status updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResult"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Quizzes"],"operationId":"deleteQuiz","summary":"Delete a quiz","description":"Soft-deletes the quiz. The link stops working.","responses":{"200":{"description":"Quiz deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResult"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/quizzes/{id}/responses":{"parameters":[{"$ref":"#/components/parameters/QuizId"}],"get":{"tags":["Responses"],"operationId":"listResponses","summary":"List responses","description":"Lists responses. `answers` is a flat `question_id → value` map (`multi_choice` → array of values). `complete: false` rows are partial autosaves — useful for drop-off analysis.","parameters":[{"name":"complete","in":"query","required":false,"description":"Filter to finished responses only.","schema":{"type":"boolean"}},{"name":"format","in":"query","required":false,"description":"Set to `csv` (or send `Accept: text/csv`) to download a CSV instead of JSON.","schema":{"type":"string","enum":["json","csv"]}},{"$ref":"#/components/parameters/PageLimit"},{"$ref":"#/components/parameters/PageOffset"}],"responses":{"200":{"description":"The quiz's responses.","content":{"application/json":{"schema":{"type":"object","properties":{"responses":{"type":"array","items":{"$ref":"#/components/schemas/QuizResponse"}},"total":{"type":"integer","description":"Total responses for the quiz (after the complete filter)."},"count":{"type":"integer","description":"Items in this page."},"offset":{"type":"integer"},"has_more":{"type":"boolean"},"next_offset":{"type":"integer","description":"Offset for the next page. Present only when `has_more` is true."}},"required":["responses","total","count","offset","has_more"]}},"text/csv":{"schema":{"type":"string"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/quizzes/{id}/responses/{rid}":{"parameters":[{"$ref":"#/components/parameters/QuizId"},{"name":"rid","in":"path","required":true,"description":"Response id (e.g. from a webhook payload).","schema":{"type":"string"}}],"get":{"tags":["Responses"],"operationId":"getResponse","summary":"Fetch one response","description":"Fetches one response by id.","responses":{"200":{"description":"The response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuizResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/quizzes/{id}/stats":{"parameters":[{"$ref":"#/components/parameters/QuizId"}],"get":{"tags":["Responses"],"operationId":"getStats","summary":"Quiz stats","description":"Funnel stats — use this to answer \"how's my quiz doing?\".","responses":{"200":{"description":"Views, funnel, and outcome distribution.","content":{"application/json":{"schema":{"type":"object","properties":{"views":{"type":"integer"},"started":{"type":"integer"},"finished":{"type":"integer"},"completion_rate":{"type":["number","null"],"description":"null when there are no responses yet."},"outcomes":{"type":"object","additionalProperties":{"type":"integer"},"description":"Present when the quiz uses `outcomes`: bucket key → count."}},"required":["views","started","finished","completion_rate"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/quizzes/{id}/webhook":{"parameters":[{"$ref":"#/components/parameters/QuizId"}],"post":{"tags":["Webhooks"],"operationId":"setWebhook","summary":"Set or clear the webhook","description":"Sets a webhook that POSTs on every completed response, or clears it with `{\"url\": null}`. If a `secret` is set, each delivery carries `X-QuizGen-Signature`: the HMAC-SHA256 hex of the raw body.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":["string","null"],"format":"uri","description":"Endpoint to POST to, or null to clear."},"secret":{"type":"string","minLength":8,"description":"Signs deliveries (HMAC-SHA256)."}},"required":["url"]}}}},"responses":{"200":{"description":"Webhook set or cleared.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResult"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/quizzes/{id}/send":{"parameters":[{"$ref":"#/components/parameters/QuizId"}],"post":{"tags":["Delivery"],"operationId":"sendQuiz","summary":"Email the quiz","description":"Emails the quiz to a list of people (paid plans; free/sandbox get 402). Max 100 recipients per call; duplicates are dropped. Each recipient gets a unique tracked link. This delivers real email immediately — confirm the list with the user first.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channel":{"type":"string","enum":["email"],"default":"email","description":"Optional, defaults to `email`. `sms` returns 400 `not_yet_available`."},"recipients":{"type":"array","maxItems":100,"items":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string"}},"required":["email"]}},"message":{"type":"string","description":"Optional note shown above the button."}},"required":["recipients"]}}}},"responses":{"200":{"description":"Send queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResult"}}}},"400":{"description":"`not_yet_available` — `channel: \"sms\"` isn't live yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanLimit"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"`quiz_closed` — reopen the quiz before sending.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`invalid_recipients` or `invalid_channel`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"No email could be delivered (every recipient failed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/quizzes/{id}/sends":{"parameters":[{"$ref":"#/components/parameters/QuizId"}],"get":{"tags":["Delivery"],"operationId":"listSends","summary":"Delivery status","description":"Per-recipient delivery status: `sent` → `started` → `completed` (plus `failed`, `opted_out`, reminder counts).","responses":{"200":{"description":"Per-recipient status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/quizzes/{id}/follow_up":{"parameters":[{"$ref":"#/components/parameters/QuizId"}],"put":{"tags":["Delivery"],"operationId":"setFollowUp","summary":"Auto-reminder rule","description":"Auto-reminds recipients who haven't finished (hourly cron). Reminders stop on completion, unsubscribe, or `max_reminders`. Send `null` to clear the rule.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"after_hours":{"type":"integer","minimum":1,"maximum":720,"default":48},"max_reminders":{"type":"integer","minimum":1,"maximum":5,"default":2},"message":{"type":"string"}}},{"type":"null"}]}}}},"responses":{"200":{"description":"Rule set or cleared.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResult"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key issued from the dashboard (`qg_live_...`) or a QuizGen OAuth access token (issued when an MCP client authorizes via https://quizgen.dev/mcp)."}},"parameters":{"QuizId":{"name":"id","in":"path","required":true,"description":"Quiz id (e.g. `qz_1f6b...`) or slug (e.g. `x7km2p`).","schema":{"type":"string"}},"PageLimit":{"name":"limit","in":"query","required":false,"description":"Max items to return (1–500). Omit both `limit` and `offset` for the full, unpaginated list.","schema":{"type":"integer","minimum":1,"maximum":500}},"PageOffset":{"name":"offset","in":"query","required":false,"description":"Skip this many items; use `next_offset` from the previous page.","schema":{"type":"integer","minimum":0}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such quiz (or not yours).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PlanLimit":{"description":"The account is at a plan limit (e.g. live-quiz cap, or a paid-only feature on a free plan). Close/delete a quiz, drop the gated fields, or upgrade.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InvalidQuiz":{"description":"The quiz definition failed validation. Fix exactly the fields in `validation_errors` and retry — do not resend an unchanged body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"invalid_quiz","message":"Quiz definition failed validation.","validation_errors":["sections.0.questions.0.type: unknown question type \"dropdown\" — did you mean \"choice\"?"],"hint":"Fix the listed fields and retry."}}}}},"RateLimited":{"description":"Rate limit hit (60 writes/min, 300 reads/min per key; sandbox creates 10/hr/IP). Honor the `Retry-After` header.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"QuizDefinition":{"type":"object","properties":{"schema_version":{"type":"number","const":1},"kind":{"type":"string","enum":["quiz","survey","form","email_capture","registration"]},"title":{"type":"string","minLength":1,"maxLength":300},"description":{"type":"string","maxLength":2000},"settings":{"type":"object","properties":{"collect_respondent":{"type":"string","enum":["none","email_optional","email_required"]},"autosave":{"type":"boolean"},"show_progress":{"type":"boolean"},"one_question_per_page":{"type":"boolean"},"show_branding":{"type":"boolean"},"close_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"max_responses":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}]},"completion":{"type":"object","properties":{"message":{"type":"string","maxLength":2000},"redirect_url":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]}},"additionalProperties":false}},"additionalProperties":false},"cover":{"type":"object","properties":{"title":{"type":"string","maxLength":300},"subtitle":{"type":"string","maxLength":1000},"button_label":{"type":"string","maxLength":60},"image_url":{"type":"string","format":"uri"}},"additionalProperties":false},"theme":{"type":"object","properties":{"preset":{"type":"string","enum":["warm","midnight","forest","corporate","playful","mono"]},"accent":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"mode":{"type":"string","enum":["light","dark","auto"]},"background":{"anyOf":[{"type":"string"},{"type":"null"}]},"font":{"anyOf":[{"type":"string"},{"type":"null"}]},"logo_url":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]}},"additionalProperties":false},"hidden_fields":{"maxItems":10,"type":"array","items":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"}},"sections":{"minItems":1,"maxItems":30,"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"title":{"type":"string","maxLength":300},"blurb":{"type":"string","maxLength":1000},"one_per_page":{"type":"boolean"},"questions":{"minItems":1,"maxItems":50,"type":"array","items":{"oneOf":[{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"short_text"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"placeholder":{"type":"string","maxLength":200}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"long_text"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"rows":{"type":"integer","minimum":2,"maximum":20},"examples":{"maxItems":8,"type":"array","items":{"type":"string","maxLength":300}}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"choice"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"options":{"minItems":2,"maxItems":20,"type":"array","items":{"type":"object","properties":{"value":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"label":{"type":"string","minLength":1,"maxLength":200},"detail":{"type":"string","maxLength":500},"image_url":{"type":"string","format":"uri"}},"required":["value","label"],"additionalProperties":false}},"follow_up":{"type":"string","maxLength":500}},"required":["id","type","prompt","options"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"multi_choice"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"options":{"minItems":2,"maxItems":20,"type":"array","items":{"type":"object","properties":{"value":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"label":{"type":"string","minLength":1,"maxLength":200},"detail":{"type":"string","maxLength":500},"image_url":{"type":"string","format":"uri"}},"required":["value","label"],"additionalProperties":false}},"min":{"type":"integer","minimum":0,"maximum":9007199254740991},"max":{"type":"integer","minimum":1,"maximum":9007199254740991}},"required":["id","type","prompt","options"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"scale"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"min":{"type":"integer","minimum":0,"maximum":1},"max":{"type":"integer","minimum":2,"maximum":10},"min_label":{"type":"string","maxLength":100},"max_label":{"type":"string","maxLength":100}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"email"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"placeholder":{"type":"string","maxLength":200}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"number"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"min":{"type":"number"},"max":{"type":"number"},"unit":{"type":"string","maxLength":30}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"date"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"min":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"max":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"time"},"prompt":{"type":"string","minLength":1,"maxLength":1000}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"phone"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"placeholder":{"type":"string","maxLength":200}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"url"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"placeholder":{"type":"string","maxLength":200}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"yes_no"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"yes_label":{"type":"string","maxLength":100},"no_label":{"type":"string","maxLength":100}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"consent"},"prompt":{"type":"string","minLength":1,"maxLength":2000}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"rating"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"max":{"type":"integer","minimum":2,"maximum":10}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"slider"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"min":{"type":"number"},"max":{"type":"number"},"step":{"type":"number","exclusiveMinimum":0},"min_label":{"type":"string","maxLength":100},"max_label":{"type":"string","maxLength":100},"unit":{"type":"string","maxLength":30}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"payment"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"amount_cents":{"type":"integer","minimum":50,"maximum":1000000},"price_options":{"minItems":2,"maxItems":10,"type":"array","items":{"type":"object","properties":{"value":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"label":{"type":"string","minLength":1,"maxLength":200},"amount_cents":{"type":"integer","minimum":50,"maximum":1000000},"detail":{"type":"string","maxLength":500}},"required":["value","label","amount_cents"],"additionalProperties":false}},"currency":{"type":"string","pattern":"^[a-z]{3}$"},"button_label":{"type":"string","maxLength":60}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"required":{"type":"boolean"},"help":{"type":"string","maxLength":1000},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"file_upload"},"prompt":{"type":"string","minLength":1,"maxLength":1000},"max_files":{"type":"integer","minimum":1,"maximum":5},"accept":{"minItems":1,"type":"array","items":{"type":"string","enum":["image","pdf","document","spreadsheet"]}}},"required":["id","type","prompt"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"show_if":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"op":{"type":"string","enum":["eq","neq","in","gte","lte","answered"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"array","items":{"type":"string"}}]}},"required":["question","op"],"additionalProperties":false},"type":{"type":"string","const":"statement"},"title":{"type":"string","minLength":1,"maxLength":300},"body":{"minItems":1,"maxItems":10,"type":"array","items":{"type":"string","maxLength":2000}}},"required":["id","type","title","body"],"additionalProperties":false}]}}},"required":["key","questions"],"additionalProperties":false}},"outcomes":{"anyOf":[{"type":"object","properties":{"method":{"type":"string","const":"points"},"points":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}}},"buckets":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"min":{"type":"number"},"max":{"type":"number"},"title":{"type":"string","minLength":1,"maxLength":300},"body":{"type":"string","maxLength":2000},"redirect_url":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]}},"required":["key","title"],"additionalProperties":false}}},"required":["method","points","buckets"],"additionalProperties":false},{"type":"null"}]}},"required":["schema_version","title","sections"],"additionalProperties":false,"description":"A quiz/form definition (`schema_version` 1). Generated from the same validator the API enforces; the canonical JSON Schema is also at https://quizgen.dev/schema/v1.json."},"Account":{"type":"object","properties":{"email":{"type":["string","null"],"description":"The account's email."},"plan":{"type":"string","example":"free"},"limits":{"type":"object","properties":{"live_quizzes":{"type":["integer","null"],"description":"null = unlimited."},"responses_per_quiz_per_month":{"type":["integer","null"]},"requests_per_minute":{"type":"object","properties":{"writes":{"type":"integer"},"reads":{"type":"integer"}}}}},"usage":{"type":"object","properties":{"live_quizzes":{"type":"integer"}}}},"required":["plan","limits","usage"]},"CreatedQuiz":{"type":"object","properties":{"id":{"type":"string","example":"qz_1f6b..."},"slug":{"type":"string","example":"x7km2p"},"url":{"type":"string","format":"uri","example":"https://quizgen.dev/q/x7km2p"},"status":{"type":"string","example":"live"},"title":{"type":"string"},"definition_version":{"type":"integer","example":1},"response_count":{"type":"integer","example":0},"sandbox":{"type":"boolean","description":"True when created without a key."},"claim_url":{"type":"string","format":"uri","description":"Sandbox only — the secret link to sign up free and keep the quiz. Give it to your user."}},"required":["id","slug","url","status"]},"QuizListItem":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"url":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"string","enum":["live","closed"]},"response_count":{"type":"integer"},"definition_version":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"QuizDetail":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"status":{"type":"string"},"definition_version":{"type":"integer"},"response_count":{"type":"integer"},"definition":{"$ref":"#/components/schemas/QuizDefinition"}}},"QuizResponse":{"type":"object","properties":{"id":{"type":"string","example":"rsp_..."},"quiz_id":{"type":"string","example":"qz_..."},"definition_version":{"type":"integer"},"answers":{"type":"object","additionalProperties":true,"description":"Flat question_id → value map (multi_choice → array of values)."},"outcome":{"type":["string","null"],"description":"Matched bucket key, if the quiz uses outcomes."},"score":{"type":["number","null"]},"respondent_email":{"type":["string","null"]},"complete":{"type":"boolean"},"paid":{"type":"boolean","description":"True once the response's payment succeeded."},"payment_intent":{"type":["string","null"],"description":"Stripe PaymentIntent id, if the quiz takes payment."},"started_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"},"meta":{"type":"object","additionalProperties":true}}},"OperationResult":{"type":"object","description":"Successful mutation result. Fields vary by operation and are documented on the endpoint.","additionalProperties":true},"SendList":{"type":"object","properties":{"sends":{"type":"array","items":{"type":"object","additionalProperties":true}},"count":{"type":"integer"}},"required":["sends"],"additionalProperties":true},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_quiz","unauthorized","not_found","invalid_json","rate_limited","plan_limit","quiz_closed","quiz_full","payments_not_ready","invalid_creator_email","invalid_status","invalid_webhook","invalid_recipients","invalid_channel","invalid_follow_up","not_yet_available"]},"message":{"type":"string"},"validation_errors":{"type":"array","items":{"type":"string"}},"hint":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}