Skip to content

Error Responses

Normal browser form posts receive an HTML success or error page. When you test with curl or a server-side script, request JSON with Accept: application/json or ?format=json.

Terminal window
curl "https://html.contact/f/hc_pub_REPLACE?format=json" \
-H "Accept: application/json" \
-H "Origin: https://example.com" \
-H "Referer: https://example.com/contact" \
--data-urlencode "email=mara@example.com" \
--data-urlencode "message=Hello"

JSON errors use this shape:

{
"ok": false,
"error": {
"code": "domain_not_allowed",
"message": "This form is not allowed on this website."
}
}
StatusCodeWhat it meansHow to fix
400validation_errorThe form payload could not be parsed, a field name was too long, or spam screening rejected a link-heavy message as invalid.Check the form encoding and field names. Keep field names short and avoid spammy/link-heavy content.
400honeypot_triggeredThe honeypot field was filled.Keep _gotcha empty for real visitors. Make sure custom scripts are not populating hidden fields.
400spam_detectedServer-side spam screening rejected the message.Review the submitted content, field names, and automation behavior.
400too_many_fieldsThe submission included too many fields.Remove unnecessary inputs before submitting.
400too_many_filesMore than one non-empty attachment was submitted.Use one file input with one selected file.
400file_too_largeAn attachment exceeded 4 MB.Upload a smaller file.
400payload_too_largeThe submitted text or attachment payload was too large.Reduce field content or attachment size.
402usage_limit_reachedThe account has reached its submission usage limit.Review usage in html.contact and upgrade or wait for the next period when applicable.
403origin_missingNo usable browser source header was present, and direct server posts are not enabled for the form.Test from the deployed page, include browser-like source headers in server tests, or enable API submissions only when you intentionally need trusted server/curl posts.
403domain_not_allowedThe browser source hostname did not match the form’s allowed domains.Add the exact hostname that serves the form, such as example.com and www.example.com separately.
403form_inactiveThe form is paused or otherwise not accepting submissions.Resume the form in html.contact.
404form_not_foundThe public form key is missing or invalid.Replace the placeholder with the real hc_pub_ key from your form. For /submit, include form_key.
429rate_limitedToo many submissions arrived in the current rate-limit window.Wait and retry later. If this happens during testing, slow down repeated requests.
500attachment_store_failedThe submission was accepted, but the uploaded attachment could not be stored.Retry the submission. If it keeps happening, remove the attachment and contact support.

For JSON tests, a successful submission returns:

{
"ok": true,
"submission_id": "sub_REPLACE",
"email_status": "provider_accepted"
}

email_status may also be not_attempted when the submission was stored but email delivery was not attempted, such as when the recipient is not ready for delivery.

A successful browser post can return a 303 redirect. html.contact considers submitted _redirect first, then the form’s Redirect URL setting.

If the chosen redirect URL is unsafe, html.contact returns the normal success response instead of redirecting.

This page focuses on public form submissions. Private API routes use the same general JSON error shape, but private API authentication, scopes, and endpoint-specific responses are documented in the Private API docs.