Submit API
One endpoint receives every submission:
POST https://api.formwire.io/submitRequest formats
Section titled “Request formats”The endpoint accepts three body encodings; pick whichever your stack produces:
| Content-Type | Typical source |
|---|---|
application/x-www-form-urlencoded | plain HTML <form> posts |
multipart/form-data | forms with enctype set (required for file uploads) |
application/json | fetch / axios / server-side calls |
Every request must include your access_key (as a hidden field or JSON property). All other fields are yours: any named value becomes part of the stored submission and the notification email. Fields starting with an underscore are reserved.
CORS is handled: preflights succeed and JSON responses are readable from browser fetch.
Success
Section titled “Success”{ "success": true, "message": "Submission received", "id": "sub_...", "update_token": "..."}ididentifies the stored submission.update_tokenlets the same client amend that submission (for example, multi-step forms updating one record).
Two variations:
- Redirect: if the request is a regular form post and includes an allowlisted
_redirectURL, the response is a302to that URL instead of JSON. - Spam: submissions caught by spam checks receive a generic
{"success": true, "message": "Submission received"}with noidorupdate_token. Bots are not told they were filtered.
Updating a submission
Section titled “Updating a submission”A successful create returns an update_token. To amend that submission later — multi-step forms, “save progress”, abandoned-cart capture — POST to the same endpoint with the id and token instead of creating a new record:
{ "access_key": "YOUR-KEY", "_submission_id": "sub_...", "_update_token": "...", "phone": "+1 555 0100"}- Fields are merged into the stored data — new keys are added, existing keys overwritten — so you only send what changed.
- Files can be attached on an update too (same
multipart/form-datarules as file uploads). - Captcha is a one-time gate at first submit, so updates skip it; rate limits still apply.
- The response returns the same
idandupdate_token, so you can keep updating.
Add _notify=1 to the final update to deliver the completed submission — it sends the notification email, auto-reply and webhooks once (and meters it once). A typical flow: create the record silently on step 1, update as the user progresses, then finalize with _notify=1. Delivery only fires if the original submission is itself deliverable (not spam or a preview).
Update errors: 403 Invalid submission id or update token, 404 Submission not found.
Errors
Section titled “Errors”All errors share one shape: {"success": false, "message": "..."}.
| Status | Message | Meaning |
|---|---|---|
400 | Invalid request body | Body could not be parsed in any accepted format |
400 | access_key is required | No key in the request |
403 | Invalid access_key | Key is malformed |
403 | Invalid or disabled access_key | Key does not exist or the form is disabled |
403 | Submissions are not allowed from this domain | The form has domain rules and the request origin is not on the allowlist |
403 | Captcha verification failed | A captcha provider is enabled and the token failed server-side verification |
403 | Invalid submission id or update token | An update referenced a submission that is not yours |
404 | Submission not found | Update targeted a submission that no longer exists |
413 | Payload too large | Body exceeds the size limit |
429 | Too many submissions, please slow down | Rate limit hit; retry after a pause |
503 | Temporarily unavailable, please retry / Could not record submission, please retry | Transient storage issue; safe to retry |
Handle 429 and 503 with a retry; treat 4xx as a bug in the integration.
Delivery guarantees
Section titled “Delivery guarantees”Every accepted submission is stored durably before the API acknowledges it. Email delivery then runs asynchronously with retries; you can see per-submission delivery status in the dashboard. A crash or mail-provider hiccup cannot lose an acknowledged submission.