Insane Forms

Server-side submits

Send Submissions from your own server with a Submit Key.

When your server sends the Submission instead of the visitor's browser (a Next.js server action, a PHP handler, a queue worker), send a Submit Key with it. A Submit Key belongs to one Project and can only create Submissions.

Get a Submit Key

Submit Keys will be created from the Project's API keys screen in the dashboard, which is coming soon. Keys start with if_. Keep yours on the server, in an environment variable, and never ship it to the browser.

Send it

Put the key in the Authorization header as a Bearer token. Add the visitor's IP address in X-Visitor-IP:

A Next.js server action:

The same request with curl:

A successful request answers 201 {"ok": true, "id": "..."}, the same as a browser submit. The other errors in the JavaScript fetch table apply too.

What a Submit Key changes

With a valid Submit Key:

  • The origin check is skipped. A server has no browser origin, so the Form's Allowed Origins don't apply.
  • X-Visitor-IP is used. The rate limits count the visitor's address instead of your server's.
  • Direct upload requests to /f/YOUR_FORM_ID/uploads accept the key too.

Turnstile still applies. If the Form uses it, forward the visitor's cf-turnstile-response field in the body.

Gotchas

  • Without X-Visitor-IP, the limits count your server's address. A server relaying every visitor then shares the limit of 10 requests a minute, so pass the visitor's address whenever you have it. The header has to hold a valid IPv4 or IPv6 address, or it's ignored. The IP is never stored.
  • A request without a Submit Key counts as a browser submit: its X-Visitor-IP is ignored and Allowed Origins apply.
  • A key that is unknown, switched off, expired, belongs to another Project or isn't a Submit Key gets 403 invalid_submit_key. So does a malformed Authorization header, such as Basic … or a Bearer header with no token.
  • A revoked key can keep working for up to a minute, because key lookups are cached for 60 seconds. Unknown keys are cached the same way.
  • Browsers can't send these headers to the endpoint: its CORS answer allows only Content-Type. Send from a server.

On this page