{"openapi":"3.1.0","info":{"title":"Playable Gift Agent API","version":"0.3.0","description":"Make a small video game about one person with POST /api/make, then poll GET /api/make/{idempotencyKey} for the play link. Agents that write their own HTML game can also save, revise and export it as a free private draft."},"servers":[{"url":"https://playablegift.com"}],"externalDocs":{"url":"https://playablegift.com/SKILL.md"},"components":{"securitySchemes":{"managementToken":{"type":"http","scheme":"bearer","description":"Private 64-character management token returned only when creating a draft. Keep it out of public content."}},"schemas":{"MakeGame":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"brief":{"type":"string","minLength":12,"maxLength":2000,"description":"The sender's supplied details about the recipient, including two or three specific habits, catchphrases or inside jokes."},"friend":{"default":"","description":"The recipient's name.","type":"string","maxLength":60},"from":{"default":"","description":"The sender's name, shown in the game. Optional.","type":"string","maxLength":40},"idempotencyKey":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Private request identifier containing 64 random lowercase hex characters."}},"required":["brief","idempotencyKey"]},"CreateGift":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"recipient":{"type":"string","minLength":1,"maxLength":60},"sender":{"type":"string","minLength":1,"maxLength":60},"title":{"type":"string","minLength":1,"maxLength":80},"concept":{"type":"string","minLength":1,"maxLength":2000},"occasion":{"default":"just-because","type":"string","enum":["birthday","anniversary","thank-you","just-because"]},"theme":{"default":"sunshine","type":"string","enum":["sunshine","midnight","rose"]},"message":{"default":"","type":"string","maxLength":2000},"recipientEmail":{"default":"","anyOf":[{"type":"string","maxLength":254,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"string","const":""}]},"game":{"type":"object","properties":{"html":{"type":"string","minLength":100,"maxLength":120000,"description":"Complete self-contained HTML game with inline CSS/JS and embedded assets. External dependencies, fetches, forms, popups, payments and personal-data collection are prohibited. Supported controls are canvas or DOM with keyboard and touch input. The game includes restart and clear win/lose states. Completion notification is parent.postMessage({type:'playablegift:complete'}, '*')."}},"required":["html"],"additionalProperties":false},"idempotencyKey":{"type":"string","pattern":"^[a-f0-9]{64}$"}},"required":["recipient","sender","title","concept","game","idempotencyKey"],"additionalProperties":false},"ReviseGift":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"recipient":{"type":"string","minLength":1,"maxLength":60},"sender":{"type":"string","minLength":1,"maxLength":60},"title":{"type":"string","minLength":1,"maxLength":80},"concept":{"type":"string","minLength":1,"maxLength":2000},"occasion":{"default":"just-because","type":"string","enum":["birthday","anniversary","thank-you","just-because"]},"theme":{"default":"sunshine","type":"string","enum":["sunshine","midnight","rose"]},"message":{"default":"","type":"string","maxLength":2000},"recipientEmail":{"default":"","anyOf":[{"type":"string","maxLength":254,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"string","const":""}]},"game":{"type":"object","properties":{"html":{"type":"string","minLength":100,"maxLength":120000,"description":"Complete self-contained HTML game with inline CSS/JS and embedded assets. External dependencies, fetches, forms, popups, payments and personal-data collection are prohibited. Supported controls are canvas or DOM with keyboard and touch input. The game includes restart and clear win/lose states. Completion notification is parent.postMessage({type:'playablegift:complete'}, '*')."}},"required":["html"],"additionalProperties":false},"expectedRevision":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["recipient","sender","title","concept","game","expectedRevision"],"additionalProperties":false}}},"paths":{"/api/make":{"post":{"operationId":"make_game","summary":"Start making a game about one person","description":"Read /SKILL.md for the workflow, privacy and retries.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MakeGame"}}}},"responses":{"200":{"description":"Success"},"202":{"description":"Building. Poll GET /api/make/{idempotencyKey}."},"400":{"description":"Invalid input"},"401":{"description":"Missing bearer token"},"403":{"description":"Origin header missing or not allowed"},"404":{"description":"Build or draft not found"},"409":{"description":"Idempotency key or revision conflict"},"429":{"description":"Daily allowance or traffic limit reached. Respect Retry-After."},"503":{"description":"Game making is paused for a moment"}},"parameters":[{"name":"Origin","in":"header","required":true,"schema":{"type":"string","const":"https://playablegift.com"}}]}},"/api/make/{idempotencyKey}":{"get":{"operationId":"get_made_game","summary":"Check a game started with make_game. When complete, it returns shareUrl and manageUrl.","description":"Read /SKILL.md for the workflow, privacy and retries.","responses":{"200":{"description":"Success"},"202":{"description":"Still building"},"400":{"description":"Invalid input"},"401":{"description":"Missing bearer token"},"403":{"description":"Origin header missing or not allowed"},"404":{"description":"Build or draft not found"},"409":{"description":"Idempotency key or revision conflict"},"429":{"description":"Daily allowance or traffic limit reached. Respect Retry-After."},"503":{"description":"Game making is paused for a moment"}},"parameters":[{"name":"idempotencyKey","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-f0-9]{64}$"}}]}},"/api/agent/catalog":{"get":{"operationId":"get_gift_catalog","summary":"Read the requirements and limits for uploading your own game","description":"Read /SKILL.md for the workflow, privacy and retries.","responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing bearer token"},"403":{"description":"Origin header missing or not allowed"},"404":{"description":"Build or draft not found"},"409":{"description":"Idempotency key or revision conflict"},"429":{"description":"Daily allowance or traffic limit reached. Respect Retry-After."},"503":{"description":"Game making is paused for a moment"}}}},"/api/agent/games":{"post":{"operationId":"create_custom_game","summary":"Save your own HTML game as a free private draft, or replay the same request","description":"Read /SKILL.md for the workflow, privacy and retries.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGift"}}}},"responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing bearer token"},"403":{"description":"Origin header missing or not allowed"},"404":{"description":"Build or draft not found"},"409":{"description":"Idempotency key or revision conflict"},"429":{"description":"Daily allowance or traffic limit reached. Respect Retry-After."},"503":{"description":"Game making is paused for a moment"}}}},"/api/agent/gift":{"get":{"operationId":"get_gift","summary":"Read a draft's revision, preview link and status","description":"Read /SKILL.md for the workflow, privacy and retries.","security":[{"managementToken":[]}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing bearer token"},"403":{"description":"Origin header missing or not allowed"},"404":{"description":"Build or draft not found"},"409":{"description":"Idempotency key or revision conflict"},"429":{"description":"Daily allowance or traffic limit reached. Respect Retry-After."},"503":{"description":"Game making is paused for a moment"}}}},"/api/agent/gift/revisions":{"get":{"operationId":"get_gift_history","summary":"Read details of the last five private revisions","description":"Read /SKILL.md for the workflow, privacy and retries.","security":[{"managementToken":[]}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing bearer token"},"403":{"description":"Origin header missing or not allowed"},"404":{"description":"Build or draft not found"},"409":{"description":"Idempotency key or revision conflict"},"429":{"description":"Daily allowance or traffic limit reached. Respect Retry-After."},"503":{"description":"Game making is paused for a moment"}}},"post":{"operationId":"revise_custom_game","summary":"Replace a draft, if expectedRevision still matches","description":"Read /SKILL.md for the workflow, privacy and retries.","security":[{"managementToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviseGift"}}}},"responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing bearer token"},"403":{"description":"Origin header missing or not allowed"},"404":{"description":"Build or draft not found"},"409":{"description":"Idempotency key or revision conflict"},"429":{"description":"Daily allowance or traffic limit reached. Respect Retry-After."},"503":{"description":"Game making is paused for a moment"}}}},"/api/agent/gift/export":{"get":{"operationId":"export_gift","summary":"Export portable gift JSON with the self-contained game HTML (optional ?revision=N)","description":"Read /SKILL.md for the workflow, privacy and retries.","security":[{"managementToken":[]}],"responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing bearer token"},"403":{"description":"Origin header missing or not allowed"},"404":{"description":"Build or draft not found"},"409":{"description":"Idempotency key or revision conflict"},"429":{"description":"Daily allowance or traffic limit reached. Respect Retry-After."},"503":{"description":"Game making is paused for a moment"}}}},"/api/preview/{previewToken}":{"get":{"operationId":"get_private_preview","summary":"Read a draft's private preview","description":"Read /SKILL.md for the workflow, privacy and retries.","responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing bearer token"},"403":{"description":"Origin header missing or not allowed"},"404":{"description":"Build or draft not found"},"409":{"description":"Idempotency key or revision conflict"},"429":{"description":"Daily allowance or traffic limit reached. Respect Retry-After."},"503":{"description":"Game making is paused for a moment"}},"parameters":[{"name":"previewToken","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-f0-9]{64}$"}}]}}}}