{
  "openapi": "3.1.0",
  "info": {
    "title": "PulseFormCreator forms API",
    "version": "v1",
    "summary": "Create, change, publish and fill forms, read responses and analytics, and manage webhooks.",
    "description": "The PulseFormCreator forms API creates, changes, publishes and deletes forms (validated by the editor’s own schema), posts responses through the same pipeline a respondent uses, and reads responses, unfinished responses and analytics. A new form is a draft and an edit to a published form is a pending draft: nothing respondents see changes until POST /forms/{id}/publish/. AI assistants reach the same account through a remote MCP server at /api/mcp/. It is free on every plan, with a rate limit of 100 requests per 60 seconds per key. Every path ends in a slash; a path without one gets a 308 redirect. Guide: https://www.pulseformcreator.com/developers/api/",
    "contact": {
      "name": "PulseFormCreator",
      "url": "https://www.pulseformcreator.com/contact/"
    },
    "termsOfService": "https://www.pulseformcreator.com/terms/"
  },
  "externalDocs": {
    "description": "Forms API guide",
    "url": "https://www.pulseformcreator.com/developers/api/"
  },
  "servers": [
    {
      "url": "https://www.pulseformcreator.com/api/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "The key and the account behind it."
    },
    {
      "name": "Forms",
      "description": "Forms the key can read and, with a read and write key, create, change, publish and delete (polls are not part of v1)."
    },
    {
      "name": "Responses",
      "description": "Submitted and unfinished responses to one form, and posting a response."
    },
    {
      "name": "Webhooks",
      "description": "The same webhooks as a form’s Workflows tab."
    }
  ],
  "paths": {
    "/me/": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getMe",
        "summary": "The account and key behind the API key",
        "description": "Use it to check that a key works.",
        "responses": {
          "200": {
            "description": "The account and the key.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Me"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/forms/": {
      "get": {
        "tags": [
          "Forms"
        ],
        "operationId": "listForms",
        "summary": "List forms, newest first",
        "description": "Your own forms and the forms of every team workspace you belong to, each with the role you have there.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Only forms with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "published",
                "closed"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Items per page, 1 to 100 (default 50).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "The `pagination.nextCursor` of the previous page, unchanged. Keep the other parameters the same between pages.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of forms.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FormListItem"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "tags": [
          "Forms"
        ],
        "operationId": "createForm",
        "summary": "Create a form",
        "description": "Validated by the editor’s own schema, with the editor’s new-form look and settings as the base. The form is born a draft: it has a link but does not take responses until `POST /forms/{id}/publish/`. Blocks may omit `id`, options may be plain strings. Needs a read and write key.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FormWrite"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The form was created (a draft).",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Form"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/forms/{id}/": {
      "get": {
        "tags": [
          "Forms"
        ],
        "operationId": "getForm",
        "summary": "Get one form and its definition",
        "description": "The PUBLISHED definition by default; `draft=1` lays the pending edits over it. `staging` says whether edits are waiting.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "draft",
            "in": "query",
            "description": "Pass `1` to read the pending edits.",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The form.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Form"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "tags": [
          "Forms"
        ],
        "operationId": "updateForm",
        "summary": "Change a form",
        "description": "Send any of `title`, `description`, `questions` (replaces the whole list), `theme` (replaces), `settings` (merged key by key; `null` removes one). On a published form the change is saved as a pending draft and the response shows it; respondents see nothing new until `POST /forms/{id}/publish/`. A password setting is never taken from the API. Needs a read and write key and a role that can edit the form.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FormWrite"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The form with the change applied (the draft view).",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Form"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Forms"
        ],
        "operationId": "deleteForm",
        "summary": "Delete a form",
        "description": "Deletes the form, its responses and uploaded files. This cannot be undone. Needs a read and write key and a role that can delete forms (owner, admin, editor).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The form was deleted.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Deleted"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/forms/{id}/publish/": {
      "post": {
        "tags": [
          "Forms"
        ],
        "operationId": "publishForm",
        "summary": "Publish a form or its pending edits",
        "description": "The editor’s Publish and Publish changes: the same logic check (422 `logic_issues` lists each problem and nothing is published), a version entry, the live link reloaded. The content is screened before this answers: a form that trips the abuse screen is paused and the answer is 403 `moderation_hold`. A form that is already paused cannot be published. Needs a read and write key and a role that can edit the form.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The form is live; `staging.pending` is false.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Form"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/LogicIssues"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/forms/{id}/discard/": {
      "post": {
        "tags": [
          "Forms"
        ],
        "operationId": "discardForm",
        "summary": "Discard pending edits",
        "description": "Throws the pending edits away; the form is exactly what is published. Needs a read and write key and a role that can edit the form.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The published form.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Form"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/forms/{id}/analytics/": {
      "get": {
        "tags": [
          "Forms"
        ],
        "operationId": "getFormAnalytics",
        "summary": "A form’s numbers over a range",
        "description": "Views, starts, completions, responses, unfinished responses, completion and start rate, median completion time and a per-day series. No device or source breakdown. Free plans read the last 7 days (`clamped` says so). Spam is not counted.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "since",
            "in": "query",
            "description": "Start of the range (inclusive): an ISO 8601 date-time or a YYYY-MM-DD date (UTC). Default 30 days ago.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "until",
            "in": "query",
            "description": "End of the range (exclusive): an ISO 8601 date-time, or a date that includes that whole day.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The numbers.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Analytics"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/forms/{id}/responses/": {
      "get": {
        "tags": [
          "Responses"
        ],
        "operationId": "listResponses",
        "summary": "List responses to a form",
        "description": "Newest first by default. To sync, keep the `submittedAt` of the newest response you have and ask for `since` that time with `order=asc`, or add a webhook.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort by submission time.",
            "schema": {
              "type": "string",
              "enum": [
                "desc",
                "asc"
              ],
              "default": "desc"
            }
          },
          {
            "name": "since",
            "in": "query",
            "description": "Only responses submitted at or after this time: an ISO 8601 date-time, or a YYYY-MM-DD date (UTC).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "until",
            "in": "query",
            "description": "Only responses submitted before this time. A plain YYYY-MM-DD date includes that whole day.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Items per page, 1 to 100 (default 50).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "The `pagination.nextCursor` of the previous page, unchanged. Keep the other parameters the same between pages.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of responses.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Response"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "tags": [
          "Responses"
        ],
        "operationId": "createResponse",
        "summary": "Post a response",
        "description": "Runs through the same pipeline as a respondent’s submit: logic replayed on the server, every answer normalized and validated, response cap, field duplicates, option limits, schedule, quiz grading, then webhooks, Sheets, email and workflows. The form must be published. The caller is your server, so captcha, password, honeypot, minimum-time and once-per-browser rules do not apply; no IP address or user agent is stored and `metadata.source` is `api`. Answers are keyed by question id or named key. An `Idempotency-Key` makes a retry safe: the same key and content returns the stored response (200, `Idempotent-Replayed: true`); the same key with other content is 422 `idempotency_conflict`. A form with a timer records the limit unverified (an API call has no clock to vouch for). Needs a read and write key and a role that can manage responses.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 255 visible characters, one per post you want made once. Scoped to the key and the form.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResponseCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "This Idempotency-Key was already used with the same content: the stored response.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Response"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "The response was stored.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Response"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Conflict"
          },
          "423": {
            "$ref": "#/components/responses/Closed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/forms/{id}/partials/": {
      "get": {
        "tags": [
          "Responses"
        ],
        "operationId": "listPartials",
        "summary": "List unfinished responses to a form",
        "description": "People who started the form and did not submit, latest activity first. Each has `status: \"partial\"`, a `sessionId` and the question they stopped on. The response that completes one carries the same `sessionId`. Free plans read the last 7 days.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort by last activity.",
            "schema": {
              "type": "string",
              "enum": [
                "desc",
                "asc"
              ],
              "default": "desc"
            }
          },
          {
            "name": "since",
            "in": "query",
            "description": "Only partials with activity at or after this time: an ISO 8601 date-time, or a YYYY-MM-DD date (UTC).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "until",
            "in": "query",
            "description": "Only partials with activity before this time.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Items per page, 1 to 100 (default 50).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "The `pagination.nextCursor` of the previous page, unchanged. Keep the other parameters the same between pages.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of unfinished responses.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Partial"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/forms/{id}/responses/{responseId}/": {
      "get": {
        "tags": [
          "Responses"
        ],
        "operationId": "getResponse",
        "summary": "Get one response",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "responseId",
            "in": "path",
            "required": true,
            "description": "The response id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The response.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Response"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Responses"
        ],
        "operationId": "deleteResponse",
        "summary": "Delete one response",
        "description": "Deletes the response, its uploaded files and the visit linked to it. This cannot be undone. Needs a read and write key.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "responseId",
            "in": "path",
            "required": true,
            "description": "The response id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The response was deleted.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Deleted"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/forms/{id}/webhooks/": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "listWebhooks",
        "summary": "List a form’s webhooks",
        "description": "Each with the result of its latest delivery. Secrets are never returned.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The form’s webhooks (not paginated).",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "createWebhook",
        "summary": "Add a webhook to a form",
        "description": "Each new response is POSTed to the URL as JSON, signed unless `signing` is false. Private and local addresses are refused. Needs a read and write key. The signing secret is returned once, here.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The webhook was added.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WebhookCreated"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/forms/{id}/webhooks/{webhookId}/": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "getWebhook",
        "summary": "Get one webhook",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "description": "The webhook id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "deleteWebhook",
        "summary": "Remove a webhook",
        "description": "Removes the webhook and its delivery log. Needs a read and write key.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The form id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "description": "The webhook id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook was removed.",
            "headers": {
              "X-API-Version": {
                "$ref": "#/components/headers/X-API-Version"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Deleted"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    }
  },
  "webhooks": {
    "formResponse": {
      "post": {
        "summary": "FORM_RESPONSE: a new response, delivered to your webhook URL",
        "description": "Sent for every stored response, wherever it came from (the runner, the live plane, or `POST /forms/{id}/responses/`). If the form had an unfinished record for this visitor, `data.sessionId` is the same as on the FORM_RESPONSE_PARTIAL that preceded it. Signed webhooks carry `PulseFormCreator-Timestamp` (Unix seconds) and `PulseFormCreator-Signature` (`sha256=` + the hex HMAC-SHA256 of `{timestamp}.{raw body}`, keyed with the signing secret). Reject timestamps more than five minutes old. Answer 2xx within 10 seconds; timeouts, 408, 429 and 5xx are retried. Fields carry the permanent question id as `key` and the named key, when there is one, as `fieldKey`; `data.values` (only when a question has a named key) repeats the values by name. Renaming a key changes `fieldKey` and a `values` property name from the next delivery on, and never `key`, so a receiver that reads ids is never broken by a rename.",
        "parameters": [
          {
            "name": "PulseFormCreator-Timestamp",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PulseFormCreator-Signature",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^sha256=[0-9a-f]{64}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookPayload"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx status acknowledges the delivery."
          }
        }
      }
    },
    "formResponseUpdated": {
      "post": {
        "summary": "FORM_RESPONSE_UPDATED: a response was edited",
        "description": "Sent when a respondent edits their response through its edit link, or the owner edits it. `data.edit` says what changed. Same shape and headers as FORM_RESPONSE.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookPayload"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx status acknowledges the delivery."
          }
        }
      }
    },
    "formResponsePartial": {
      "post": {
        "summary": "FORM_RESPONSE_PARTIAL: someone left the form unfinished",
        "description": "Sent when a visitor leaves with answers and does not submit, to every destination that accepts the unfinished trigger. `data.status` is `partial`, `data.sessionId` is the visitor’s session and `data.lastQuestion` where they stopped. The response that completes it is a FORM_RESPONSE with the same `data.sessionId`. Same shape and headers as FORM_RESPONSE.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookPayload"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx status acknowledges the delivery."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "pfc_live_…",
        "description": "An API key from Account › API keys, sent as `Authorization: Bearer pfc_live_…`. Read keys can list and read; read and write keys can also create, change, publish and delete forms, post and delete responses, and add or remove webhooks. An account can hold 20 active keys. Call the API from a server: it sends no CORS headers."
      }
    },
    "headers": {
      "X-API-Version": {
        "description": "Always `v1` for this version.",
        "schema": {
          "type": "string",
          "const": "v1"
        }
      },
      "X-RateLimit-Limit": {
        "description": "Requests allowed per window, per key.",
        "schema": {
          "type": "integer",
          "const": 100
        }
      }
    },
    "responses": {
      "InvalidRequest": {
        "description": "`invalid_request`: a parameter or the body is wrong. The message says which.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "`unauthorized`: no key, a malformed key, or a revoked key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "headers": {
          "WWW-Authenticate": {
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "Forbidden": {
        "description": "`insufficient_scope` (a read-only key tried to change something) or `forbidden` (your role in that workspace does not allow it).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "`not_found`: the form, response or webhook does not exist, or the key cannot see it. The API never confirms that an id exists.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "`method_not_allowed`: the path exists, but not with that method.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "headers": {
          "Allow": {
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "RateLimited": {
        "description": "`rate_limited`: more than 100 requests in 60 seconds on this key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            }
          }
        }
      },
      "InternalError": {
        "description": "`internal_error`: our fault. Retry with backoff.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Conflict": {
        "description": "`conflict` (the form changed while saving: read it again and retry), `not_published` (publish the form first), `already_responded` or `option_full` (a duplicate or a full option; `error.errors` names it), or `idempotency_conflict` (the key was used with other content).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "LogicIssues": {
        "description": "`logic_issues`: the form would be broken; `error.issues` lists each problem as one sentence. Nothing was published.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Closed": {
        "description": "`limit_reached` (the response cap is full) or `form_closed` (closed, or outside its schedule).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "status",
              "code",
              "message"
            ],
            "properties": {
              "status": {
                "type": "integer",
                "description": "The same as the HTTP status."
              },
              "code": {
                "type": "string",
                "enum": [
                  "invalid_request",
                  "unauthorized",
                  "forbidden",
                  "insufficient_scope",
                  "not_found",
                  "method_not_allowed",
                  "rate_limited",
                  "internal_error",
                  "conflict",
                  "not_published",
                  "logic_issues",
                  "moderation_hold",
                  "already_responded",
                  "option_full",
                  "limit_reached",
                  "form_closed",
                  "idempotency_conflict"
                ]
              },
              "message": {
                "type": "string"
              },
              "issues": {
                "type": "array",
                "description": "`invalid_request` on a form write (a dotted `path` and a sentence), `logic_issues` on publish (a sentence and the `blockId` it is on).",
                "items": {
                  "type": "object",
                  "properties": {
                    "path": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "id": {
                      "type": "string"
                    },
                    "blockId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              },
              "errors": {
                "type": "array",
                "description": "A response that was not accepted: one entry per question.",
                "items": {
                  "type": "object",
                  "required": [
                    "questionId",
                    "message"
                  ],
                  "properties": {
                    "questionId": {
                      "type": "string"
                    },
                    "key": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "Pagination": {
        "type": "object",
        "required": [
          "limit",
          "hasMore",
          "nextCursor"
        ],
        "properties": {
          "limit": {
            "type": "integer"
          },
          "hasMore": {
            "type": "boolean"
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass back as `cursor` for the next page; null on the last page."
          }
        }
      },
      "Me": {
        "type": "object",
        "required": [
          "user",
          "key"
        ],
        "properties": {
          "user": {
            "type": "object",
            "required": [
              "id",
              "email"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "key": {
            "type": "object",
            "required": [
              "id",
              "scopes"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "read",
                    "write"
                  ]
                }
              }
            }
          }
        }
      },
      "FormSummary": {
        "type": "object",
        "required": [
          "id",
          "title",
          "status",
          "url",
          "anonymous",
          "questionCount",
          "createdAt",
          "updatedAt",
          "publishedAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published",
              "closed"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The public link; null while the form is a draft."
          },
          "anonymous": {
            "type": "boolean",
            "description": "True when the form uses anonymous mode."
          },
          "questionCount": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "publishedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "FormListItem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FormSummary"
          },
          {
            "type": "object",
            "required": [
              "role"
            ],
            "properties": {
              "role": {
                "type": "string",
                "enum": [
                  "owner",
                  "admin",
                  "editor",
                  "builder",
                  "viewer"
                ],
                "description": "Your role in the workspace that owns the form."
              }
            }
          }
        ]
      },
      "QuestionSummary": {
        "type": "object",
        "required": [
          "id",
          "type",
          "label",
          "required"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The permanent id this question’s answers use in `answers` and `fields[].key`."
          },
          "key": {
            "type": "string",
            "description": "The question’s named key (`email`), when it has one. Unique in the form; may be renamed at any time."
          },
          "type": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          },
          "options": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "label"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Form": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FormSummary"
          },
          {
            "type": "object",
            "required": [
              "description",
              "questions",
              "hiddenFields",
              "variables",
              "blocks"
            ],
            "properties": {
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "questions": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/QuestionSummary"
                },
                "description": "One entry per question, in form order (layout blocks left out)."
              },
              "hiddenFields": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "name",
                    "label"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    }
                  }
                }
              },
              "variables": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "id",
                    "name",
                    "type"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string"
                    }
                  }
                }
              },
              "blocks": {
                "type": "array",
                "items": {
                  "type": "object"
                },
                "description": "The full definition: every block, including layout, logic and endings."
              },
              "theme": {
                "type": "object",
                "additionalProperties": true
              },
              "settings": {
                "type": "object",
                "additionalProperties": true,
                "description": "The form’s settings. A password is never returned."
              },
              "responseCount": {
                "type": "integer"
              },
              "staging": {
                "type": "object",
                "description": "Staged publishing: `pending` is true while edits wait for `POST /forms/{id}/publish/`.",
                "properties": {
                  "pending": {
                    "type": "boolean"
                  },
                  "changes": {
                    "type": "integer"
                  }
                }
              },
              "held": {
                "type": "boolean",
                "description": "True while the form is paused for review and cannot be published."
              }
            }
          }
        ]
      },
      "Field": {
        "type": "object",
        "description": "The same shape as a webhook payload’s `data.fields[]`.",
        "required": [
          "key",
          "label",
          "type",
          "value",
          "displayValue"
        ],
        "properties": {
          "key": {
            "type": "string",
            "description": "A question id, `hidden:<name>` or `var:<id>`. Permanent: it never changes when a question is renamed or given a key."
          },
          "fieldKey": {
            "type": "string",
            "description": "The question’s named key, when it has one. Read this for a readable name; read `key` for one that never changes."
          },
          "label": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "description": "The question type, or `hidden_field` / `calculated_field`."
          },
          "value": {
            "description": "The stored value: option ids, arrays, objects or file references."
          },
          "displayValue": {
            "type": "string",
            "description": "Readable text: option labels, joined lists, file links."
          }
        }
      },
      "Partial": {
        "type": "object",
        "required": [
          "id",
          "sessionId",
          "formId",
          "status",
          "lastActivityAt",
          "fields",
          "answers"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The session id."
          },
          "sessionId": {
            "type": "string",
            "description": "The same id on the response that completes this one."
          },
          "formId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "partial"
            ]
          },
          "lastQuestion": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "label": {
                "type": "string"
              }
            }
          },
          "progress": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "page": {
                "type": "integer"
              },
              "of": {
                "type": "integer"
              }
            }
          },
          "startedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "lastActivityAt": {
            "type": "string",
            "format": "date-time"
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          },
          "answers": {
            "type": "object",
            "additionalProperties": true
          },
          "device": {
            "type": [
              "string",
              "null"
            ],
            "description": "Left out for anonymous forms."
          },
          "browser": {
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Response": {
        "type": "object",
        "required": [
          "id",
          "formId",
          "submittedAt",
          "fields",
          "answers",
          "values",
          "hidden",
          "variables",
          "endingId",
          "number",
          "status",
          "note",
          "metadata"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "formId": {
            "type": "string",
            "format": "uuid"
          },
          "submittedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          },
          "answers": {
            "type": "object",
            "additionalProperties": true,
            "description": "Stored answers keyed by question id. Each stored file gets a `url` that works for an hour."
          },
          "values": {
            "type": "object",
            "additionalProperties": true,
            "description": "The same values by named key, the id where a question has no key. A rename changes a property name here; `answers` and `fields[].key` never change."
          },
          "hidden": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "variables": {
            "type": "object",
            "additionalProperties": true
          },
          "endingId": {
            "type": [
              "string",
              "null"
            ]
          },
          "number": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The response number within the form (#1042). Stable; never reused."
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "done"
            ]
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "description": "The owner’s private note."
          },
          "metadata": {
            "type": "object",
            "required": [
              "startedAt",
              "durationMs",
              "source"
            ],
            "properties": {
              "startedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "durationMs": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "source": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "`api` for a response posted through the API, `tally_import` for one imported from Tally; otherwise null."
              },
              "edits": {
                "type": "integer",
                "description": "How many times the response was edited."
              },
              "editedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "ipHash": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "A one-way hash. Left out on anonymous forms."
              },
              "userAgent": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Left out on anonymous forms."
              },
              "sessionId": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Left out on anonymous forms."
              }
            }
          }
        }
      },
      "FormWrite": {
        "type": "object",
        "description": "The body of POST /forms/ and PATCH /forms/{id}/. Validated by the editor’s own schema (`surveyDraftSchema`). Any other field is a 400.",
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 200
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2000
          },
          "questions": {
            "type": "array",
            "maxItems": 500,
            "description": "Blocks, as `GET /forms/{id}/` returns them. `id` may be left out (one is made); an option, row, column or item may be a plain string. A rating without `scale` has 5 points. Each question may carry `key`: lowercase letters, digits and underscores, starting with a letter, at most 40, unique in the form, not another question’s id or a hidden field’s name.",
            "items": {
              "type": "object",
              "required": [
                "type"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "key": {
                  "type": "string",
                  "pattern": "^[a-z][a-z0-9_]{0,39}$"
                },
                "type": {
                  "type": "string"
                },
                "title": {
                  "type": "string"
                }
              },
              "additionalProperties": true
            }
          },
          "theme": {
            "type": "object",
            "additionalProperties": true
          },
          "settings": {
            "type": "object",
            "additionalProperties": true,
            "description": "Merged key by key onto the stored settings; `null` removes a key. Password protection is never taken from the API."
          }
        },
        "additionalProperties": false
      },
      "ResponseCreate": {
        "type": "object",
        "required": [
          "answers"
        ],
        "description": "The body of POST /forms/{id}/responses/. Values are the stored shapes `GET` returns (option ids, arrays, objects). Any other field is a 400.",
        "properties": {
          "answers": {
            "type": "object",
            "additionalProperties": true,
            "description": "Question id or named key to value."
          },
          "hidden": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Hidden field values by name (only the form’s declared names are kept)."
          },
          "language": {
            "type": "string",
            "description": "The language the answers are in (`meta.language`). Ignored when the form does not offer it."
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          },
          "timeZone": {
            "type": "string",
            "description": "An IANA zone, for TODAY() and AGE() in formulas."
          },
          "pageTimes": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            }
          }
        },
        "additionalProperties": false
      },
      "Analytics": {
        "type": "object",
        "required": [
          "formId",
          "range",
          "clamped",
          "views",
          "starts",
          "completions",
          "responses",
          "partials",
          "completionRate",
          "startRate",
          "medianDurationMs",
          "series",
          "truncated"
        ],
        "properties": {
          "formId": {
            "type": "string",
            "format": "uuid"
          },
          "range": {
            "type": "object",
            "properties": {
              "since": {
                "type": "string",
                "format": "date-time"
              },
              "until": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          },
          "clamped": {
            "type": "boolean",
            "description": "True when the Free plan’s 7-day window shortened the range."
          },
          "views": {
            "type": "integer"
          },
          "starts": {
            "type": "integer"
          },
          "completions": {
            "type": "integer"
          },
          "responses": {
            "type": "integer",
            "description": "Responses stored in the range, spam left out."
          },
          "partials": {
            "type": "integer",
            "description": "Started and not finished."
          },
          "completionRate": {
            "type": [
              "number",
              "null"
            ],
            "description": "completions / starts."
          },
          "startRate": {
            "type": [
              "number",
              "null"
            ],
            "description": "starts / views."
          },
          "medianDurationMs": {
            "type": [
              "integer",
              "null"
            ]
          },
          "series": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "date",
                "responses"
              ],
              "properties": {
                "date": {
                  "type": "string",
                  "format": "date"
                },
                "responses": {
                  "type": "integer"
                }
              }
            }
          },
          "truncated": {
            "type": "boolean",
            "description": "True when more than 10,000 responses fall in the range: `series` and the median cover the newest."
          }
        }
      },
      "Deleted": {
        "type": "object",
        "required": [
          "id",
          "deleted"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "deleted": {
            "type": "boolean",
            "const": true
          }
        }
      },
      "Webhook": {
        "type": "object",
        "required": [
          "id",
          "formId",
          "name",
          "enabled",
          "url",
          "signing",
          "secretHint",
          "createdAt",
          "updatedAt",
          "lastDelivery"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "formId": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "signing": {
            "type": "boolean"
          },
          "secretHint": {
            "type": [
              "string",
              "null"
            ],
            "description": "Enough to recognize the secret (`whsec_…a1b2`), never the secret."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastDelivery": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "status",
              "httpStatus",
              "error",
              "createdAt"
            ],
            "properties": {
              "status": {
                "type": "string"
              },
              "httpStatus": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "error": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "WebhookCreate": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The https address to POST to."
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 80
          },
          "signing": {
            "type": "boolean",
            "default": true
          },
          "enabled": {
            "type": "boolean",
            "default": true
          }
        }
      },
      "WebhookCreated": {
        "type": "object",
        "required": [
          "webhook",
          "signingSecret"
        ],
        "properties": {
          "webhook": {
            "$ref": "#/components/schemas/Webhook"
          },
          "signingSecret": {
            "type": [
              "string",
              "null"
            ],
            "description": "Shown once. Store it where your receiver can read it."
          }
        }
      },
      "WebhookPayload": {
        "type": "object",
        "required": [
          "eventId",
          "eventType",
          "createdAt",
          "data"
        ],
        "properties": {
          "eventId": {
            "type": "string"
          },
          "eventType": {
            "type": "string",
            "enum": [
              "FORM_RESPONSE",
              "FORM_RESPONSE_UPDATED",
              "FORM_RESPONSE_PARTIAL"
            ],
            "description": "FORM_RESPONSE_UPDATED is sent when a response is edited; data.edit says what changed. FORM_RESPONSE_PARTIAL is an unfinished form (data.status is partial); the response that completes it is a FORM_RESPONSE with the same data.sessionId."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "type": "object",
            "required": [
              "responseId",
              "submissionId",
              "surveyId",
              "surveyTitle",
              "fields",
              "hidden",
              "variables",
              "endingId"
            ],
            "properties": {
              "responseId": {
                "type": "string"
              },
              "submissionId": {
                "type": "string"
              },
              "values": {
                "type": "object",
                "additionalProperties": true,
                "description": "Only when a question has a named key: the question values by key (the id where a question has none)."
              },
              "number": {
                "type": "integer",
                "description": "The response number within the form (#1042)."
              },
              "language": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The language the respondent answered in."
              },
              "durationMs": {
                "type": "integer",
                "description": "Time from start to submit."
              },
              "surveyId": {
                "type": "string",
                "description": "The form id."
              },
              "surveyTitle": {
                "type": "string"
              },
              "surveyUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "createdAt": {
                "type": "string",
                "format": "date-time"
              },
              "fields": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Field"
                }
              },
              "hidden": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              },
              "variables": {
                "type": "object",
                "additionalProperties": true
              },
              "endingId": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "pdfUrl": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "A signed link to this response as a PDF, valid for 7 days."
              },
              "status": {
                "type": "string",
                "enum": [
                  "open",
                  "done",
                  "partial"
                ],
                "description": "`open` on a new response, `partial` on an unfinished form."
              },
              "sessionId": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The runner session. On a partial it is also the responseId; on the response that completes it, the same value."
              },
              "lastQuestion": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "Partial only: where they stopped.",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "label": {
                    "type": "string"
                  }
                }
              },
              "note": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The owner’s private note; null on a new response."
              }
            }
          }
        }
      }
    }
  }
}