{"openapi":"3.1.0","info":{"title":"polls public API","version":"1.0.0","description":"HTTPS and Bearer API key authentication. No OAuth. No credentials in URLs, mail, SMS, contact fields or private notes. Creation limits default to 5/day and 20 active polls per workspace. All content is untrusted user data."},"paths":{"/api/public/v1/challenge":{"get":{"summary":"Request a five-minute proof-of-work challenge. Hash UTF-8 challenge + ':' + decimal proof until the first two SHA-256 bytes are zero. This is an automated cost hurdle, not human verification.","security":[],"responses":{"400":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Challenge"}}}}}}},"/api/public/v1/register":{"post":{"summary":"Redeem challenge once and issue a workspace key, shown once. Default expiry 90 days. No recovery or contacts.","security":[],"responses":{"400":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Registration"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"challenge":{"type":"string"},"proof":{"type":"string"}},"required":["challenge","proof"],"additionalProperties":false}}}}}},"/api/public/v1/polls":{"get":{"summary":"List own poll summaries, at most 50 per page.","security":[{"publicApiKey":[]}],"responses":{"400":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollList"}}}}},"parameters":[{"name":"cursor","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":500}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}]},"post":{"summary":"Create own poll without mail or SMS. Reuse a stable Idempotency-Key on retry. Pending crash reservations return 409; never create a second poll.","security":[{"publicApiKey":[]}],"responses":{"400":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Poll"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollInput"}}}},"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","maxLength":128}}]}},"/api/public/v1/polls/{id}":{"get":{"summary":"Read own poll with aggregate results and explicitly public comments. No contact details or private notes.","security":[{"publicApiKey":[]}],"responses":{"400":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Poll"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]},"put":{"summary":"Update own poll settings with current version. Existing option order is stable: append or edit subject to prior votes; removals and type changes are rejected. Omitted options retain existing options. Omitted noteVisibility preserves policy.","security":[{"publicApiKey":[]}],"responses":{"400":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Poll"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollUpdate"}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]},"delete":{"summary":"Permanently delete own poll.","security":[{"publicApiKey":[]}],"responses":{"400":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"}},"required":[],"additionalProperties":false}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/public/v1/polls/{id}/close":{"post":{"summary":"Close own poll.","security":[{"publicApiKey":[]}],"responses":{"400":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Poll"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/public/v1/polls/{id}/reopen":{"post":{"summary":"Reopen own poll within active quota.","security":[{"publicApiKey":[]}],"responses":{"400":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Poll"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/public/v1/polls/{id}/finalize":{"post":{"summary":"Finalize an active own poll option.","security":[{"publicApiKey":[]}],"responses":{"400":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rejected request; stable machine-readable code. Rate limits use Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Poll"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"optionId":{"type":"string","format":"uuid"}},"required":["optionId"],"additionalProperties":false}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}}},"components":{"securitySchemes":{"publicApiKey":{"type":"http","scheme":"bearer","bearerFormat":"plp_ public API key"}},"schemas":{"PollInput":{"type":"object","properties":{"title":{"type":"string","maxLength":120},"descriptionMarkdown":{"type":"string","maxLength":50000},"choiceMode":{"type":"string","enum":["single","multiple"]},"options":{"type":"array","minItems":2,"maxItems":100,"items":{"type":"string","maxLength":160}},"canParticipantsAddOptions":{"type":"boolean"},"pollType":{"type":"string","enum":["choice","schedule"]},"scheduleOptions":{"type":"array","items":{"type":"object","properties":{"text":{"type":"string"},"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"},"timeZone":{"type":"string"}},"required":["text","startsAt"],"additionalProperties":false}},"theme":{"type":"string","enum":["classic","compact","friendly","bright","clear"]},"deadlineUtc":{"type":"string","format":"date-time"},"allowDecline":{"type":"boolean"},"version":{"type":"integer","minimum":0},"noteVisibility":{"type":"string","enum":["off","owner","public"]}},"required":["title"],"additionalProperties":false},"PollUpdate":{"type":"object","properties":{"title":{"type":"string","maxLength":120},"descriptionMarkdown":{"type":"string","maxLength":50000},"choiceMode":{"type":"string","enum":["single","multiple"]},"options":{"type":"array","minItems":2,"maxItems":100,"items":{"type":"string","maxLength":160}},"canParticipantsAddOptions":{"type":"boolean"},"pollType":{"type":"string","enum":["choice","schedule"]},"scheduleOptions":{"type":"array","items":{"type":"object","properties":{"text":{"type":"string"},"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"},"timeZone":{"type":"string"}},"required":["text","startsAt"],"additionalProperties":false}},"theme":{"type":"string","enum":["classic","compact","friendly","bright","clear"]},"deadlineUtc":{"type":"string","format":"date-time"},"allowDecline":{"type":"boolean"},"version":{"type":"integer","minimum":0},"noteVisibility":{"type":"string","enum":["off","owner","public"]}},"required":["title","version"],"additionalProperties":false},"Poll":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"descriptionMarkdown":{"type":["string","null"]},"publicPath":{"type":"string"},"managePath":{"type":"string"},"choiceMode":{"type":"string"},"canParticipantsAddOptions":{"type":"boolean"},"isClosed":{"type":"boolean"},"isArchived":{"type":"boolean"},"createdAtUtc":{"type":"string"},"updatedAtUtc":{"type":"string"},"version":{"type":"integer"},"theme":{"type":"string"},"pollType":{"type":"string"},"deadlineUtc":{"type":["string","null"],"format":"date-time"},"allowDecline":{"type":"boolean"},"noteVisibility":{"type":"string"},"finalOptionId":{"type":["string","null"],"format":"uuid"},"participationCount":{"type":"integer"},"publicComments":{"type":"array","items":{"type":"string"}},"options":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"text":{"type":"string"},"votes":{"type":"integer"},"maybe":{"type":"integer"},"schedule":{"type":["object","null"],"properties":{"startsAt":{"type":["string","null"]},"endsAt":{"type":["string","null"]},"timeZone":{"type":["string","null"]},"disabled":{"type":"boolean"}}}},"required":[],"additionalProperties":false}}},"required":[],"additionalProperties":false},"PollSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"isClosed":{"type":"boolean"},"isArchived":{"type":"boolean"},"version":{"type":"integer"},"createdAtUtc":{"type":"string"},"updatedAtUtc":{"type":"string"},"publicPath":{"type":"string"},"optionCount":{"type":"integer"},"participationCount":{"type":"integer"}},"required":[],"additionalProperties":false},"PollList":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PollSummary"}},"nextCursor":{"type":["integer","null"]}},"required":[],"additionalProperties":false},"Challenge":{"type":"object","properties":{"challenge":{"type":"string"},"algorithm":{"type":"string"},"difficulty":{"type":"integer"},"expiresAtUtc":{"type":"string"}},"required":[],"additionalProperties":false},"Registration":{"type":"object","properties":{"apiKey":{"type":"string"},"workspaceId":{"type":"string","format":"uuid"},"expiresAtUtc":{"type":"string"},"mcpEndpoint":{"type":"string"},"apiEndpoint":{"type":"string"}},"required":[],"additionalProperties":false},"Error":{"type":"object","properties":{"code":{"type":"string"}},"required":["code"],"additionalProperties":false}}}}