{"openapi":"3.1.0","info":{"title":"EPP Form Builder API","version":"0.1.0","description":"Swagger-compatible OpenAPI contract for the standalone EPP form builder. The API exposes forms, publishing, submissions, and EPP connector acknowledgements."},"servers":[{"url":"/api/epp"}],"tags":[{"name":"Forms","description":"Create, update, and publish form definitions."},{"name":"Events","description":"Read event workspaces and editable event master data."},{"name":"Submissions","description":"Capture public submissions and mapped EPP payloads."},{"name":"Connectors","description":"Acknowledge queued PDF, calendar, approval, and backend packets."}],"paths":{"/forms":{"get":{"tags":["Forms"],"summary":"List forms","security":[{"EppAdminToken":[]}],"responses":{"200":{"description":"Forms returned"},"401":{"description":"Admin token missing or invalid"},"503":{"description":"Database is not configured or unavailable"}}},"post":{"tags":["Forms"],"summary":"Create a form from an EPP template","security":[{"EppAdminToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFormRequest"}}}},"responses":{"201":{"description":"Form created"},"401":{"description":"Admin token missing or invalid"},"422":{"description":"Invalid request body"}}}},"/forms/{formId}":{"get":{"tags":["Forms"],"summary":"Get a form","security":[{"EppAdminToken":[]}],"parameters":[{"$ref":"#/components/parameters/FormId"}],"responses":{"200":{"description":"Form returned"},"401":{"description":"Admin token missing or invalid"},"404":{"description":"Form not found"}}},"patch":{"tags":["Forms"],"summary":"Update a form","security":[{"EppAdminToken":[]}],"parameters":[{"$ref":"#/components/parameters/FormId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateFormRequest"}}}},"responses":{"200":{"description":"Form updated"},"401":{"description":"Admin token missing or invalid"},"404":{"description":"Form not found"},"422":{"description":"Invalid request body"}}},"delete":{"tags":["Forms"],"summary":"Delete a form and its submissions, versions, packets, and idempotency keys","security":[{"EppAdminToken":[]}],"parameters":[{"$ref":"#/components/parameters/FormId"}],"responses":{"200":{"description":"Form deleted"},"401":{"description":"Admin token missing or invalid"},"404":{"description":"Form not found"}}}},"/forms/{formId}/clone":{"post":{"tags":["Forms"],"summary":"Duplicate a form as a new draft","security":[{"EppAdminToken":[]}],"parameters":[{"$ref":"#/components/parameters/FormId"}],"responses":{"200":{"description":"Form duplicated"},"401":{"description":"Admin token missing or invalid"},"404":{"description":"Form not found"}}}},"/forms/{formId}/publish":{"post":{"tags":["Forms"],"summary":"Publish a form","security":[{"EppAdminToken":[]}],"parameters":[{"$ref":"#/components/parameters/FormId"}],"responses":{"200":{"description":"Form published"},"400":{"description":"Form is not publish-ready"},"401":{"description":"Admin token missing or invalid"},"404":{"description":"Form not found"}}}},"/forms/{formId}/versions":{"get":{"tags":["Forms"],"summary":"List immutable published versions for a form","security":[{"EppAdminToken":[]}],"parameters":[{"$ref":"#/components/parameters/FormId"}],"responses":{"200":{"description":"Versions returned"},"401":{"description":"Admin token missing or invalid"},"404":{"description":"Form not found"}}}},"/forms/{formId}/submissions":{"get":{"tags":["Submissions"],"summary":"List submissions for a form","security":[{"EppAdminToken":[]}],"parameters":[{"$ref":"#/components/parameters/FormId"}],"responses":{"200":{"description":"Submissions returned"},"401":{"description":"Admin token missing or invalid"}}},"post":{"tags":["Submissions"],"summary":"Submit a public response","parameters":[{"$ref":"#/components/parameters/FormId"},{"name":"X-Idempotency-Key","in":"header","required":false,"description":"Optional UUID-shaped key. The first successful response for a given key is cached for 24h; repeats return the same response.","schema":{"type":"string","minLength":8,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSubmissionRequest"}}}},"responses":{"200":{"description":"Idempotent replay of a previous submission"},"201":{"description":"Submission captured and connector packets queued"},"403":{"description":"Form is inactive (FORM_INACTIVE)"},"404":{"description":"Form not found"},"409":{"description":"CAPACITY_EXCEEDED or DUPLICATE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"VALIDATION_ERROR with fieldErrors[]"}}}},"/connectors/{packetId}/ack":{"post":{"tags":["Connectors"],"summary":"Acknowledge or fail a connector packet","security":[{"EppAdminToken":[]}],"parameters":[{"$ref":"#/components/parameters/PacketId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AckConnectorRequest"}}}},"responses":{"200":{"description":"Connector packet updated"},"401":{"description":"Admin token missing or invalid"},"404":{"description":"Connector packet not found"},"422":{"description":"Invalid request body"}}}},"/events":{"get":{"tags":["Events"],"summary":"List event workspaces","security":[{"EppAdminToken":[]}],"responses":{"200":{"description":"Events returned"},"401":{"description":"Admin token missing or invalid"},"503":{"description":"Database is not configured or unavailable"}}}},"/events/{eventId}/data":{"get":{"tags":["Events"],"summary":"Get event master data and mapped records","security":[{"EppAdminToken":[]}],"parameters":[{"$ref":"#/components/parameters/EventId"}],"responses":{"200":{"description":"Event data returned"},"401":{"description":"Admin token missing or invalid"},"404":{"description":"Event not found"}}},"patch":{"tags":["Events"],"summary":"Update one event-data record","security":[{"EppAdminToken":[]}],"parameters":[{"$ref":"#/components/parameters/EventId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEventRecordRequest"}}}},"responses":{"200":{"description":"Event-data record updated"},"401":{"description":"Admin token missing or invalid"},"404":{"description":"Event-data record not found"},"422":{"description":"Invalid request body"}}}}},"components":{"securitySchemes":{"EppAdminToken":{"type":"apiKey","in":"header","name":"x-epp-admin-token"}},"parameters":{"FormId":{"name":"formId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"PacketId":{"name":"packetId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"EventId":{"name":"eventId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}},"schemas":{"CreateFormRequest":{"type":"object","properties":{"templateKey":{"type":"string","enum":["blank-form","event-rsvp","forum-registration","meeting-request","sme-request","approval-request","external-appointment","simple-registration","forum-choice","approval-rsvp"]},"eventId":{"type":"string","format":"uuid"},"name":{"type":"string","maxLength":160},"slug":{"type":"string","pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"}}},"UpdateFormRequest":{"type":"object","properties":{"name":{"type":"string","maxLength":160},"description":{"type":"string","maxLength":1000},"status":{"type":"string","enum":["draft","archived"]},"schema":{"type":"object","additionalProperties":true}}},"CreateSubmissionRequest":{"type":"object","required":["values"],"properties":{"values":{"type":"object","additionalProperties":true},"idempotencyKey":{"type":"string","minLength":8,"maxLength":128}}},"UpdateEventRecordRequest":{"type":"object","oneOf":[{"$ref":"#/components/schemas/UpdateCompanyRecordRequest"},{"$ref":"#/components/schemas/UpdateContactRecordRequest"},{"$ref":"#/components/schemas/UpdateInternalAttendeeRecordRequest"},{"$ref":"#/components/schemas/UpdateTopicRecordRequest"},{"$ref":"#/components/schemas/UpdateLocationRecordRequest"},{"$ref":"#/components/schemas/UpdateTimeSlotRecordRequest"}]},"UpdateCompanyRecordRequest":{"type":"object","required":["kind","id","values"],"properties":{"kind":{"type":"string","enum":["company"]},"id":{"type":"string","format":"uuid"},"values":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1},"website":{"type":"string"},"tier":{"type":"string"},"notes":{"type":"string"},"active":{"type":"boolean"}}}}},"UpdateContactRecordRequest":{"type":"object","required":["kind","id","values"],"properties":{"kind":{"type":"string","enum":["contact"]},"id":{"type":"string","format":"uuid"},"values":{"type":"object","additionalProperties":true}}},"UpdateInternalAttendeeRecordRequest":{"type":"object","required":["kind","id","values"],"properties":{"kind":{"type":"string","enum":["internalAttendee"]},"id":{"type":"string","format":"uuid"},"values":{"type":"object","additionalProperties":true}}},"UpdateTopicRecordRequest":{"type":"object","required":["kind","id","values"],"properties":{"kind":{"type":"string","enum":["topic"]},"id":{"type":"string","format":"uuid"},"values":{"type":"object","additionalProperties":true}}},"UpdateLocationRecordRequest":{"type":"object","required":["kind","id","values"],"properties":{"kind":{"type":"string","enum":["location"]},"id":{"type":"string","format":"uuid"},"values":{"type":"object","additionalProperties":true}}},"UpdateTimeSlotRecordRequest":{"type":"object","required":["kind","id","values"],"properties":{"kind":{"type":"string","enum":["timeSlot"]},"id":{"type":"string","format":"uuid"},"values":{"type":"object","additionalProperties":true}}},"AckConnectorRequest":{"type":"object","properties":{"status":{"type":"string","enum":["acked","failed"],"default":"acked"},"note":{"type":"string","maxLength":1000}}},"ErrorBody":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false]},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["NOT_FOUND","BAD_REQUEST","VALIDATION_ERROR","FORM_INACTIVE","CAPACITY_EXCEEDED","DUPLICATE","DATABASE_UNAVAILABLE","INTERNAL_ERROR"]},"message":{"type":"string"},"fieldErrors":{"type":"array","items":{"type":"object","required":["fieldId","message"],"properties":{"fieldId":{"type":"string"},"label":{"type":"string"},"message":{"type":"string"}}}}}}}}}}}