{
  "name": "HoneyForms",
  "description": "Form backend for static sites. Create a working endpoint with one unauthenticated request.",
  "documentation": "/llms.txt",
  "operations": [
    {
      "id": "create_endpoint",
      "description": "Create a form endpoint. No authentication required.",
      "method": "POST",
      "path": "/v1/endpoints",
      "body": {
        "email": "string, required — where submissions are delivered",
        "name": "string, optional — label shown in the notification"
      },
      "returns": [
        "endpoint_id",
        "access_key",
        "submit_url",
        "read_token",
        "snippet",
        "email_verified",
        "terms"
      ],
      "rate_limit": "5 per hour, 20 per day, per IP",
      "notes": "Submissions are stored immediately. Email delivery begins after the human clicks the confirmation link. The request itself accepts the Terms of Service, which incorporate the Privacy Policy and the DPA by reference; the returned `terms` object carries the version and the three URLs, and the acceptance is recorded against the account."
    },
    {
      "id": "submit",
      "description": "Submit a form. This is the URL that goes in the HTML form action.",
      "method": "POST",
      "path": "/s/{access_key}",
      "content_types": ["application/x-www-form-urlencoded", "application/json"],
      "reserved_fields": ["redirect", "_next", "subject", "from_name", "reply_to", "cc", "botcheck"],
      "notes": "The first real submission locks the endpoint to its origin domain. `_next` is an alias for `redirect`. If the owner turned Turnstile on for this endpoint, a `cf-turnstile-response` token from the widget is required and the request answers 403 without one; it is off by default."
    },
    {
      "id": "request_sign_in_link",
      "description": "Email the account owner a single-use link that signs them in. There is no password, and you cannot sign in on their behalf.",
      "method": "POST",
      "path": "/login",
      "content_types": ["application/x-www-form-urlencoded"],
      "body": {
        "email": "string, required — the address the account was created with"
      },
      "rate_limit": "10 per hour per IP, 5 per hour per address",
      "notes": "The response is identical whether or not the address has an account, so it cannot be used to test which addresses are registered. The link expires in 15 minutes, works once, and confirms the address if it was not confirmed yet. The confirmation link sent at creation signs the user in too."
    },
    {
      "id": "list_submissions",
      "description": "Read stored submissions for one endpoint.",
      "method": "GET",
      "path": "/v1/endpoints/{endpoint_id}/submissions",
      "auth": "Bearer read_token",
      "query": {
        "limit": "integer, optional — how many, newest first. Default 100, max 5000.",
        "format": "string, optional — 'json' (default) or 'csv'."
      },
      "notes": "The read_token is scoped to a single endpoint, is read-only and expires. It grants access to third-party personal data — never commit it. In CSV, values starting with =, +, -, @, tab or CR are prefixed with an apostrophe so spreadsheets do not execute them; the JSON format is unaltered."
    }
  ],
  "limits": {
    "free_submissions_per_month": 500,
    "submissions_per_month_before_email_confirmed": 50,
    "body_bytes": 262144,
    "over_limit": "Submissions are still accepted and stored; email delivery is held and everything held is delivered in one digest when the month resets (1st, UTC) or the account upgrades. The endpoint always answers 200/303 — the form never breaks for the visitor and nothing is lost.",
    "read_submissions": "Available on every plan, including free.",
    "account": "The account is the email address: a second endpoint created with the same address joins the same account and shares its monthly quota."
  },
  "terms": {
    "version": "2026-09-02",
    "url": "/terms",
    "privacy_url": "/privacy",
    "dpa_url": "/dpa",
    "acceptable_use_url": "/acceptable-use",
    "report_abuse_url": "/report-abuse",
    "accepted_by": "Creating an endpoint. There is no checkbox, no signature and no account to create first.",
    "recorded": "Every creation writes a dated acceptance record against the account, carrying the version above.",
    "dpa": "Published and incorporated into the Terms by reference; it needs no signature. Your user is the controller of the submitted data and we are the processor.",
    "tell_the_user": "Creating the key accepted the Terms, which incorporate the Privacy Policy and the Data Processing Agreement."
  },
  "credentials": {
    "access_key": {
      "public": true,
      "placement": "HTML form action",
      "protection": "domain locking"
    },
    "read_token": {
      "public": false,
      "placement": "server-side only",
      "warning": "Reads personal data submitted by third parties. Do not commit or expose in client code."
    }
  }
}
