splitforms.com

Submission Responses and Error Codes

Maintained by the SplitForms team · Updated

Send Accept: application/json when calling SplitForms with fetch. Check both the HTTP status and success value, then use code to identify a documented failure. A 429 rate_limited response needs a pause; a 429 quota_reached response needs a plan or allowance check. A 200 response alone does not prove inbox delivery.

Request a JSON response

Native HTML posts can navigate to a thank-you page or return a readable error page. JavaScript integrations should request JSON explicitly. The usual successful response contains success: true and message: "Submission received". File accounting, a note or a validated redirect can be included when applicable.

Some internal failures use a general message without a code. Handle that case rather than assuming code is always present. Preserve the visitor’s entries after a failure so they can correct a field or try again.

const response = await fetch("https://splitforms.com/api/submit", {
  method: "POST",
  headers: { Accept: "application/json" },
  body: new FormData(form),
});
const result = await response.json();
if (!response.ok || result.success !== true) {
  throw new Error(result.message || "Could not submit the form");
}
// Show a receipt message; inspect result.note for upload warnings.

References: SplitForms API reference

Submission error reference

These statuses and codes describe the public /api/submit endpoint. Account APIs and MCP authenticate differently; their 401 responses are not evidence that a public form key needs to be kept on your server.

Submission error reference
HTTP / codeMeaningNext step
400 missing_access_keyNo form key in the bodyAdd a hidden access_key input, or use /f/YOUR_ACCESS_KEY.
400 invalid_bodyMalformed or unsupported body shapeSend a JSON object or valid form encoding.
404 invalid_access_keyThe form key was not foundCopy the form’s current key, not an MCP or account token.
403 inactive_formThe owner paused the formRe-enable it in the dashboard.
403 origin_not_allowedStrict origin protection rejected the siteAdd the intended production domain to Allowed Domains.
403 form_unavailableThe form is not accepting submissionsContact support if this is unexpected.
413 payload_too_largeRequest exceeds the body limitReduce attachments and check individual file limits.
415 unsupported_content_typeUnsupported request encodingUse JSON, URL-encoded or multipart data.
429 rate_limitedToo many requests in a short windowPause; do not retry in a tight loop.
429 quota_reachedAccount submission allowance exhaustedCheck quota information and billing.
500 profile_lookup_failed or general failureA server-side operation failedKeep the input and check the dashboard before retrying.

References: SplitForms API reference

Why a 200 response may not produce an email

Spam gates may return a generic success response without saving a lead or sending email. This prevents bots from learning which check rejected a request. Do not use automated production submissions as an uptime probe: they can trigger filtering and notifications.

For a legitimate missing lead, inspect the dashboard and Spam view, the allowed domain, verification setup and the actual request payload. For a saved lead with no email, inspect notification recipients and delivery settings. Submission acceptance and email delivery are separate steps.

References: Submission lifecycle and delivery checks

Handle an uncertain network result carefully

A timeout means the browser did not receive a response; it does not prove the server failed to save the submission. Blindly resending can create duplicates. Keep the visitor’s form data, display a useful message and reconcile against the dashboard when diagnosing a failure.

Disable the submit button only while the request is pending, restore it on failure, and show a visible status message. For background workflows, use your own job identifier to deduplicate downstream actions. Do not assume this public endpoint implements an Idempotency-Key header.

References: Duplicate submission guide

Frequently asked questions

Is every 429 a monthly limit?

No. rate_limited is a request-frequency limit. quota_reached is the account’s submission allowance; Free uses a total allowance rather than a monthly reset.

Should fetch use mode: no-cors?

No. An opaque response prevents your code from inspecting success and error details. Use the endpoint’s normal CORS support and request JSON.