Skip to main content
The capture endpoint is a documented HTTP contract, not only something the allGood script talks to. Use this when you’re building the request yourself. For an ordinary web page, prefer the script — it handles the honeypot, the bot widget, field checks and double submissions for you.

The request

There is no API key and no authorization header here. The form id is a public identifier; the origin allowlist is the control.

The body

Send whatever your form collects. There’s no fixed schema at the endpoint — a field the form definition doesn’t know about is still stored rather than rejected. Three keys have special meaning: And one is ignored if you send it: consentTextId. allGood deletes it and substitutes the form’s own bound value from its own records, so the consent evidence can’t be forged from the page. Everything else is stored as sent.

Size limit

Your account setting, 8 KB by default, and never more than 16 KB whatever the setting says. Measured in bytes, not characters. Both the declared length and the real length are checked.

The order of checks

Checks stop at the first failure, so exactly one outcome describes a submission and it names the first thing that was wrong.
Note where check 1 sits. A refused origin gets a bare 403 with no CORS headers, so a browser sees an opaque network error rather than a readable body — it cannot tell “not allowlisted” apart from “network down”. Use the runtime config endpoint to find out, or read the console warning the script writes.

Preflight

A cross-origin JSON POST is never a simple request, so the browser always sends OPTIONS first. The origin is echoed exactly, never * — the path is credentialed, and * is invalid with credentials.

Responses

redirectUrl is present only when the form configures one and it passed the safety check. This endpoint never returns consent_missing. See Reason codes.

Retries

Accepted responses carry a submissionId, and everything downstream deduplicates on it. Retrying the same HTTP request mints a new one, so a retry does create a second record. Guard against double submission on your side, as the script does.

Rate limits

Event capture has separate budgets. A caller with no Origin header — a server — is covered by the per-IP budget only.

Posting from a server

You can. There’s no origin to check, so the allowlist doesn’t apply and the per-IP budget is the limit. Be aware that bot protection needs a browser-minted token, so a server-side caller is effectively unauthenticated — put your own rate limiting and validation in front of it.