Docs

Quickstart

  1. Sign in (email link or GitHub — no passwords) and create a form. You get an endpoint like https://formreply.dev/f/ax3k9pz.
  2. Paste it as your form's action:
<form action="https://formreply.dev/f/YOUR_FORM_ID" method="POST">
  <input name="email" type="email" placeholder="you@site.com">
  <textarea name="message"></textarea>
  <button type="submit">Send</button>
</form>

Classic posts get a 302 redirect to your configured thank-you URL (set it in form settings, or pass a _next hidden field). Submissions show up in your inbox instantly.

AJAX / fetch

Send FormData or JSON with an Accept: application/json header and you'll get JSON back instead of a redirect:

const res = await fetch('https://formreply.dev/f/YOUR_FORM_ID', {
  method: 'POST',
  headers: { 'Accept': 'application/json' },
  body: new FormData(form),
});
const { ok, id } = await res.json();  // { "ok": true, "id": "sub_…" }

JSON body works too (Content-Type: application/json). CORS: lock your form to your domains with allowed domains in settings — entries like example.com, *.example.com, or *. Empty list = any origin.

Special fields (Formspree-compatible)

FieldEffect
_replytoSubmitter's email — used for reply-to on notifications and for the auto-reply.
_subjectOverrides the notification email subject.
_nextRedirect URL for classic posts (overrides the stored thank-you URL).
_gotchaHoneypot. Add it as a hidden input — bots fill it and are filed to spam silently (no notification sent).
cf-turnstile-responseCloudflare Turnstile token — verified when you configure a secret in spam settings.

A plain email field is detected as the reply-to too. Everything else is stored verbatim in the submission.

Auto-reply

Enable auto-reply in form settings and every submission that includes an email gets an instant response. Subject and body support {field} placeholders filled from the submitted data — {name}, {email}, anything. Free sends from formreply.dev; Pro lets you use your own from-address.

Webhooks

Pro forms can register a generic webhook. On each submission we POST a signed JSON payload with up to 3 retries on failure:

POST https://your.endpoint/hook
X-FormReply-Signature: t=1698000000,v1=<hmac-sha256>
Content-Type: application/json

{
  "event": "submission.created",
  "form_id": "ax3k9pz",
  "submission": {
    "id": "sub_…",
    "created_at": "2026-10-24 08:00:00",
    "email": "visitor@site.com",
    "data": { "name": "…", "message": "…" }
  }
}

Verify v1 as HMAC-SHA256 of `${t}.${rawBody}` with your webhook secret. Slack webhooks post a formatted message to your incoming-webhook URL.

Rate limits & spam

Per-IP (default 20/hour) and per-form (default 300/hour) limits return 429 when exceeded — tune them in spam settings. Spam (honeypot, disposable domain, failed Turnstile) is stored in the spam folder for 7 days, never silently deleted.

File uploads

Pro and Team plans accept multipart/form-data file inputs — 10 MB per file, 25 MB total per submission. Files are stored in R2 and downloadable only via short-lived signed links from the inbox.