Rate limits and spam protection

60/60s per (tenant, ip), body size, allowed websites, Turnstile

Each (tenant, IP) pair gets 60 requests per 60 seconds using a fixed window. Exceed that and you get a 429 with a Retry-After header.

IPv4 addresses are truncated to /24 and IPv6 to /48 before they enter the rate limiter, so a NAT or shared network doesn't unfairly penalize a single user.

Spam protection

  • Body size. Requests over 64 KB are refused with 413 PAYLOAD_TOO_LARGE.
  • Wrong keys. An address that sends 10 wrong API keys is refused with 429 for about a minute. Valid keys are never counted.
  • Allowed websites. List your sites on the endpoint. Browser submissions from any other site, and requests that do not say where they came from, get 403 ORIGIN_NOT_ALLOWED. Leave the list empty for server-to-server calls.
  • Cloudflare Turnstile. Paste your own Turnstile secret key (free at Cloudflare) on the endpoint and add the widget to your form. Each submission must then carry the solved token in cf-turnstile-response or the x-turnstile-token header, or it gets 403 CAPTCHA_FAILED.
  • Honeypot. A hidden website field that people leave empty. Bots that fill it get a fake success and nothing is stored.
  • Confirmation emails. One address gets at most 3 confirmation emails a day from your workspace, and invalid addresses get none.
  • Plan email limits. Each plan has a daily and a monthly email ceiling, and all workspaces share one sending capacity. When either is reached, the email is held, and the submission is still saved and shown in your dashboard.