{
  "openapi": "3.1.0",
  "info": {
    "title": "AI Form API API",
    "version": "0.1.0",
    "summary": "Forms your AI agent can create, share and read.",
    "description": "Create forms, share a public link, read responses as JSON or CSV, get a webhook per response.\n\nEvery public form can also be filled by the visitor's own AI agent (fill codes, /v1/fill, or the fill MCP).\n\nRequest bodies are limited to 64 KB. Rate-limited endpoints send RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset; 429 adds Retry-After.\n\nFree plan: 30 requests/min and 1000/day per API key, 3 open forms, 100 responses per month.\n\nField types: short_text, long_text, email, number, url, phone, single_choice, multi_choice, checkbox, date, rating. At most 50 fields per form. Fill codes live 60 minutes."
  },
  "servers": [
    {
      "url": "https://aiformapi.com"
    }
  ],
  "tags": [
    {
      "name": "Account"
    },
    {
      "name": "Forms"
    },
    {
      "name": "Responses"
    },
    {
      "name": "Webhooks"
    },
    {
      "name": "Public",
      "description": "No API key. Used by form pages and anyone with a form link."
    },
    {
      "name": "Agent fill",
      "description": "Let a person's own AI agent fill a public form."
    }
  ],
  "paths": {
    "/v1/signup": {
      "post": {
        "operationId": "signup",
        "summary": "Send a sign-in link",
        "description": "Sends a magic link to the address. The link signs in to the dashboard, which shows the first API key once. The answer is the same for known and unknown addresses.",
        "tags": [
          "Account"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignupInput"
              }
            }
          }
        },
        "security": [],
        "responses": {
          "202": {
            "description": "Link sent (or the address is ignored)",
            "headers": {},
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignupSent"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden`: 403. Not allowed (for example agent fill is off, or the human check failed).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed`: 422 (400 for malformed JSON). The request is not valid. details.errors lists path and message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`service_unavailable`: 503. A required service (for example email) is not available.\n`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/forms": {
      "post": {
        "operationId": "createForm",
        "summary": "Create a form",
        "description": "Creates an open form and returns its public URL. Free plan: 3 open forms. Fields asking for passwords, codes, card or account numbers, and passport or national ID numbers are rejected with 422 blocked_field.",
        "tags": [
          "Forms"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FormInput"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "description": "Form created",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Form"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: 401. Missing, malformed or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`quota_exceeded`: 403. A plan limit is reached (open forms, responses per month, webhooks).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large`: 413. The body is larger than 64 KB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed`: 422 (400 for malformed JSON). The request is not valid. details.errors lists path and message.\n`blocked_field`: 422. A field asks for a password, code, card or account number, or a passport or national ID number. details.fields lists them.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listForms",
        "summary": "List your forms",
        "description": "Newest first, cursor pagination.",
        "tags": [
          "Forms"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, 1 to 100 (default 20)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "next_cursor from the previous page",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "A page of forms",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormList"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: 401. Missing, malformed or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed`: 422 (400 for malformed JSON). The request is not valid. details.errors lists path and message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/forms/{id}": {
      "get": {
        "operationId": "getForm",
        "summary": "Read a form",
        "tags": [
          "Forms"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The form with its webhooks (secrets are never returned again)",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Form"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: 401. Missing, malformed or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateForm",
        "summary": "Change title, description, fields or settings",
        "description": "Send only what changes. fields replaces the whole list. settings merges key by key and null removes a key.",
        "tags": [
          "Forms"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FormPatch"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The updated form",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Form"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: 401. Missing, malformed or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed`: 422 (400 for malformed JSON). The request is not valid. details.errors lists path and message.\n`blocked_field`: 422. A field asks for a password, code, card or account number, or a passport or national ID number. details.fields lists them.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteForm",
        "summary": "Delete a form and all its responses",
        "tags": [
          "Forms"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: 401. Missing, malformed or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/forms/{id}/close": {
      "post": {
        "operationId": "closeForm",
        "summary": "Stop accepting responses",
        "tags": [
          "Forms"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The closed form",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Form"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: 401. Missing, malformed or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/forms/{id}/reopen": {
      "post": {
        "operationId": "reopenForm",
        "summary": "Accept responses again",
        "description": "Counts against the open-form quota like a new form.",
        "tags": [
          "Forms"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The reopened form",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Form"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: 401. Missing, malformed or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`quota_exceeded`: 403. A plan limit is reached (open forms, responses per month, webhooks).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/forms/{id}/responses": {
      "get": {
        "operationId": "listResponses",
        "summary": "Read responses as JSON or CSV",
        "description": "Oldest first by default. CSV has one column per field id, then response_id, source, submitted_at. When more rows exist the CSV response carries an X-Next-Cursor header.",
        "tags": [
          "Responses"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (default) or csv",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "description": "Only responses after this ISO 8601 time",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "JSON: 1 to 1000 (default 100). CSV: 1 to 10000 (default 10000)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10000
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "next_cursor from the previous page",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "description": "asc (default) or desc",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "A page of responses (JSON) or a CSV file",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseList"
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: 401. Missing, malformed or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed`: 422 (400 for malformed JSON). The request is not valid. details.errors lists path and message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/forms/{id}/responses/{response_id}": {
      "get": {
        "operationId": "getResponse",
        "summary": "Read one response",
        "tags": [
          "Responses"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "response_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The response",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseObject"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: 401. Missing, malformed or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/forms/{id}/webhooks": {
      "post": {
        "operationId": "addWebhook",
        "summary": "Call a URL for each new response",
        "description": "POST {event:\"response.created\", form_id, response} with header X-AIFormAPI-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, t + \".\" + body)>. 5 s timeout, 1 retry. At most 3 per form. The secret is returned once.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookInput"
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "description": "Webhook added",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCreated"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: 401. Missing, malformed or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`quota_exceeded`: 403. A plan limit is reached (open forms, responses per month, webhooks).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed`: 422 (400 for malformed JSON). The request is not valid. details.errors lists path and message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/forms/{id}/webhooks/{webhook_id}": {
      "delete": {
        "operationId": "deleteWebhook",
        "summary": "Remove a webhook",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Removed",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: 401. Missing, malformed or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Plan, limits and current usage",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Usage",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: 401. Missing, malformed or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/forms/{slug}": {
      "get": {
        "operationId": "getPublicForm",
        "summary": "Public form schema",
        "description": "No owner data. Per IP: 60 per minute.",
        "tags": [
          "Public"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "The public form",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicForm"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/forms/{slug}/responses": {
      "post": {
        "operationId": "submitResponse",
        "summary": "Submit a response as a person",
        "description": "Per IP: 5 per minute and 30 per hour. Per form: 60 per minute. When Turnstile is on, send turnstile_token.",
        "tags": [
          "Public"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HumanSubmitInput"
              }
            }
          }
        },
        "security": [],
        "responses": {
          "201": {
            "description": "Stored",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Receipt"
                }
              }
            }
          },
          "403": {
            "description": "`quota_exceeded`: 403. A plan limit is reached (open forms, responses per month, webhooks).\n`forbidden`: 403. Not allowed (for example agent fill is off, or the human check failed).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`form_closed`: 409. The form is closed, past its closing time or at its response limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large`: 413. The body is larger than 64 KB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_answers`: 422. Answers do not match the form. details.fields lists id and problem.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/forms/{slug}/fill-tokens": {
      "post": {
        "operationId": "mintFillToken",
        "summary": "Get a fill code and prompt for an AI agent",
        "description": "Returns a single-use code (valid 60 minutes, 5 POST attempts) and the ready-to-paste prompt. Per IP: 5 per minute and 30 per day. Per form: 200 per day.",
        "tags": [
          "Agent fill"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FillTokenMintInput"
              }
            }
          }
        },
        "security": [],
        "responses": {
          "201": {
            "description": "Token minted",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FillTokenMinted"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden`: 403. Not allowed (for example agent fill is off, or the human check failed).\n`quota_exceeded`: 403. A plan limit is reached (open forms, responses per month, webhooks).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`form_closed`: 409. The form is closed, past its closing time or at its response limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/fill/{token}": {
      "get": {
        "operationId": "getFillForm",
        "summary": "Read the form and instructions for a fill code",
        "description": "For agents that can only GET. Does not use up the code. 30 per hour per code.",
        "tags": [
          "Agent fill"
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Schema and instructions",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FillForm"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "`token_expired`: 410. The fill code expired or used up its attempts.\n`token_used`: 410. The fill code was already used.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "submitFill",
        "summary": "Submit answers with a fill code",
        "description": "One successful use per code. At most 5 POST attempts: the 6th gets 410 token_expired with details.reason \"max_attempts\". Per IP: 10 per minute.",
        "tags": [
          "Agent fill"
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FillSubmitInput"
              }
            }
          }
        },
        "security": [],
        "responses": {
          "201": {
            "description": "Stored",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Receipt"
                }
              }
            }
          },
          "403": {
            "description": "`quota_exceeded`: 403. A plan limit is reached (open forms, responses per month, webhooks).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`form_closed`: 409. The form is closed, past its closing time or at its response limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "`token_expired`: 410. The fill code expired or used up its attempts.\n`token_used`: 410. The fill code was already used.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_answers`: 422. Answers do not match the form. details.fields lists id and problem.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/abuse-reports": {
      "post": {
        "operationId": "reportAbuse",
        "summary": "Report a form",
        "tags": [
          "Public"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AbuseReportInput"
              }
            }
          }
        },
        "security": [],
        "responses": {
          "201": {
            "description": "Report stored",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AbuseReceived"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: 404. The resource does not exist or belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`validation_failed`: 422 (400 for malformed JSON). The request is not valid. details.errors lists path and message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: 429. Too many requests. Wait Retry-After seconds.",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds to wait",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`rate_limiter_unavailable`: 503. The rate limiter is not available, so the endpoint is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Authorization: Bearer afk_<32 letters and digits>"
      }
    },
    "schemas": {
      "Field": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 40,
            "pattern": "^[a-z][a-z0-9_]*$",
            "description": "Unique snake_case id, at most 40 characters. It is the key in answers and the CSV column name."
          },
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "type": {
            "type": "string",
            "enum": [
              "short_text",
              "long_text",
              "email",
              "number",
              "url",
              "phone",
              "single_choice",
              "multi_choice",
              "checkbox",
              "date",
              "rating"
            ]
          },
          "required": {
            "type": "boolean"
          },
          "help": {
            "type": "string",
            "maxLength": 500
          },
          "options": {
            "description": "Required for single_choice and multi_choice (2 to 50 distinct options). Not allowed for other types.",
            "maxItems": 50,
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          "min": {
            "description": "number: smallest value. rating: lowest score (default 1). multi_choice: fewest choices.",
            "type": "number",
            "minimum": -1000000000000000,
            "maximum": 1000000000000000
          },
          "max": {
            "description": "number: largest value. rating: highest score (default 5, at most 10). multi_choice: most choices.",
            "type": "number",
            "minimum": -1000000000000000,
            "maximum": 1000000000000000
          },
          "max_length": {
            "description": "short_text and long_text only. Cannot exceed 500 (short_text) or 5,000 (long_text).",
            "type": "integer",
            "minimum": 1,
            "maximum": 5000
          }
        },
        "required": [
          "id",
          "label",
          "type"
        ],
        "additionalProperties": false
      },
      "FormSettings": {
        "type": "object",
        "properties": {
          "agent_fill": {
            "description": "Show the agent-fill card on the public form. Default true.",
            "type": "boolean"
          },
          "close_at": {
            "description": "The form stops accepting responses at this time. null clears it.",
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "max_responses": {
            "description": "The form closes after this many responses. null clears it.",
            "anyOf": [
              {
                "type": "integer",
                "minimum": 1,
                "maximum": 1000000
              },
              {
                "type": "null"
              }
            ]
          },
          "confirmation_message": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ]
          },
          "notify_email": {
            "description": "Email the account owner for each new response. Default false.",
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "FormInput": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ]
          },
          "fields": {
            "minItems": 1,
            "maxItems": 50,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          },
          "settings": {
            "$ref": "#/components/schemas/FormSettings"
          }
        },
        "required": [
          "title",
          "fields"
        ],
        "additionalProperties": false
      },
      "FormPatch": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ]
          },
          "fields": {
            "minItems": 1,
            "maxItems": 50,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          },
          "settings": {
            "$ref": "#/components/schemas/FormSettings"
          }
        },
        "additionalProperties": false
      },
      "SignupInput": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 254
          },
          "turnstile_token": {
            "type": "string",
            "maxLength": 4096
          }
        },
        "required": [
          "email"
        ],
        "additionalProperties": false
      },
      "HumanSubmitInput": {
        "type": "object",
        "properties": {
          "answers": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {}
          },
          "source": {
            "description": "Use paste when the answers came from a pasted agent block. Default human.",
            "type": "string",
            "enum": [
              "human",
              "paste"
            ]
          },
          "turnstile_token": {
            "type": "string",
            "maxLength": 4096
          }
        },
        "required": [
          "answers"
        ],
        "additionalProperties": false
      },
      "FillTokenMintInput": {
        "type": "object",
        "properties": {
          "turnstile_token": {
            "type": "string",
            "maxLength": 4096
          }
        },
        "additionalProperties": false
      },
      "FillSubmitInput": {
        "type": "object",
        "properties": {
          "answers": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {}
          }
        },
        "required": [
          "answers"
        ],
        "additionalProperties": false
      },
      "WebhookInput": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000
          }
        },
        "required": [
          "url"
        ],
        "additionalProperties": false
      },
      "AbuseReportInput": {
        "type": "object",
        "properties": {
          "form": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "reason": {
            "type": "string",
            "enum": [
              "phishing",
              "spam",
              "illegal",
              "other"
            ]
          },
          "details": {
            "type": "string",
            "maxLength": 2000
          },
          "contact_email": {
            "type": "string",
            "maxLength": 254
          },
          "turnstile_token": {
            "type": "string",
            "maxLength": 4096
          }
        },
        "required": [
          "form",
          "reason"
        ],
        "additionalProperties": false
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "unauthorized",
                  "forbidden",
                  "not_found",
                  "validation_failed",
                  "blocked_field",
                  "invalid_answers",
                  "form_closed",
                  "quota_exceeded",
                  "rate_limited",
                  "token_expired",
                  "token_used",
                  "payload_too_large",
                  "rate_limiter_unavailable",
                  "service_unavailable",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string",
                "description": "Plain-language explanation"
              },
              "details": {
                "description": "Extra data. For 422 invalid_answers: {fields:[{id, problem}]}. For validation_failed: {errors:[{path, message}]}."
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "Form": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Form id, frm_..."
          },
          "slug": {
            "type": "string",
            "description": "Public slug used in the form URL"
          },
          "public_url": {
            "type": "string",
            "description": "Share this link",
            "format": "uri"
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "closed"
            ]
          },
          "accepting": {
            "type": "boolean",
            "description": "false when closed, past close_at or at max_responses"
          },
          "closed_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "closed",
              "expired",
              "limit_reached",
              "quota_full",
              null
            ]
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          },
          "settings": {
            "type": "object",
            "properties": {
              "agent_fill": {
                "type": "boolean"
              },
              "close_at": {
                "type": "string",
                "description": "Closing time (UTC)",
                "format": "date-time"
              },
              "max_responses": {
                "type": "integer",
                "minimum": 1
              },
              "confirmation_message": {
                "type": "string"
              },
              "notify_email": {
                "type": "boolean"
              }
            },
            "required": [
              "agent_fill",
              "notify_email"
            ]
          },
          "response_count": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "webhooks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "last_status": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "HTTP status of the last delivery, 0 for a network error"
                },
                "last_error": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "last_attempt_at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                }
              },
              "required": [
                "id",
                "url",
                "last_status",
                "last_error",
                "last_attempt_at",
                "created_at"
              ]
            },
            "description": "Only in GET /v1/forms/{id}"
          }
        },
        "required": [
          "id",
          "slug",
          "public_url",
          "status",
          "title",
          "fields",
          "settings",
          "response_count",
          "created_at"
        ]
      },
      "FormList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Form"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "data",
          "next_cursor"
        ]
      },
      "ResponseObject": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "rsp_..."
          },
          "form_id": {
            "type": "string"
          },
          "answers": {
            "type": "object",
            "additionalProperties": true,
            "description": "Field id to value"
          },
          "source": {
            "type": "string",
            "enum": [
              "human",
              "paste",
              "agent_api",
              "agent_mcp"
            ]
          },
          "submitted_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "form_id",
          "answers",
          "source",
          "submitted_at"
        ]
      },
      "ResponseList": {
        "type": "object",
        "description": "JSON format. With format=csv the body is text/csv instead.",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResponseObject"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "data",
          "next_cursor"
        ]
      },
      "Receipt": {
        "type": "object",
        "properties": {
          "response_id": {
            "type": "string"
          },
          "receipt": {
            "type": "string",
            "description": "Human-readable receipt such as AF-7K3Q-9XMD. Tell the person this."
          },
          "submitted_at": {
            "type": "string",
            "format": "date-time"
          },
          "confirmation_message": {
            "type": "string",
            "description": "Only for human submits, when the form has one"
          }
        },
        "required": [
          "response_id",
          "receipt",
          "submitted_at"
        ]
      },
      "Deleted": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "deleted": {
            "type": "boolean",
            "const": true
          }
        },
        "required": [
          "id",
          "deleted"
        ]
      },
      "WebhookCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "secret": {
            "type": "string",
            "description": "Shown once. Use it to verify X-AIFormAPI-Signature."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "url",
          "secret",
          "created_at"
        ]
      },
      "Usage": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string",
            "enum": [
              "free",
              "pro"
            ]
          },
          "limits": {
            "type": "object",
            "properties": {
              "requests_per_minute": {
                "type": "integer"
              },
              "requests_per_day": {
                "type": "integer"
              },
              "open_forms": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "null = unlimited"
              },
              "responses_per_month": {
                "type": "integer"
              }
            }
          },
          "usage": {
            "type": "object",
            "properties": {
              "open_forms": {
                "type": "integer"
              },
              "responses_this_month": {
                "type": "integer"
              },
              "month": {
                "type": "string",
                "description": "UTC calendar month, YYYY-MM"
              },
              "resets_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        },
        "required": [
          "plan",
          "limits",
          "usage"
        ]
      },
      "PublicForm": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          },
          "settings": {
            "type": "object",
            "properties": {
              "agent_fill": {
                "type": "boolean"
              },
              "confirmation_message": {
                "type": "string"
              }
            },
            "required": [
              "agent_fill"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "closed"
            ]
          },
          "accepting": {
            "type": "boolean"
          },
          "closed_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "closed",
              "expired",
              "limit_reached",
              "quota_full",
              null
            ]
          }
        },
        "required": [
          "id",
          "slug",
          "title",
          "fields",
          "settings",
          "status",
          "accepting"
        ]
      },
      "FillTokenMinted": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "Single-use fill code, fil_..."
          },
          "fill_url": {
            "type": "string",
            "description": "POST answers here",
            "format": "uri"
          },
          "prompt": {
            "type": "string",
            "description": "Full prompt to give to an AI agent"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "form_id": {
            "type": "string",
            "description": "Id of the form the code belongs to"
          }
        },
        "required": [
          "token",
          "fill_url",
          "prompt",
          "expires_at",
          "form_id"
        ]
      },
      "FillForm": {
        "type": "object",
        "properties": {
          "form": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "fields": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Field"
                }
              }
            }
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "attempts_left": {
            "type": "integer"
          },
          "instructions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "submit": {
            "type": "object",
            "properties": {
              "method": {
                "type": "string"
              },
              "url": {
                "type": "string"
              },
              "content_type": {
                "type": "string"
              },
              "body_example": {
                "type": "object"
              }
            }
          }
        },
        "required": [
          "form",
          "expires_at",
          "attempts_left",
          "instructions",
          "submit"
        ]
      },
      "SignupSent": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "const": "sent"
          },
          "message": {
            "type": "string"
          },
          "dev_link": {
            "type": "string",
            "description": "Only outside production"
          }
        },
        "required": [
          "status",
          "message"
        ]
      },
      "AbuseReceived": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "const": "received"
          }
        },
        "required": [
          "id",
          "status"
        ]
      }
    }
  }
}