{
  "openapi": "3.1.1",
  "info": {
    "title": "Form Koi API",
    "version": "1.0.0-preview",
    "description": "Preview contract for the staging API. Production is not yet available. Management requests are server-to-server HTTPS with a scoped, expiring bearer token from the workspace. Do not include Cookie, Origin or x-formkoi-proxy-key on management requests. JSON mutation bodies are limited to 32 KiB and reject unknown properties. Required scopes are specified in x-required-scopes; an empty array on inspectToken means any valid token. Authentication, billing, token administration and dashboard receiver tests are session-only and deliberately excluded. Timestamps are Unix milliseconds unless a schema explicitly uses date-time. Success response shapes vary by endpoint. Unknown error codes should be displayed by their message, with requestId retained for diagnosis."
  },
  "servers": [
    {
      "url": "https://api-staging.formkoi.com",
      "description": "Staging only. Email is captured in the test inbox until live sending is activated."
    }
  ],
  "tags": [
    {
      "name": "Submissions",
      "description": "Public visitor submission intake."
    },
    {
      "name": "Forms",
      "description": "Form configuration and customer Turnstile widgets."
    },
    {
      "name": "Recipients",
      "description": "Workspace email recipients and verification."
    },
    {
      "name": "Messages",
      "description": "Stored submissions, delivery history, exports and private files."
    },
    {
      "name": "Routing",
      "description": "Ordered rules for selecting notification recipients."
    },
    {
      "name": "Visitor replies",
      "description": "Consented automatic replies and draft previews."
    },
    {
      "name": "Webhooks",
      "description": "Signed outgoing events, receiver configuration and delivery history."
    },
    {
      "name": "Account",
      "description": "Token metadata and current workspace usage."
    }
  ],
  "externalDocs": {
    "url": "https://staging.formkoi.com/docs/api",
    "description": "Guides, examples, error handling and credential lifecycle."
  },
  "paths": {
    "/v1/token": {
      "get": {
        "operationId": "inspectToken",
        "summary": "Inspect the current API token",
        "description": "Any valid management token may inspect itself. Does not expose its secret or allow token creation, rotation or revocation.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Token"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms": {
      "get": {
        "operationId": "listForms",
        "summary": "List forms",
        "description": "Returns form settings and recipient IDs. The list omits Turnstile; retrieve a single form to read that configuration.",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "forms:read"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "description": "Page size."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^\\d{13}:[a-f0-9-]{36}$"
            },
            "description": "Opaque nextCursor from the previous page. Results are newest first, ordered by timestamp and ID."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FormSummary"
                      }
                    },
                    "nextCursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "createForm",
        "summary": "Create a form",
        "description": "Create a form",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "forms:write"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateForm"
              },
              "example": {
                "name": "Website contact",
                "recipientIds": [
                  "11111111-1111-4111-8111-111111111111"
                ],
                "settings": {
                  "subject": "A new website enquiry",
                  "messageRetentionDays": null,
                  "honeypot": "botcheck",
                  "allowedOrigins": [
                    "https://www.example.com"
                  ],
                  "redirectUrl": "https://www.example.com/thanks",
                  "uploads": {
                    "enabled": false,
                    "retentionDays": 30
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Form"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms/{formId}": {
      "get": {
        "operationId": "getForm",
        "summary": "Read a form",
        "description": "Read a form",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "forms:read"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Form"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "updateForm",
        "summary": "Update a form",
        "description": "At least one field. Settings are merged into the saved settings: send only the members you want to change, including inside uploads, and omitted members keep their current values. Recipient IDs must belong to verified addresses in this workspace.",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "forms:write"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateForm"
              },
              "example": {
                "name": "Project enquiries",
                "status": "active"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Form"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteForm",
        "summary": "Permanently delete a form and its messages",
        "description": "Permanently delete a form and its messages",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "forms:write"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted. No response body."
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms/{formId}/rotate-key": {
      "post": {
        "operationId": "rotatePublicKey",
        "summary": "Replace the public submission key",
        "description": "No request body. Invalidates the old key immediately; update the installed website snippet.",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "forms:write"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Form"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms/{formId}/turnstile": {
      "post": {
        "operationId": "saveTurnstile",
        "summary": "Connect or update a customer Turnstile widget",
        "description": "Connect or update a customer Turnstile widget",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "forms:write"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TurnstileInput"
              },
              "example": {
                "siteKey": "REPLACE_WITH_YOUR_SITE_KEY",
                "secretKey": "REPLACE_WITH_YOUR_SECRET_KEY",
                "hostnames": [
                  "www.example.com"
                ],
                "enabled": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Turnstile"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteTurnstile",
        "summary": "Disconnect the customer Turnstile widget",
        "description": "Disconnects anti-spam verification. Visitor replies will no longer be eligible without a verified widget.",
        "tags": [
          "Forms"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "forms:write"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted. No response body."
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/recipients": {
      "get": {
        "operationId": "listRecipients",
        "summary": "List recipient verification status",
        "description": "All workspace recipients, up to 20, oldest first. This endpoint is not paginated.",
        "tags": [
          "Recipients"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "recipients:read"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Recipient"
                      },
                      "maxItems": 20
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "addRecipient",
        "summary": "Add a recipient or resend verification",
        "description": "A recipient must verify their own address before a form can use it. One verification per address per minute; maximum 20 recipients per workspace. Staging uses the test inbox until live delivery is activated.",
        "tags": [
          "Recipients"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "recipients:write"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecipientInput"
              },
              "example": {
                "email": "hello@example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Address is already verified.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Recipient"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "202": {
            "description": "Verification email queued/sent to the address. The address is not yet verified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecipientPending"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/submissions": {
      "get": {
        "operationId": "listSubmissions",
        "summary": "List messages",
        "description": "List messages",
        "tags": [
          "Messages"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "submissions:read"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 25
            },
            "description": "Page size."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^\\d{13}:[a-f0-9-]{36}$"
            },
            "description": "Opaque nextCursor from the previous page. Results are newest first, ordered by timestamp and ID."
          },
          {
            "name": "folder",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "inbox",
                "archive",
                "spam",
                "all"
              ]
            },
            "description": "Defaults to inbox; use all to include every folder."
          },
          {
            "name": "formId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Only this form's messages."
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Case-insensitive substring search; trimmed, maximum 200 characters."
          },
          {
            "name": "unread",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "description": "Only the literal true restricts results to unread messages."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SubmissionSummary"
                      }
                    },
                    "nextCursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/submissions/export": {
      "get": {
        "operationId": "exportSubmissions",
        "summary": "Export matching messages as CSV",
        "description": "More than 1,000 matching messages returns 422 export_too_large; narrow the filters. Does not return a cursor.",
        "tags": [
          "Messages"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "submissions:read"
        ],
        "parameters": [
          {
            "name": "folder",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "inbox",
                "archive",
                "spam",
                "all"
              ]
            },
            "description": "Defaults to inbox; use all to include every folder."
          },
          {
            "name": "formId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Only this form's messages."
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Case-insensitive substring search; trimmed, maximum 200 characters."
          },
          {
            "name": "unread",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "description": "Only the literal true restricts results to unread messages."
          }
        ],
        "responses": {
          "200": {
            "description": "UTF-8 CSV with BOM; up to 1,000 messages. Includes id, received_at (ISO timestamp), form, folder, name, email, fields_json. Formula-like cell values are escaped.",
            "headers": {
              "Content-Disposition": {
                "schema": {
                  "type": "string"
                },
                "description": "Forces a CSV download."
              }
            },
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/submissions/{submissionId}": {
      "get": {
        "operationId": "getSubmission",
        "summary": "Read a message and delivery history",
        "description": "Read a message and delivery history",
        "tags": [
          "Messages"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "submissions:read"
        ],
        "parameters": [
          {
            "name": "submissionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The submissionId."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Submission"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "updateSubmission",
        "summary": "Move a message or change read state",
        "description": "Returns message fields and notification plan. Unlike GET, this response omits deliveries, attempts, attachments and autoresponder decision.",
        "tags": [
          "Messages"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "submissions:write"
        ],
        "parameters": [
          {
            "name": "submissionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The submissionId."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmissionUpdate"
              },
              "example": {
                "folder": "archive",
                "read": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/SubmissionFields"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteSubmission",
        "summary": "Permanently delete a message",
        "description": "Permanently delete a message",
        "tags": [
          "Messages"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "submissions:write"
        ],
        "parameters": [
          {
            "name": "submissionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The submissionId."
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted. No response body."
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/submissions/{submissionId}/attachments/{attachmentId}": {
      "get": {
        "operationId": "downloadAttachment",
        "summary": "Download a private attachment",
        "description": "Download a private attachment",
        "tags": [
          "Messages"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "files:read"
        ],
        "parameters": [
          {
            "name": "submissionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The submissionId."
          },
          {
            "name": "attachmentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The attachmentId."
          }
        ],
        "responses": {
          "200": {
            "description": "Raw file bytes as application/octet-stream with forced download. Expired/unavailable files return an error, never a public R2 URL.",
            "headers": {
              "Content-Disposition": {
                "schema": {
                  "type": "string"
                },
                "description": "Attachment filename."
              }
            },
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/submissions/{submissionId}/deliveries/{emailDeliveryId}/retry": {
      "post": {
        "operationId": "retryNotification",
        "summary": "Retry an eligible owner email notification",
        "description": "The body is optional; acknowledgePossibleDuplicate defaults to false.",
        "tags": [
          "Messages"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "submissions:write"
        ],
        "parameters": [
          {
            "name": "submissionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The submissionId."
          },
          {
            "name": "emailDeliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9-]{32,36}$"
            },
            "description": "The emailDeliveryId."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmailRetry"
              },
              "example": {
                "acknowledgePossibleDuplicate": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Read current usage and allowance",
        "description": "UTC calendar month. Accepted counts do not reset when messages are deleted. Storage bytes include objects awaiting cleanup. Folder counts reflect current messages; empty folders may be absent.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "usage:read"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Usage"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms/{formId}/routing": {
      "get": {
        "operationId": "getRouting",
        "summary": "Read ordered recipient routing",
        "description": "Read ordered recipient routing",
        "tags": [
          "Routing"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "integrations:read"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Routing"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "saveRouting",
        "summary": "Save recipient routing with a revision",
        "description": "Save recipient routing with a revision",
        "tags": [
          "Routing"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "integrations:write"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoutingSave"
              },
              "example": {
                "revision": null,
                "enabled": true,
                "rules": [
                  {
                    "id": "22222222-2222-4222-8222-222222222222",
                    "name": "Project enquiries",
                    "field": "topic",
                    "operator": "equals",
                    "value": "project",
                    "recipientIds": [
                      "11111111-1111-4111-8111-111111111111"
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Routing"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms/{formId}/routing/preview": {
      "post": {
        "operationId": "previewRouting",
        "summary": "Preview which recipients a draft selects",
        "description": "Does not save configuration, create a message or send email. Uses verified workspace recipients.",
        "tags": [
          "Routing"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "integrations:read"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoutingPreview"
              },
              "example": {
                "config": {
                  "enabled": true,
                  "rules": [
                    {
                      "id": "22222222-2222-4222-8222-222222222222",
                      "name": "Project enquiries",
                      "field": "topic",
                      "operator": "equals",
                      "value": "project",
                      "recipientIds": [
                        "11111111-1111-4111-8111-111111111111"
                      ]
                    }
                  ]
                },
                "fields": {
                  "topic": "project",
                  "message": "Can we work together?"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/NotificationPlan"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms/{formId}/autoresponder": {
      "get": {
        "operationId": "getAutoresponder",
        "summary": "Read visitor reply settings",
        "description": "Read visitor reply settings",
        "tags": [
          "Visitor replies"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "integrations:read"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "anyOf": [
                        {
                          "$ref": "#/components/schemas/Autoresponder"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "saveAutoresponder",
        "summary": "Save visitor reply settings with a revision",
        "description": "Save visitor reply settings with a revision",
        "tags": [
          "Visitor replies"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "integrations:write"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AutoresponderSave"
              },
              "example": {
                "revision": null,
                "enabled": false,
                "subject": "Thanks for your message",
                "message": "Your note is with our team. We will reply to this address.",
                "replyRecipientId": "11111111-1111-4111-8111-111111111111"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Autoresponder"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms/{formId}/autoresponder/preview": {
      "post": {
        "operationId": "previewAutoresponder",
        "summary": "Render a draft visitor reply without sending",
        "description": "Pass the config directly, with no config/revision wrapper. Does not save or send; enabling Turnstile is not required to preview a draft.",
        "tags": [
          "Visitor replies"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "integrations:read"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AutoresponderConfig"
              },
              "example": {
                "enabled": false,
                "subject": "Thanks for your message",
                "message": "Your note is with our team. We will reply to this address.",
                "replyRecipientId": "11111111-1111-4111-8111-111111111111"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AutoresponderPreview"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms/{formId}/webhook": {
      "get": {
        "operationId": "getWebhook",
        "summary": "Read the configured webhook receiver",
        "description": "Read the configured webhook receiver",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "integrations:read"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "anyOf": [
                        {
                          "$ref": "#/components/schemas/Webhook"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "saveWebhook",
        "summary": "Create or update a webhook receiver",
        "description": "Create or update a webhook receiver",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "integrations:write"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookInput"
              },
              "example": {
                "url": "https://hooks.example.com/formkoi",
                "enabled": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated. No signing secret is returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "201": {
            "description": "Created. Save the one-time signing secret.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCreated"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhook",
        "summary": "Delete the webhook configuration",
        "description": "Delete the webhook configuration",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "integrations:write"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted. No response body."
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms/{formId}/webhook/rotate-secret": {
      "post": {
        "operationId": "rotateWebhookSecret",
        "summary": "Replace the webhook signing secret",
        "description": "Requires current revision. Immediately invalidates the previous secret and cancels queued deliveries for the old revision. Save the one-time new value.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "integrations:write"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Revision"
              },
              "example": {
                "revision": "33333333-3333-4333-8333-333333333333"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCreated"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms/{formId}/webhook/test": {
      "post": {
        "operationId": "testWebhook",
        "summary": "Queue a synthetic webhook test",
        "description": "No request body is needed. Tests may run while the endpoint is disabled. Limited to one per minute and 100 per day for this endpoint.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "integrations:write"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Empty"
              },
              "example": {}
            }
          }
        },
        "responses": {
          "202": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookTest"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms/{formId}/webhook/deliveries": {
      "get": {
        "operationId": "listWebhookDeliveries",
        "summary": "List webhook deliveries",
        "description": "List webhook deliveries",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "submissions:read"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            },
            "description": "Page size."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^\\d{13}:[a-f0-9-]{36}$"
            },
            "description": "Opaque nextCursor from the previous page. Results are newest first, ordered by timestamp and ID."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "nextCursor": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms/{formId}/webhook/deliveries/{deliveryId}": {
      "get": {
        "operationId": "getWebhookDelivery",
        "summary": "Read a webhook payload and attempt history",
        "description": "Read a webhook payload and attempt history",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "submissions:read"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          },
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The deliveryId."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WebhookDeliveryDetail"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/forms/{formId}/webhook/deliveries/{deliveryId}/retry": {
      "post": {
        "operationId": "retryWebhook",
        "summary": "Retry an eligible failed webhook",
        "description": "No request body is needed. Available after one minute, only while the original endpoint revision is current. Submission events also need an enabled endpoint and a message outside spam. Reuses the same event ID; receivers must deduplicate.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": [
          "submissions:write"
        ],
        "parameters": [
          {
            "name": "formId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The formId."
          },
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The deliveryId."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Empty"
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/f/{publicKey}": {
      "post": {
        "operationId": "submitForm",
        "tags": [
          "Submissions"
        ],
        "summary": "Send a visitor's form submission",
        "security": [],
        "description": "Public endpoint: use the form's public key, never a management token. Supports custom fields, repeated values and opt-in uploads. Origin controls, Turnstile, honeypot, rate limits and allowance are enforced. A success acknowledges durable receipt, not email delivery, and does not disclose spam classification. Prefer Accept: application/json in JavaScript. HTML form bodies with Accept containing text/html get a thank-you page or configured redirect. JSON bodies always get JSON on success. Errors may be HTML whenever Accept contains text/html.",
        "parameters": [
          {
            "name": "publicKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^fk_[a-f0-9]{64}$"
            },
            "description": "Public form key copied from the workspace."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[a-zA-Z0-9_.:-]{8,128}$"
            },
            "description": "Reuse for the same logical submission. Same key with different content returns 409. Takes precedence over _idempotency_key. Deduplication lasts while the stored message exists."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "When the form has allowedOrigins, this must exactly match one. Browser supplied. An origin check is not caller authentication."
          }
        ],
        "requestBody": {
          "required": true,
          "description": "64 KiB normally; multipart with uploads enabled allows 10 MiB plus 128 KiB encoding overhead, and normalized text still has a 64 KiB limit. Up to 3 files, each up to 5 MiB, 10 MiB combined. PNG, JPEG, WebP, PDF and UTF-8 .txt only. No malware scanning. Use the configured honeypot (default botcheck) and cf-turnstile-response where enabled. _formkoi_autoreply=true requests a consented visitor reply; it is not guaranteed. Recipients, subject and redirect are owner settings, not visitor-controlled fields.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmissionInput"
              },
              "example": {
                "name": "Alex",
                "email": "alex@example.com",
                "message": "Can you help with my project?",
                "botcheck": ""
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "maxProperties": 50,
                "propertyNames": {
                  "type": "string",
                  "pattern": "^[a-zA-Z_][a-zA-Z0-9_.\\[\\]-]{0,63}$",
                  "not": {
                    "enum": [
                      "__proto__",
                      "constructor",
                      "prototype"
                    ]
                  }
                },
                "additionalProperties": {
                  "anyOf": [
                    {
                      "type": "string",
                      "maxLength": 10000
                    },
                    {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "maxLength": 10000
                      },
                      "maxItems": 20
                    }
                  ]
                },
                "description": "At most 50 field names, 100 scalar values in total, and 64 KiB after conversion to strings. Nested objects and null are rejected. Control fields count toward these limits. Nonempty visitor fields or a file are required. The email field, when nonempty, must contain a valid address. Numbers and booleans become strings."
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "additionalProperties": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "string",
                      "format": "binary"
                    },
                    {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  ]
                },
                "description": "Named text fields and file parts. File fields must be separate from name, email, message, reserved controls and the honeypot. For a portable generated client, construct FormData explicitly."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Duplicate JSON submission, or successful HTML thank-you page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionResult"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "New submission durably stored.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionResult"
                }
              }
            }
          },
          "303": {
            "description": "Successful HTML submission; redirect configured by the form owner.",
            "headers": {
              "Location": {
                "schema": {
                  "type": "string",
                  "format": "uri"
                },
                "description": "Configured HTTPS thank-you URL."
              }
            }
          },
          "default": {
            "description": "Error. Inspect error.code and retain requestId for support; 429 can include Retry-After. Accept containing text/html may produce an HTML error page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "fkm_<environment>_<secret>",
        "description": "Scoped management token created in the workspace. Keep it on your server. Never use a public form key as a management token."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "requestId": {
                "type": "string",
                "format": "uuid"
              }
            },
            "required": [
              "code",
              "message",
              "requestId"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "error"
        ],
        "additionalProperties": false
      },
      "Message": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          }
        },
        "required": [
          "message"
        ],
        "additionalProperties": false
      },
      "Empty": {
        "type": "object",
        "properties": {},
        "required": [],
        "additionalProperties": false
      },
      "SubmissionInput": {
        "type": "object",
        "maxProperties": 50,
        "propertyNames": {
          "type": "string",
          "pattern": "^[a-zA-Z_][a-zA-Z0-9_.\\[\\]-]{0,63}$",
          "not": {
            "enum": [
              "__proto__",
              "constructor",
              "prototype"
            ]
          }
        },
        "additionalProperties": {
          "anyOf": [
            {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 10000
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                }
              ]
            },
            {
              "type": "array",
              "items": {
                "anyOf": [
                  {
                    "type": "string",
                    "maxLength": 10000
                  },
                  {
                    "type": "number"
                  },
                  {
                    "type": "boolean"
                  }
                ]
              },
              "maxItems": 20
            }
          ]
        },
        "description": "At most 50 field names, 100 scalar values in total, and 64 KiB after conversion to strings. Nested objects and null are rejected. Control fields count toward these limits. Nonempty visitor fields or a file are required. The email field, when nonempty, must contain a valid address. Numbers and booleans become strings."
      },
      "SubmissionResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          },
          "submissionId": {
            "type": "string",
            "format": "uuid"
          },
          "duplicate": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "submissionId",
          "duplicate",
          "message"
        ],
        "additionalProperties": false
      },
      "FormDesign": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "enum": [
              2
            ]
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "pattern": "^[a-zA-Z0-9_-]{1,40}$"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "text",
                    "email",
                    "tel",
                    "url",
                    "number",
                    "date",
                    "textarea",
                    "select",
                    "radio",
                    "checkboxes",
                    "checkbox",
                    "file",
                    "hidden"
                  ]
                },
                "name": {
                  "type": "string",
                  "pattern": "^[a-zA-Z_][a-zA-Z0-9_-]{0,63}$",
                  "not": {
                    "enum": [
                      "__proto__",
                      "constructor",
                      "prototype",
                      "access_key",
                      "cf-turnstile-response",
                      "_idempotency_key"
                    ]
                  },
                  "description": "Unique within the design. File fields cannot be named name, email or message."
                },
                "label": {
                  "type": "string",
                  "maxLength": 120
                },
                "placeholder": {
                  "type": "string",
                  "maxLength": 120
                },
                "help": {
                  "type": "string",
                  "maxLength": 240
                },
                "required": {
                  "type": "boolean"
                },
                "options": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "maxItems": 20,
                  "description": "Choices for select, radio and checkboxes fields."
                },
                "width": {
                  "type": "string",
                  "enum": [
                    "full",
                    "half"
                  ]
                },
                "value": {
                  "type": "string",
                  "maxLength": 200,
                  "description": "Hidden field value, or the value a single checkbox sends."
                }
              },
              "required": [
                "id",
                "type",
                "name",
                "label",
                "placeholder",
                "help",
                "required",
                "options",
                "width",
                "value"
              ],
              "additionalProperties": false,
              "description": "One field in the designed form."
            },
            "minItems": 1,
            "maxItems": 30
          },
          "theme": {
            "type": "object",
            "properties": {
              "background": {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              },
              "text": {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              },
              "accent": {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              },
              "font": {
                "type": "string",
                "enum": [
                  "sans",
                  "serif",
                  "mono"
                ]
              },
              "radius": {
                "type": "integer",
                "minimum": 0,
                "maximum": 24
              },
              "spacing": {
                "type": "integer",
                "minimum": 12,
                "maximum": 32
              },
              "fullWidth": {
                "type": "boolean"
              },
              "inputStyle": {
                "type": "string",
                "enum": [
                  "outline",
                  "filled",
                  "underline"
                ]
              }
            },
            "required": [
              "background",
              "text",
              "accent",
              "font",
              "radius",
              "spacing",
              "fullWidth",
              "inputStyle"
            ],
            "additionalProperties": false
          },
          "copy": {
            "type": "object",
            "properties": {
              "heading": {
                "type": "string",
                "maxLength": 120
              },
              "description": {
                "type": "string",
                "maxLength": 400
              },
              "button": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              "success": {
                "type": "string",
                "maxLength": 200
              }
            },
            "required": [
              "heading",
              "description",
              "button",
              "success"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "version",
          "fields",
          "theme",
          "copy"
        ],
        "additionalProperties": false,
        "description": "The visual form designer’s fields, styles and copy. Always sent whole; a patch replaces the saved design. Field names cannot match the honeypot."
      },
      "FormSettingsInput": {
        "type": "object",
        "properties": {
          "appearance": {
            "$ref": "#/components/schemas/FormDesign"
          },
          "messageRetentionDays": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 1,
                "maximum": 365
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Automatic expiry for newly received messages, in days. Null keeps messages until explicit deletion. Existing message expiries are unchanged."
          },
          "uploads": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean",
                "default": false
              },
              "retentionDays": {
                "type": "integer",
                "minimum": 1,
                "maximum": 365,
                "default": 30
              }
            },
            "required": [],
            "additionalProperties": false
          },
          "allowedOrigins": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri",
              "pattern": "^https://",
              "description": "HTTPS origin only: no credentials, path other than /, query or fragment. Normalized to its origin."
            },
            "maxItems": 10,
            "default": []
          },
          "redirectUrl": {
            "type": "string",
            "default": "",
            "description": "Empty string disables the redirect. Otherwise an HTTPS URL without credentials. Used only for successful HTML form responses."
          },
          "subject": {
            "type": "string",
            "minLength": 1,
            "maxLength": 150,
            "pattern": "^[^\\r\\n]*$",
            "default": "New form submission",
            "description": "Trimmed before validation. Notification subject controlled by the owner."
          },
          "honeypot": {
            "type": "string",
            "pattern": "^[a-zA-Z][a-zA-Z0-9_]{0,63}$",
            "not": {
              "enum": [
                "name",
                "email",
                "message",
                "access_key",
                "_formkoi_autoreply"
              ]
            },
            "default": "botcheck"
          }
        },
        "required": [],
        "additionalProperties": false
      },
      "FormSettingsPatch": {
        "type": "object",
        "required": [],
        "additionalProperties": false,
        "description": "Any subset of settings, nested uploads members included. Omitted members keep their saved values.",
        "properties": {
          "appearance": {
            "$ref": "#/components/schemas/FormDesign"
          },
          "messageRetentionDays": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 1,
                "maximum": 365
              },
              {
                "type": "null"
              }
            ],
            "description": "Automatic expiry for newly received messages, in days. Null keeps messages until explicit deletion. Existing message expiries are unchanged."
          },
          "uploads": {
            "type": "object",
            "required": [],
            "additionalProperties": false,
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "retentionDays": {
                "type": "integer",
                "minimum": 1,
                "maximum": 365
              }
            }
          },
          "allowedOrigins": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri",
              "pattern": "^https://",
              "description": "HTTPS origin only: no credentials, path other than /, query or fragment. Normalized to its origin."
            },
            "maxItems": 10
          },
          "redirectUrl": {
            "type": "string",
            "description": "Empty string disables the redirect. Otherwise an HTTPS URL without credentials. Used only for successful HTML form responses."
          },
          "subject": {
            "type": "string",
            "minLength": 1,
            "maxLength": 150,
            "pattern": "^[^\\r\\n]*$",
            "description": "Trimmed before validation. Notification subject controlled by the owner."
          },
          "honeypot": {
            "type": "string",
            "pattern": "^[a-zA-Z][a-zA-Z0-9_]{0,63}$",
            "not": {
              "enum": [
                "name",
                "email",
                "message",
                "access_key",
                "_formkoi_autoreply"
              ]
            }
          }
        }
      },
      "FormSettings": {
        "type": "object",
        "properties": {
          "appearance": {
            "$ref": "#/components/schemas/FormDesign"
          },
          "messageRetentionDays": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 1,
                "maximum": 365
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Automatic expiry for newly received messages, in days. Null keeps messages until explicit deletion. Existing message expiries are unchanged."
          },
          "uploads": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "retentionDays": {
                "type": "integer",
                "minimum": 1,
                "maximum": 365
              }
            },
            "required": [
              "enabled",
              "retentionDays"
            ],
            "additionalProperties": false
          },
          "allowedOrigins": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri",
              "pattern": "^https://",
              "description": "HTTPS origin only: no credentials, path other than /, query or fragment. Normalized to its origin."
            },
            "maxItems": 10,
            "default": []
          },
          "redirectUrl": {
            "type": "string",
            "default": "",
            "description": "Empty string disables the redirect. Otherwise an HTTPS URL without credentials. Used only for successful HTML form responses."
          },
          "subject": {
            "type": "string",
            "minLength": 1,
            "maxLength": 150,
            "pattern": "^[^\\r\\n]*$",
            "default": "New form submission",
            "description": "Trimmed before validation. Notification subject controlled by the owner."
          },
          "honeypot": {
            "type": "string",
            "pattern": "^[a-zA-Z][a-zA-Z0-9_]{0,63}$",
            "not": {
              "enum": [
                "name",
                "email",
                "message",
                "access_key",
                "_formkoi_autoreply"
              ]
            },
            "default": "botcheck"
          }
        },
        "required": [
          "messageRetentionDays",
          "uploads",
          "allowedOrigins",
          "redirectUrl",
          "subject",
          "honeypot"
        ],
        "additionalProperties": false
      },
      "CreateForm": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80,
            "description": "Trimmed before validation."
          },
          "recipientIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "maxItems": 5,
            "description": "Use an empty array for no default email notifications. Submissions remain available in the inbox."
          },
          "settings": {
            "$ref": "#/components/schemas/FormSettingsInput"
          }
        },
        "required": [
          "name",
          "recipientIds"
        ],
        "additionalProperties": false
      },
      "UpdateForm": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80,
            "description": "Trimmed before validation."
          },
          "recipientIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "maxItems": 5,
            "description": "Use an empty array for no default email notifications. Submissions remain available in the inbox."
          },
          "settings": {
            "$ref": "#/components/schemas/FormSettingsPatch"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused"
            ]
          }
        },
        "required": [],
        "additionalProperties": false,
        "minProperties": 1,
        "description": "At least one field. Settings are merged into the saved settings: send only the members you want to change, including inside uploads, and omitted members keep their current values. Recipient IDs must belong to verified addresses in this workspace."
      },
      "FormSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "publicKey": {
            "type": "string",
            "pattern": "^fk_[a-f0-9]{64}$"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused"
            ]
          },
          "settings": {
            "$ref": "#/components/schemas/FormSettings"
          },
          "recipientIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "updatedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          }
        },
        "required": [
          "id",
          "name",
          "publicKey",
          "status",
          "settings",
          "recipientIds",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "Form": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "publicKey": {
            "type": "string",
            "pattern": "^fk_[a-f0-9]{64}$"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused"
            ]
          },
          "settings": {
            "$ref": "#/components/schemas/FormSettings"
          },
          "recipientIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "updatedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "turnstile": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Turnstile"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "name",
          "publicKey",
          "status",
          "settings",
          "recipientIds",
          "createdAt",
          "updatedAt",
          "turnstile"
        ],
        "additionalProperties": false
      },
      "TurnstileInput": {
        "type": "object",
        "properties": {
          "siteKey": {
            "type": "string",
            "minLength": 10,
            "maxLength": 100,
            "pattern": "^[a-zA-Z0-9_-]+$"
          },
          "secretKey": {
            "type": "string",
            "minLength": 20,
            "maxLength": 200,
            "pattern": "^[a-zA-Z0-9_-]+$",
            "writeOnly": true,
            "description": "Required for a new widget or changed site key. Omit to keep the current widget's secret. Never returned."
          },
          "hostnames": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 253,
              "pattern": "^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$",
              "description": "Trimmed and lowercased. Exact website hostname without protocol, port or path. Duplicates are removed."
            },
            "minItems": 1,
            "maxItems": 10
          },
          "enabled": {
            "type": "boolean"
          }
        },
        "required": [
          "siteKey",
          "hostnames",
          "enabled"
        ],
        "additionalProperties": false,
        "description": "Use a customer-owned widget registered for these hostnames. Test keys, localhost and numeric hostnames are rejected outside local development. Updating clears prior verification status."
      },
      "Turnstile": {
        "type": "object",
        "properties": {
          "siteKey": {
            "type": "string"
          },
          "hostnames": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "enabled": {
            "type": "boolean"
          },
          "verifiedAt": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "description": "Unix timestamp in milliseconds."
              },
              {
                "type": "null"
              }
            ]
          },
          "updatedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          }
        },
        "required": [
          "siteKey",
          "hostnames",
          "enabled",
          "verifiedAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "Recipient": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "verified": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          }
        },
        "required": [
          "id",
          "email",
          "verified",
          "createdAt"
        ],
        "additionalProperties": false
      },
      "RecipientInput": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          }
        },
        "required": [
          "email"
        ],
        "additionalProperties": false,
        "description": "Lowercased. No display name or surrounding whitespace. Reposting an unverified address resends verification subject to cooldown."
      },
      "RecipientPending": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Recipient"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "data",
          "message"
        ],
        "additionalProperties": false
      },
      "RoutingRule": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60
          },
          "field": {
            "type": "string",
            "pattern": "^[a-zA-Z_][a-zA-Z0-9_.\\[\\]-]{0,63}$",
            "not": {
              "enum": [
                "__proto__",
                "constructor",
                "prototype",
                "access_key",
                "cf-turnstile-response",
                "_idempotency_key"
              ]
            }
          },
          "operator": {
            "type": "string",
            "enum": [
              "equals",
              "contains",
              "present"
            ]
          },
          "value": {
            "type": "string",
            "maxLength": 200,
            "default": ""
          },
          "recipientIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 5,
            "uniqueItems": true
          }
        },
        "required": [
          "id",
          "name",
          "field",
          "operator",
          "recipientIds"
        ],
        "additionalProperties": false,
        "description": "Names, match values are trimmed. equals and contains need a nonempty value; present ignores value. First match wins; matching is case-insensitive. The form's honeypot cannot be a routing field.",
        "allOf": [
          {
            "if": {
              "properties": {
                "operator": {
                  "enum": [
                    "equals",
                    "contains"
                  ]
                }
              },
              "required": [
                "operator"
              ],
              "additionalProperties": true
            },
            "then": {
              "properties": {
                "value": {
                  "type": "string",
                  "minLength": 1
                }
              },
              "required": [
                "value"
              ],
              "additionalProperties": true
            }
          }
        ]
      },
      "RoutingConfig": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "rules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoutingRule"
            },
            "maxItems": 10
          }
        },
        "required": [
          "enabled",
          "rules"
        ],
        "additionalProperties": false,
        "description": "Rule IDs must be unique. Enabling needs at least one rule. Every selected recipient must be verified and belong to the workspace.",
        "allOf": [
          {
            "if": {
              "properties": {
                "enabled": {
                  "const": true
                }
              },
              "required": [
                "enabled"
              ],
              "additionalProperties": true
            },
            "then": {
              "properties": {
                "rules": {
                  "minItems": 1
                }
              },
              "additionalProperties": true
            }
          }
        ]
      },
      "RoutingSave": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "rules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoutingRule"
            },
            "maxItems": 10
          },
          "revision": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "enabled",
          "rules",
          "revision"
        ],
        "additionalProperties": false,
        "description": "Rule IDs must be unique. Enabling needs at least one rule. Every selected recipient must be verified and belong to the workspace. Read current settings first. Send revision:null only for the first save. Stale revisions return 409.",
        "allOf": [
          {
            "if": {
              "properties": {
                "enabled": {
                  "const": true
                }
              },
              "required": [
                "enabled"
              ],
              "additionalProperties": true
            },
            "then": {
              "properties": {
                "rules": {
                  "minItems": 1
                }
              },
              "additionalProperties": true
            }
          }
        ]
      },
      "RoutingPreview": {
        "type": "object",
        "properties": {
          "config": {
            "$ref": "#/components/schemas/RoutingConfig"
          },
          "fields": {
            "$ref": "#/components/schemas/SubmissionInput"
          }
        },
        "required": [
          "config",
          "fields"
        ],
        "additionalProperties": false
      },
      "Routing": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "rules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoutingRule"
            }
          },
          "revision": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "updatedAt": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "description": "Unix timestamp in milliseconds."
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "enabled",
          "rules",
          "revision",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "NotificationPlan": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "rule",
              "default"
            ]
          },
          "reason": {
            "type": "string",
            "enum": [
              "matched",
              "no_match",
              "disabled"
            ]
          },
          "ruleId": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "ruleName": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "subject": {
            "type": "string"
          },
          "recipients": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "email": {
                  "type": "string",
                  "format": "email",
                  "maxLength": 254
                }
              },
              "required": [
                "id",
                "email"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "source",
          "reason",
          "ruleId",
          "ruleName",
          "subject",
          "recipients"
        ],
        "additionalProperties": false
      },
      "AutoresponderConfig": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "subject": {
            "type": "string",
            "minLength": 1,
            "maxLength": 150,
            "pattern": "^[^\\r\\n\\x00-\\x1f\\x7f]*$"
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 3000,
            "pattern": "^[^\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]*$"
          },
          "replyRecipientId": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "enabled",
          "subject",
          "message",
          "replyRecipientId"
        ],
        "additionalProperties": false,
        "description": "Subject and message are trimmed. Reply recipient must be verified. Enabling requires enabled Turnstile. Visitor replies also require an eligible verified submission, explicit _formkoi_autoreply=true consent, and abuse checks."
      },
      "AutoresponderSave": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "subject": {
            "type": "string",
            "minLength": 1,
            "maxLength": 150,
            "pattern": "^[^\\r\\n\\x00-\\x1f\\x7f]*$"
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 3000,
            "pattern": "^[^\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]*$"
          },
          "replyRecipientId": {
            "type": "string",
            "format": "uuid"
          },
          "revision": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "enabled",
          "subject",
          "message",
          "replyRecipientId",
          "revision"
        ],
        "additionalProperties": false,
        "description": "The same fields as the saved reply plus the current revision. Read current settings first; use revision:null for the initial save. A stale revision returns 409."
      },
      "Autoresponder": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "subject": {
            "type": "string",
            "minLength": 1,
            "maxLength": 150,
            "pattern": "^[^\\r\\n\\x00-\\x1f\\x7f]*$"
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 3000,
            "pattern": "^[^\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]*$"
          },
          "replyRecipientId": {
            "type": "string",
            "format": "uuid"
          },
          "revision": {
            "type": "string",
            "format": "uuid"
          },
          "updatedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          }
        },
        "required": [
          "enabled",
          "subject",
          "message",
          "replyRecipientId",
          "revision",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "AutoresponderPreview": {
        "type": "object",
        "properties": {
          "subject": {
            "type": "string"
          },
          "replyTo": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "text": {
            "type": "string"
          }
        },
        "required": [
          "subject",
          "replyTo",
          "text"
        ],
        "additionalProperties": false
      },
      "WebhookInput": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000,
            "format": "uri",
            "pattern": "^https://"
          },
          "enabled": {
            "type": "boolean",
            "default": false
          },
          "revision": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "url"
        ],
        "additionalProperties": false,
        "description": "Public HTTPS receiver on port 443 without userinfo or fragment. Query parameters are supported. URL is trimmed and validated again at delivery. Omit revision for creation; current revision is required to update. Destination changes cancel queued events for the old revision."
      },
      "Revision": {
        "type": "object",
        "properties": {
          "revision": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "revision"
        ],
        "additionalProperties": false
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "enabled": {
            "type": "boolean"
          },
          "revision": {
            "type": "string",
            "format": "uuid"
          },
          "updatedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          }
        },
        "required": [
          "id",
          "url",
          "enabled",
          "revision",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "WebhookCreated": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Webhook"
          },
          "signingSecret": {
            "type": "string",
            "pattern": "^whsec_",
            "description": "Shown once on creation or rotation. Store in the receiver's secret store."
          }
        },
        "required": [
          "data",
          "signingSecret"
        ],
        "additionalProperties": false
      },
      "WebhookTest": {
        "type": "object",
        "properties": {
          "deliveryId": {
            "type": "string",
            "format": "uuid"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "deliveryId",
          "message"
        ],
        "additionalProperties": false
      },
      "WebhookPayload": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/SubmissionEvent"
          },
          {
            "$ref": "#/components/schemas/TestEvent"
          }
        ]
      },
      "SubmissionEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "const": "submission.received",
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "type": "object",
            "properties": {
              "submissionId": {
                "type": "string",
                "format": "uuid"
              },
              "formId": {
                "type": "string",
                "format": "uuid"
              },
              "formName": {
                "type": "string"
              },
              "fields": {
                "type": "object",
                "additionalProperties": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  ]
                },
                "description": "Visitor values normalized to strings. Submission controls and the configured honeypot are removed."
              },
              "receivedAt": {
                "type": "string",
                "format": "date-time"
              },
              "attachments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "name": {
                      "type": "string"
                    },
                    "field": {
                      "type": "string"
                    },
                    "size": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "mediaType": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "field",
                    "size",
                    "mediaType"
                  ],
                  "additionalProperties": false
                }
              }
            },
            "required": [
              "submissionId",
              "formId",
              "formName",
              "fields",
              "receivedAt",
              "attachments"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "id",
          "type",
          "createdAt",
          "data"
        ],
        "additionalProperties": false
      },
      "TestEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "const": "webhook.test",
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "type": "object",
            "properties": {
              "formId": {
                "type": "string",
                "format": "uuid"
              },
              "formName": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "formId",
              "formName",
              "message"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "id",
          "type",
          "createdAt",
          "data"
        ],
        "additionalProperties": false
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "state": {
            "type": "string",
            "enum": [
              "pending",
              "sending",
              "delivered",
              "failed",
              "cancelled"
            ]
          },
          "attempts": {
            "type": "integer",
            "minimum": 0
          },
          "nextAttemptAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "httpStatus": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 100,
                "maximum": 599
              },
              {
                "type": "null"
              }
            ]
          },
          "errorCode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "submission.received",
              "webhook.test"
            ]
          },
          "createdAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "updatedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "destinationOrigin": {
            "type": "string"
          },
          "submissionId": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "state",
          "attempts",
          "nextAttemptAt",
          "httpStatus",
          "errorCode",
          "kind",
          "createdAt",
          "updatedAt",
          "destinationOrigin",
          "submissionId"
        ],
        "additionalProperties": false
      },
      "WebhookAttempt": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "startedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "finishedAt": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "description": "Unix timestamp in milliseconds."
              },
              {
                "type": "null"
              }
            ]
          },
          "outcome": {
            "type": "string",
            "enum": [
              "sending",
              "pending",
              "delivered",
              "failed",
              "interrupted"
            ]
          },
          "httpStatus": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "errorCode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "durationMs": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "startedAt",
          "finishedAt",
          "outcome",
          "httpStatus",
          "errorCode",
          "durationMs"
        ],
        "additionalProperties": false
      },
      "WebhookDeliveryDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "state": {
            "type": "string",
            "enum": [
              "pending",
              "sending",
              "delivered",
              "failed",
              "cancelled"
            ]
          },
          "attempts": {
            "type": "integer",
            "minimum": 0
          },
          "nextAttemptAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "httpStatus": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 100,
                "maximum": 599
              },
              {
                "type": "null"
              }
            ]
          },
          "errorCode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "payload": {
            "$ref": "#/components/schemas/WebhookPayload"
          },
          "history": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookAttempt"
            },
            "maxItems": 100
          }
        },
        "required": [
          "id",
          "state",
          "attempts",
          "nextAttemptAt",
          "httpStatus",
          "errorCode",
          "payload",
          "history"
        ],
        "additionalProperties": false
      },
      "SubmissionSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "formId": {
            "type": "string",
            "format": "uuid"
          },
          "formName": {
            "type": "string"
          },
          "senderName": {
            "type": "string"
          },
          "senderEmail": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "preview": {
            "type": "string",
            "maxLength": 180
          },
          "folder": {
            "type": "string",
            "enum": [
              "inbox",
              "archive",
              "spam"
            ]
          },
          "spamReason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "read": {
            "type": "boolean"
          },
          "receivedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "expiresAt": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "description": "Unix timestamp in milliseconds."
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "formId",
          "formName",
          "senderName",
          "senderEmail",
          "preview",
          "folder",
          "spamReason",
          "read",
          "receivedAt",
          "expiresAt"
        ],
        "additionalProperties": false
      },
      "SubmissionFields": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "formId": {
            "type": "string",
            "format": "uuid"
          },
          "formName": {
            "type": "string"
          },
          "senderName": {
            "type": "string"
          },
          "senderEmail": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "preview": {
            "type": "string",
            "maxLength": 180
          },
          "folder": {
            "type": "string",
            "enum": [
              "inbox",
              "archive",
              "spam"
            ]
          },
          "spamReason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "read": {
            "type": "boolean"
          },
          "receivedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "expiresAt": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "description": "Unix timestamp in milliseconds."
              },
              {
                "type": "null"
              }
            ]
          },
          "fields": {
            "type": "object",
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              ]
            },
            "description": "Visitor values normalized to strings. Submission controls and the configured honeypot are removed."
          },
          "notificationPlan": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/NotificationPlan"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "formId",
          "formName",
          "senderName",
          "senderEmail",
          "preview",
          "folder",
          "spamReason",
          "read",
          "receivedAt",
          "expiresAt",
          "fields",
          "notificationPlan"
        ],
        "additionalProperties": false
      },
      "Submission": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "formId": {
            "type": "string",
            "format": "uuid"
          },
          "formName": {
            "type": "string"
          },
          "senderName": {
            "type": "string"
          },
          "senderEmail": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "preview": {
            "type": "string",
            "maxLength": 180
          },
          "folder": {
            "type": "string",
            "enum": [
              "inbox",
              "archive",
              "spam"
            ]
          },
          "spamReason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "read": {
            "type": "boolean"
          },
          "receivedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "expiresAt": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "description": "Unix timestamp in milliseconds."
              },
              {
                "type": "null"
              }
            ]
          },
          "fields": {
            "type": "object",
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              ]
            },
            "description": "Visitor values normalized to strings. Submission controls and the configured honeypot are removed."
          },
          "notificationPlan": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/NotificationPlan"
              },
              {
                "type": "null"
              }
            ]
          },
          "deliveries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailDelivery"
            }
          },
          "attempts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailAttempt"
            },
            "maxItems": 100
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Attachment"
            }
          },
          "autoresponder": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "Eligibility or suppression decision, such as consent_required or eligible. Open string for future reasons."
                  }
                },
                "required": [
                  "reason"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "formId",
          "formName",
          "senderName",
          "senderEmail",
          "preview",
          "folder",
          "spamReason",
          "read",
          "receivedAt",
          "expiresAt",
          "fields",
          "notificationPlan",
          "deliveries",
          "attempts",
          "attachments",
          "autoresponder"
        ],
        "additionalProperties": false
      },
      "SubmissionUpdate": {
        "type": "object",
        "properties": {
          "folder": {
            "type": "string",
            "enum": [
              "inbox",
              "archive",
              "spam"
            ]
          },
          "read": {
            "type": "boolean"
          }
        },
        "required": [],
        "additionalProperties": false,
        "minProperties": 1,
        "description": "Restoring spam can consume allowance and queue owner notifications/webhooks. It does not send a visitor reply. Moving to spam cancels pending deliveries."
      },
      "EmailDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-f0-9-]{32,36}$"
          },
          "kind": {
            "type": "string",
            "enum": [
              "notification",
              "autoresponder"
            ]
          },
          "recipient": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "state": {
            "type": "string",
            "enum": [
              "pending",
              "sending",
              "accepted",
              "delivered",
              "deferred",
              "bounced",
              "complained",
              "failed",
              "suppressed",
              "uncertain",
              "cancelled"
            ]
          },
          "attempts": {
            "type": "integer",
            "minimum": 0
          },
          "errorCode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "updatedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          }
        },
        "required": [
          "id",
          "kind",
          "recipient",
          "state",
          "attempts",
          "errorCode",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "EmailAttempt": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "deliveryId": {
            "type": "string"
          },
          "startedAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "finishedAt": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "description": "Unix timestamp in milliseconds."
              },
              {
                "type": "null"
              }
            ]
          },
          "outcome": {
            "type": "string",
            "enum": [
              "sending",
              "pending",
              "accepted",
              "failed",
              "suppressed",
              "uncertain"
            ]
          },
          "errorCode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "deliveryId",
          "startedAt",
          "finishedAt",
          "outcome",
          "errorCode"
        ],
        "additionalProperties": false
      },
      "EmailRetry": {
        "type": "object",
        "properties": {
          "acknowledgePossibleDuplicate": {
            "type": "boolean",
            "default": false
          }
        },
        "required": [],
        "additionalProperties": false,
        "description": "Owner notifications only. Failed or uncertain deliveries can be retried after one minute if the message is outside spam. Uncertain sends require true because another copy may arrive. Visitor replies cannot be manually resent."
      },
      "Attachment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "field": {
            "type": "string"
          },
          "size": {
            "type": "integer",
            "minimum": 0
          },
          "mediaType": {
            "type": "string"
          },
          "expiresAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "available": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "name",
          "field",
          "size",
          "mediaType",
          "expiresAt",
          "available"
        ],
        "additionalProperties": false
      },
      "Usage": {
        "type": "object",
        "properties": {
          "storage": {
            "type": "object",
            "properties": {
              "bytes": {
                "type": "integer",
                "minimum": 0
              },
              "limit": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "bytes",
              "limit"
            ],
            "additionalProperties": false
          },
          "month": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}$"
          },
          "accepted": {
            "type": "integer",
            "minimum": 0
          },
          "spam": {
            "type": "integer",
            "minimum": 0
          },
          "limit": {
            "type": "integer",
            "minimum": 0
          },
          "extra": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "paused": {
                    "type": "boolean"
                  },
                  "submissions": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "accruedCents": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "capCents": {
                    "type": "integer",
                    "minimum": 0
                  }
                },
                "required": [
                  "enabled",
                  "paused",
                  "submissions",
                  "accruedCents",
                  "capCents"
                ],
                "additionalProperties": false,
                "description": "Paid extra usage on Pro: whether it is on, whether it is paused for payment or storage review, and this month's extra submissions and accrued charge against the spending cap. Null on Free."
              },
              {
                "type": "null"
              }
            ]
          },
          "folders": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "folder": {
                  "type": "string",
                  "enum": [
                    "inbox",
                    "archive",
                    "spam"
                  ]
                },
                "total": {
                  "type": "integer",
                  "minimum": 0
                },
                "unread": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "required": [
                "folder",
                "total",
                "unread"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "storage",
          "month",
          "accepted",
          "spam",
          "limit",
          "extra",
          "folders"
        ],
        "additionalProperties": false
      },
      "Token": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "forms:read",
                "forms:write",
                "submissions:read",
                "submissions:write",
                "files:read",
                "recipients:read",
                "recipients:write",
                "integrations:read",
                "integrations:write",
                "usage:read"
              ]
            }
          },
          "expiresAt": {
            "type": "integer",
            "minimum": 0,
            "description": "Unix timestamp in milliseconds."
          },
          "workspaceId": {
            "type": "string",
            "format": "uuid"
          },
          "environment": {
            "type": "string",
            "enum": [
              "local",
              "staging",
              "production"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "scopes",
          "expiresAt",
          "workspaceId",
          "environment"
        ],
        "additionalProperties": false
      }
    },
    "responses": {
      "Error": {
        "description": "Error: 400 malformed JSON; 401 invalid/expired token; 403 transport or permission; 404 unavailable resource; 409 conflicting state/revision; 413 size limit; 415 content type; 422 invalid fields; 429 limit/cooldown; 500 unexpected failure; 503 temporary dependency failure. Retry only where safe; do not blindly repeat mutations.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "string"
            },
            "description": "May be present on rate-limited responses. Some domain-specific cooldowns only provide an error message."
          },
          "X-Request-Id": {
            "schema": {
              "type": "string"
            },
            "description": "Request identifier for diagnosis."
          }
        }
      }
    }
  }
}
