{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"QuizOut API","version":"1.1","description":"Locked synchronous and stateless v1 contract for the QuizOut WordPress plugin and third-party integrations. The platform returns generated quizzes inline and stores no article or quiz resource."},"servers":[{"url":"https://api.quizout.io/v1"}],"externalDocs":{"description":"Human-readable QuizOut API documentation","url":"https://quizout.io/docs"},"tags":[{"name":"Sites","description":"Provision, connect, inspect, and claim WordPress sites."},{"name":"Quiz generation","description":"Generate a single-select quiz synchronously without creating a stored quiz resource."},{"name":"Usage","description":"Read the current post allowance and attribution entitlement."}],"x-quizout-docs":{"machine_spec_url":"https://api.quizout.io/v1/openapi.json","overview":["QuizOut is synchronous: POST /quizzes returns the complete quiz in the same response. There is no polling endpoint or generation webhook.","QuizOut is stateless for content: article input and generated quiz output are not durable product records. The WordPress plugin stores and renders the returned quiz.","The only transient generation record is an encrypted successful idempotency response plus a request digest in Solid Cache for at most 24 hours."],"authentication":{"description":"Pass a per-site key as Authorization: Bearer <site_api_key>. Site keys are separate from Devise console sessions and are shown in plaintext only once when issued.","live_key":"qo_live_ keys use the production generation path. A post's first successful quiz consumes quota; later successful regenerations do not consume another post unit.","test_key":"qo_test_ keys use a deterministic provider-free generator. They never create usage-ledger entries, consume monthly quota or prepaid credits, or count successful regenerations.","sandbox_site":"A sandbox site is a separate URL classification for localhost, private, .localhost, .test, .local, or staging environments. Site environment and key mode are independent: a live key on a sandbox site still uses real generation and its sandbox allowance; a test key is provider-free on either site environment.","test_key_command":"export QUIZOUT_API_KEY='qo_test_REPLACE_WITH_YOUR_KEY'"},"test_mode":{"default_format":"comprehension","honours":["context.format_hint","context.question_count","post.locale","the site's attribution entitlement"],"description":"Test responses use generic deterministic integration content and never echo the submitted title, article body, or audience. Validation, idempotency, request throttles, key-sharing protection, and last-used tracking still apply. usage.counted is always false and the remaining usage fields are an unchanged snapshot of the site."},"rate_limits":[{"name":"Authenticated API key","applies_to":"Authenticated endpoints except POST /quizzes","limit":"120 requests per key","window":"1 minute"},{"name":"Authenticated source IP","applies_to":"Authenticated endpoints except POST /quizzes","limit":"300 requests per IP","window":"1 minute"},{"name":"Quiz generation key","applies_to":"POST /quizzes, including qo_test_ keys","limit":"10 requests per key","window":"1 minute"},{"name":"Quiz generation source IP","applies_to":"POST /quizzes, including qo_test_ keys","limit":"30 requests per IP","window":"1 minute"},{"name":"Provisioning attempts","applies_to":"POST /sites","limit":"10 requests per IP","window":"1 hour"},{"name":"Distinct verified live sites","applies_to":"POST /sites","limit":"20 sites per IP","window":"UTC day"},{"name":"Distinct sandbox sites","applies_to":"POST /sites","limit":"5 sites per IP","window":"UTC day"}],"guards":[{"name":"Concurrent regeneration","limit":"One in flight per site and post","response":"429 rate_limited; reason regeneration_in_progress; Retry-After: 5"},{"name":"Free successful regenerations","limit":"3 per site and post for its lifetime","response":"429 rate_limited; reason regeneration_limit_reached; Reset: 0"},{"name":"Paid or credited successful regenerations","limit":"10 per site and post for its lifetime","response":"429 rate_limited; reason regeneration_limit_reached; Reset: 0"},{"name":"API key source sharing","limit":"10 distinct source fingerprints","response":"Rolling 24-hour window; 429 rate_limited with reason api_key_ip_limit"}]},"security":[{"siteApiKey":[]}],"paths":{"/sites":{"post":{"operationId":"provisionSite","tags":["Sites"],"summary":"Auto-provision an anonymous free site","description":"Public HTTPS sites prove control through a redirect-free POST of { proof } to {home_url}/wp-json/quizout/v1/provisioning-proof. The callback must return JSON containing exactly { verified: true, proof: <same>, home_url: <canonical URL> }. Unreachable localhost, private-address, .localhost, .test, and .local sites are provisioned as tightly limited sandboxes without an outbound callback; a public hostname with a staging label is sandboxed but still verified. Anonymous retries reuse the Site and site token while replacing the prior bootstrap key. Provisioning is limited to 10 attempts per IP/hour and 20 distinct verified live or 5 distinct sandbox sites per IP/UTC day.","security":[],"parameters":[{"$ref":"#/components/parameters/RequestId"}],"requestBody":{"required":true,"description":"Maximum serialized JSON body size: 16384 bytes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisionSiteRequest"},"example":{"home_url":"https://blog.example.com","wp_version":"6.8","timezone":"Europe/London","proof":"proof_abc123"}}}},"responses":{"201":{"$ref":"#/components/responses/SiteProvisioned"},"422":{"$ref":"#/components/responses/InvalidRequest"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/quizzes":{"post":{"operationId":"generateQuiz","tags":["Quiz generation"],"summary":"Generate a quiz synchronously","description":"Validates the article and returns the complete quiz inline; no quiz resource is stored. Limited to 10 requests per API key/minute and 30 requests per IP/minute. With a qo_live_ key, a site/post receives 3 lifetime successful regenerations on Free or 10 on Growth, Pro, or while active prepaid credits remain. With a qo_test_ key, generation is deterministic and provider-free, usage.counted is false, quota and regeneration allowances are untouched, and the normal validation, idempotency, and temporal limits still apply.","parameters":[{"$ref":"#/components/parameters/RequestId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"description":"Maximum serialized JSON body size: 131072 bytes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateQuizRequest"},"example":{"post":{"external_id":"wp_1024","url":"https://blog.example.com/sunset-glam","title":"Sunset Glam Makeup Look","content":"Full article text or HTML","published_at":"2026-07-20T17:16:31Z","locale":"en"},"context":{"format_hint":null,"question_count":4,"audience":"beauty readers","allow_scorecard":true}}}}},"responses":{"200":{"$ref":"#/components/responses/QuizGenerated"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/InvalidRequest"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/GenerationFailed"}}}},"/usage":{"get":{"operationId":"getUsage","tags":["Usage"],"summary":"Get current site usage and attribution entitlement","description":"Returns the allowance for the authenticated site's live or sandbox environment. Key mode does not create a separate usage pool; qo_test_ quiz requests leave these values unchanged.","parameters":[{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"$ref":"#/components/responses/UsageReturned"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/site":{"get":{"operationId":"getSite","tags":["Sites"],"summary":"Get the site profile, plan, and usage","description":"Returns the authenticated site profile and allowance. The current deployment may return the documented transitional 501 response until this operation ships.","parameters":[{"$ref":"#/components/parameters/RequestId"}],"responses":{"200":{"$ref":"#/components/responses/SiteReturned"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"501":{"$ref":"#/components/responses/NotImplemented"}}}},"/site/connect":{"post":{"operationId":"connectSite","tags":["Sites"],"summary":"Verify an API key and register site metadata","description":"Authenticates only with the pasted site Bearer key, refreshes WordPress metadata and canonical URL/environment for that same Site, and preserves any console-defined name and existing keys. URL moves are allowed unless the canonical URL belongs to another Site; current Free-plan usage is returned for the site's live or sandbox pool.","parameters":[{"$ref":"#/components/parameters/RequestId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectSiteRequest"},"example":{"home_url":"https://blog.example.com","wp_version":"6.8","timezone":"Africa/Lagos"}}}},"responses":{"200":{"$ref":"#/components/responses/SiteReturned"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/InvalidRequest"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/site/claim":{"post":{"operationId":"initiateSiteClaim","tags":["Sites"],"summary":"Initiate a site claim by email magic link","description":"Creates a 24-hour pending claim and emails a scanner-safe console link. This API call never authenticates a human or moves the Site; the console confirmation POST completes account creation or merge.","parameters":[{"$ref":"#/components/parameters/RequestId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimSiteRequest"},"example":{"email":"owner@example.com"}}}},"responses":{"202":{"$ref":"#/components/responses/ClaimInitiated"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/InvalidRequest"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}}},"components":{"securitySchemes":{"siteApiKey":{"type":"http","scheme":"bearer","bearerFormat":"qo_live_... or qo_test_...","description":"Per-site API key, separate from Devise console authentication. qo_live_ uses production generation and metering. qo_test_ uses deterministic provider-free quiz generation and never consumes quota."}},"parameters":{"RequestId":{"name":"X-Request-Id","in":"header","required":false,"description":"Optional caller correlation ID; echoed in the response.","schema":{"type":"string","maxLength":255}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"description":"UUID scoped to this site credential. A successful response is replayable for 24 hours.","schema":{"type":"string","format":"uuid"}}},"headers":{"RequestId":{"description":"Caller-supplied correlation ID, or a server-generated one.","schema":{"type":"string"}},"RateLimitLimit":{"description":"Limit for the currently binding request, abuse, or regeneration guard. Zero means that no limit is enforced for this operation.","schema":{"type":"integer","minimum":0,"example":0}},"RateLimitRemaining":{"description":"Capacity remaining for the binding guard. Zero is also the no-enforcement sentinel when limit is zero.","schema":{"type":"integer","minimum":0,"example":0}},"RateLimitReset":{"description":"Unix reset timestamp. Zero means either no enforced limit when Limit is zero, or no automatic reset for the lifetime regeneration cap when Limit is nonzero.","schema":{"type":"integer","minimum":0,"example":0}},"SpecVersion":{"description":"QuizOut response contract version.","schema":{"type":"string","const":"1.1"}},"RetryAfter":{"description":"Seconds until a rate-limited request should be retried.","schema":{"type":"integer","minimum":1}}},"schemas":{"ErrorEnvelope":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","details"],"properties":{"code":{"type":"string","enum":["unauthorized","forbidden","invalid_request","quota_exceeded","rate_limited","generation_failed","server_error","not_implemented"]},"message":{"type":"string","minLength":1},"details":{"type":"object"}},"additionalProperties":false}},"additionalProperties":false},"QuotaUsage":{"type":"object","required":["quota","used","remaining","plan_quota","plan_used","pack_remaining","period_end"],"properties":{"quota":{"type":"integer","minimum":0},"used":{"type":"integer","minimum":0},"remaining":{"type":"integer","minimum":0},"plan_quota":{"type":"integer","minimum":0},"plan_used":{"type":"integer","minimum":0},"pack_remaining":{"type":"integer","minimum":0},"period_end":{"type":"string","format":"date-time"}},"additionalProperties":false},"Usage":{"type":"object","required":["plan","quota","used","remaining","plan_quota","plan_used","pack_remaining","period_end"],"properties":{"plan":{"type":"string","enum":["free","growth","pro"]},"quota":{"type":"integer","minimum":0},"used":{"type":"integer","minimum":0},"remaining":{"type":"integer","minimum":0},"plan_quota":{"type":"integer","minimum":0},"plan_used":{"type":"integer","minimum":0},"pack_remaining":{"type":"integer","minimum":0},"period_end":{"type":"string","format":"date-time"}},"additionalProperties":false},"GenerationUsage":{"type":"object","required":["plan","quota","used","remaining","plan_quota","plan_used","pack_remaining","period_end","counted"],"properties":{"plan":{"type":"string","enum":["free","growth","pro"]},"quota":{"type":"integer","minimum":0},"used":{"type":"integer","minimum":0},"remaining":{"type":"integer","minimum":0},"plan_quota":{"type":"integer","minimum":0},"plan_used":{"type":"integer","minimum":0},"pack_remaining":{"type":"integer","minimum":0},"period_end":{"type":"string","format":"date-time"},"counted":{"type":"boolean"}},"additionalProperties":false},"Attribution":{"type":"object","required":["powered_by","url"],"properties":{"powered_by":{"type":"boolean"},"url":{"type":"string","format":"uri"}},"additionalProperties":false},"QuizMeta":{"type":"object","required":["spec_version","generated_at"],"properties":{"spec_version":{"type":"string","const":"1.0"},"generated_at":{"type":"string","format":"date-time"}},"additionalProperties":false},"QuizBase":{"type":"object","required":["generation_id","format","locale","attribution","meta"],"properties":{"generation_id":{"type":"string","minLength":1},"format":{"type":"string","minLength":1},"locale":{"type":"string","minLength":2},"attribution":{"$ref":"#/components/schemas/Attribution"},"meta":{"$ref":"#/components/schemas/QuizMeta"}}},"QuestionBase":{"type":"object","required":["position","prompt","answer_type","explanation"],"properties":{"position":{"type":"integer","minimum":1},"prompt":{"type":"string","minLength":1},"answer_type":{"type":"string","const":"single_select"},"explanation":{"type":"string","minLength":1}}},"GradedOption":{"type":"object","required":["position","text","correct","points","outcome_key"],"properties":{"position":{"type":"integer","minimum":1},"text":{"type":"string","minLength":1},"correct":{"type":"boolean"},"points":{"type":"null"},"outcome_key":{"type":"null"}},"additionalProperties":false},"WeightedOption":{"type":"object","required":["position","text","correct","points","outcome_key"],"properties":{"position":{"type":"integer","minimum":1},"text":{"type":"string","minLength":1},"correct":{"type":"null"},"points":{"type":"integer","minimum":0},"outcome_key":{"type":"null"}},"additionalProperties":false},"RoutedOption":{"type":"object","required":["position","text","correct","points","outcome_key"],"properties":{"position":{"type":"integer","minimum":1},"text":{"type":"string","minLength":1},"correct":{"type":"null"},"points":{"type":"null"},"outcome_key":{"type":"string","minLength":1}},"additionalProperties":false},"GradedQuestion":{"allOf":[{"$ref":"#/components/schemas/QuestionBase"},{"type":"object","required":["options"],"properties":{"options":{"type":"array","minItems":2,"items":{"$ref":"#/components/schemas/GradedOption"}}}}],"unevaluatedProperties":false},"WeightedQuestion":{"allOf":[{"$ref":"#/components/schemas/QuestionBase"},{"type":"object","required":["options"],"properties":{"options":{"type":"array","minItems":2,"items":{"$ref":"#/components/schemas/WeightedOption"}}}}],"unevaluatedProperties":false},"RoutedQuestion":{"allOf":[{"$ref":"#/components/schemas/QuestionBase"},{"type":"object","required":["options"],"properties":{"options":{"type":"array","minItems":2,"items":{"$ref":"#/components/schemas/RoutedOption"}}}}],"unevaluatedProperties":false},"Band":{"type":"object","required":["key","min","max","label","message"],"properties":{"key":{"type":"string","minLength":1},"min":{"type":"integer","minimum":0},"max":{"type":"integer","minimum":0},"label":{"type":"string","minLength":1},"message":{"type":"string","minLength":1}},"additionalProperties":false},"Outcome":{"type":"object","required":["key","label","message"],"properties":{"key":{"type":"string","minLength":1},"label":{"type":"string","minLength":1},"message":{"type":"string","minLength":1}},"additionalProperties":false},"GradedResult":{"type":"object","required":["kind","max_score","bands","outcomes"],"properties":{"kind":{"type":"string","const":"graded"},"max_score":{"type":"null"},"bands":{"type":"null"},"outcomes":{"type":"null"}},"additionalProperties":false},"WeightedResult":{"type":"object","required":["kind","max_score","bands","outcomes"],"properties":{"kind":{"type":"string","const":"weighted"},"max_score":{"type":"integer","minimum":0},"bands":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/Band"}},"outcomes":{"type":"null"}},"additionalProperties":false},"RoutedResult":{"type":"object","required":["kind","max_score","bands","outcomes"],"properties":{"kind":{"type":"string","const":"routed"},"max_score":{"type":"null"},"bands":{"type":"null"},"outcomes":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/Outcome"}}},"additionalProperties":false},"GradedQuiz":{"allOf":[{"$ref":"#/components/schemas/QuizBase"},{"type":"object","required":["scoring_kind","questions","result"],"properties":{"scoring_kind":{"type":"string","const":"graded"},"questions":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/GradedQuestion"}},"result":{"$ref":"#/components/schemas/GradedResult"}}}],"unevaluatedProperties":false},"WeightedQuiz":{"allOf":[{"$ref":"#/components/schemas/QuizBase"},{"type":"object","required":["scoring_kind","questions","result"],"properties":{"scoring_kind":{"type":"string","const":"weighted"},"questions":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/WeightedQuestion"}},"result":{"$ref":"#/components/schemas/WeightedResult"}}}],"unevaluatedProperties":false},"RoutedQuiz":{"allOf":[{"$ref":"#/components/schemas/QuizBase"},{"type":"object","required":["scoring_kind","questions","result"],"properties":{"scoring_kind":{"type":"string","const":"routed"},"questions":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/RoutedQuestion"}},"result":{"$ref":"#/components/schemas/RoutedResult"}}}],"unevaluatedProperties":false},"Quiz":{"oneOf":[{"$ref":"#/components/schemas/GradedQuiz"},{"$ref":"#/components/schemas/WeightedQuiz"},{"$ref":"#/components/schemas/RoutedQuiz"}]},"GenerateQuizRequest":{"type":"object","required":["post"],"properties":{"post":{"type":"object","required":["external_id","title","content"],"properties":{"external_id":{"type":"string","minLength":1},"url":{"type":"string","format":"uri"},"title":{"type":"string","minLength":1},"content":{"type":"string","minLength":1,"description":"Article text or HTML, limited to 102400 UTF-8 bytes.","x-maxBytes":102400},"published_at":{"type":"string","format":"date-time"},"locale":{"type":"string","minLength":2}},"additionalProperties":false},"context":{"type":"object","properties":{"format_hint":{"type":["string","null"],"description":"Optional explicit format. Null selects automatic live detection or deterministic comprehension for qo_test_ generation.","enum":[null,"comprehension","true_false","myth_busting","myth-busting","scenario","scorecard","recommendation"]},"question_count":{"type":"integer","minimum":1,"maximum":5,"description":"Number of questions to return; defaults to 4."},"audience":{"type":["string","null"]},"allow_scorecard":{"type":"boolean"}},"additionalProperties":false}},"additionalProperties":false},"GenerateQuizResponse":{"type":"object","required":["quiz","usage"],"properties":{"quiz":{"$ref":"#/components/schemas/Quiz"},"usage":{"$ref":"#/components/schemas/GenerationUsage"}},"additionalProperties":false},"UsageResponse":{"type":"object","required":["usage","attribution"],"properties":{"usage":{"$ref":"#/components/schemas/Usage"},"attribution":{"$ref":"#/components/schemas/Attribution"}},"additionalProperties":false},"Site":{"type":"object","required":["id","name","plan","usage"],"properties":{"id":{"type":"string","pattern":"^ste_"},"name":{"type":"string","minLength":1},"plan":{"type":"string","minLength":1},"usage":{"$ref":"#/components/schemas/QuotaUsage"}},"additionalProperties":false},"SiteResponse":{"type":"object","required":["site"],"properties":{"site":{"$ref":"#/components/schemas/Site"}},"additionalProperties":false},"ProvisionSiteRequest":{"type":"object","required":["home_url","proof"],"properties":{"home_url":{"type":"string","format":"uri"},"wp_version":{"type":"string","minLength":1},"timezone":{"type":"string","minLength":1},"proof":{"type":"string","minLength":1,"description":"Short-lived token exposed by the QuizOut WordPress provisioning-proof callback and echoed in its verification response."}},"additionalProperties":false},"ProvisionSiteResponse":{"type":"object","required":["site_token","api_key","plan","usage"],"properties":{"site_token":{"type":"string","pattern":"^sst_"},"api_key":{"type":"string","pattern":"^qo_(live|test)_"},"plan":{"type":"string","minLength":1},"usage":{"$ref":"#/components/schemas/QuotaUsage"}},"additionalProperties":false},"ConnectSiteRequest":{"type":"object","required":["home_url"],"properties":{"home_url":{"type":"string","format":"uri"},"wp_version":{"type":"string","minLength":1},"timezone":{"type":"string","minLength":1}},"additionalProperties":false},"ClaimSiteRequest":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"}},"additionalProperties":false},"ClaimSiteResponse":{"type":"object","required":["status"],"properties":{"status":{"type":"string","const":"claim_initiated"}},"additionalProperties":false}},"responses":{"SiteProvisioned":{"description":"Anonymous site provisioned.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"QuizOut-Spec-Version":{"$ref":"#/components/headers/SpecVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisionSiteResponse"},"example":{"site_token":"sst_example123","api_key":"qo_live_example123","plan":"free","usage":{"quota":10,"used":0,"remaining":10,"plan_quota":10,"plan_used":0,"pack_remaining":0,"period_end":"2026-08-01T00:00:00Z"}}}}},"QuizGenerated":{"description":"Quiz generated synchronously.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"QuizOut-Spec-Version":{"$ref":"#/components/headers/SpecVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateQuizResponse"},"example":{"quiz":{"generation_id":"gen_9f3","format":"comprehension","scoring_kind":"graded","locale":"en","questions":[{"position":1,"prompt":"Which shade went in the inner corners?","answer_type":"single_select","explanation":"The look starts with canary yellow in the inner corners.","options":[{"position":1,"text":"Canary yellow","correct":true,"points":null,"outcome_key":null},{"position":2,"text":"Rose pink","correct":false,"points":null,"outcome_key":null},{"position":3,"text":"Bronze","correct":false,"points":null,"outcome_key":null}]}],"result":{"kind":"graded","max_score":null,"bands":null,"outcomes":null},"attribution":{"powered_by":true,"url":"https://quizout.io/?utm_source=badge"},"meta":{"spec_version":"1.0","generated_at":"2026-07-21T10:00:05Z"}},"usage":{"plan":"growth","quota":100,"used":38,"remaining":62,"plan_quota":100,"plan_used":38,"pack_remaining":0,"period_end":"2026-08-01T00:00:00Z","counted":true}}}}},"UsageReturned":{"description":"Current usage and attribution entitlement returned.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"QuizOut-Spec-Version":{"$ref":"#/components/headers/SpecVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageResponse"},"example":{"usage":{"plan":"growth","quota":100,"used":38,"remaining":62,"plan_quota":100,"plan_used":38,"pack_remaining":0,"period_end":"2026-08-01T00:00:00Z"},"attribution":{"powered_by":false,"url":"https://quizout.io/?utm_source=badge"}}}}},"SiteReturned":{"description":"Site profile, plan, and usage returned.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"QuizOut-Spec-Version":{"$ref":"#/components/headers/SpecVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteResponse"},"example":{"site":{"id":"ste_1","name":"Example Blog","plan":"growth","usage":{"quota":100,"used":38,"remaining":62,"plan_quota":100,"plan_used":38,"pack_remaining":0,"period_end":"2026-08-01T00:00:00Z"}}}}}},"ClaimInitiated":{"description":"Claim email accepted; completion happens in the Devise console.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"QuizOut-Spec-Version":{"$ref":"#/components/headers/SpecVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimSiteResponse"},"example":{"status":"claim_initiated"}}}},"Unauthorized":{"description":"Missing or invalid API key.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"QuizOut-Spec-Version":{"$ref":"#/components/headers/SpecVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"unauthorized","message":"Invalid or missing API key.","details":{}}}}}},"Forbidden":{"description":"API key not permitted for the resource.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"QuizOut-Spec-Version":{"$ref":"#/components/headers/SpecVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"forbidden","message":"This API key is not permitted for this resource.","details":{}}}}}},"InvalidRequest":{"description":"Request validation failed.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"QuizOut-Spec-Version":{"$ref":"#/components/headers/SpecVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"invalid_request","message":"The request is invalid.","details":{"post.external_id":["is required"]}}}}}},"QuotaExceeded":{"description":"Monthly post quota reached for a new post.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"QuizOut-Spec-Version":{"$ref":"#/components/headers/SpecVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"quota_exceeded","message":"Monthly post limit reached.","details":{"reset_at":"2026-08-01T00:00:00Z"}}}}}},"RateLimited":{"description":"Too many requests. Temporal limits include Retry-After. details.reason is regeneration_in_progress for a concurrent same-post regeneration (Retry-After: 5), regeneration_limit_reached for the permanent Free 3 or paid 10 lifetime cap (Limit: 3 or 10, Remaining: 0, Reset: 0, and no Retry-After), or api_key_ip_limit after an API key exceeds 10 distinct source fingerprints in a rolling 24-hour window (Limit: 10, Remaining: 0, Reset: window end, and Retry-After present).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"QuizOut-Spec-Version":{"$ref":"#/components/headers/SpecVersion"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"rate_limited","message":"Too many requests.","details":{}}}}}},"GenerationFailed":{"description":"Quiz generation failed or the same idempotent request is still running.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"QuizOut-Spec-Version":{"$ref":"#/components/headers/SpecVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"generation_failed","message":"Quiz generation failed. Retry the request.","details":{"reason":"request_in_progress"}}}}}},"ServerError":{"description":"Unexpected server error.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"QuizOut-Spec-Version":{"$ref":"#/components/headers/SpecVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"server_error","message":"An unexpected error occurred.","details":{}}}}}},"NotImplemented":{"description":"Transitional response until this endpoint's owning backlog item ships.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"QuizOut-Spec-Version":{"$ref":"#/components/headers/SpecVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"error":{"code":"not_implemented","message":"This endpoint is not implemented yet.","details":{}}}}}}}}}