Forms, updated
Submit API and fields
The submit API is one endpoint: POST https://formthunder.com/submit, or POST https://formthunder.com/submit/{formId} with the key in the path. It accepts JSON, URL-encoded and multipart bodies, CORS is open, and the field names match Web3Forms. Any field that isn't reserved is forwarded as-is, and a field's name is its label in the email.
Request
curl -X POST https://formthunder.com/submit \
-H "Content-Type: application/json" \
-d '{"access_key":"YOUR_ACCESS_KEY","name":"Priya","email":"priya@example.com","message":"Hello"}'The access key is the form's ID. It's public by design, because it can only send to recipients you've verified.
Reserved fields
| Field | What it does |
|---|---|
access_key | Identifies the form. Required unless the ID is in the URL. |
subject | Email subject. Overrides the form's setting. |
from_name | Sender name shown in the inbox. |
replyto | Reply-to address. |
email | The visitor's address. Stored as the sender and used for replies and the autoresponder. |
ccemail | CC addresses, comma-separated. They must be verified linked emails. Pro. |
redirect | Absolute URL to send a plain HTML form post to. |
botcheck | Honeypot. Any value other than false or off marks the submission as spam. |
webhook | HTTPS URL to post this one submission to. Pro. |
attachment | Files, or upload IDs from the uploader. Pro. |
h-captcha-response | hCaptcha token. |
cf-turnstile-response | Turnstile token. Pro. |
g-recaptcha-response, recaptcha_response | reCAPTCHA token. Pro. |
preheader | Preview text in the email. |
A field name ending in [] is treated as a list, so colors[] arrives as colors.
Response
A JSON or fetch request gets JSON back.
{
"success": true,
"message": "Your message was sent.",
"submission_id": "8f14e45f-...",
"body": { "data": { "name": "Priya", "message": "Hello" }, "message": "..." }
}A plain HTML form post gets a 303 to redirect, or to the default success page. If it fails, the 303 goes to /submit/error with the reason. A failed JSON request gets success: false, a message and sometimes a hint. A successful one may also carry warnings, for things like ignored files.
Status codes
| Code | Meaning | What to do |
|---|---|---|
| 200 | Stored. Deliveries are queued. | Nothing. |
| 303 | Stored. Redirecting a plain form post. | Nothing. |
| 400 | Bad request: missing key, bad JSON, failed captcha. | Read message. |
| 403 | The form is paused, or the origin isn't on its allowed domains. | Add the domain or resume the form. |
| 413 | Too large. | Bodies stop at 6 MB and direct files at 5 MB. Use the uploader. |
| 429 | Over 30 requests a minute from this IP to this form. | Wait a minute. |
| 503 | We couldn't store it. Sent with Retry-After. | Retry after that many seconds. |
Limits
A submission can hold up to 100 fields, and each value up to 50,000 characters. Longer values are trimmed.
What happens next
The submission and its delivery jobs are written to Postgres in one transaction before you get a success reply. A background worker then sends the email and any webhooks or chat messages, and retries failures for up to 24 hours. See how that's built.