Receive signed form webhooks

Verify signatures, deduplicate deliveries and handle retries.

Reviewed October 22, 2026

Configure the destination

Use a public HTTPS endpoint in the form destination controls. Keep the generated signing secret private when it is shown. Select and map the intended fields. Subscriber destinations require explicit visitor opt-in. Test with fictional submissions before collecting real information.

Verify the raw request

Deliveries POST JSON with an event ID, type form.submitted, version, page/block IDs and submission fields. Headers include Capybara-Event-Id, Idempotency-Key and Capybara-Signature: t=UNIX_SECONDS,v1=HEX_SIGNATURE. Compute HMAC-SHA256 over timestamp + "." + raw_request_body using the UTF-8 signing secret. Compare in constant time and reject timestamps outside a short tolerance. Do not parse and reserialize the body before verification.

Acknowledge and deduplicate

Deduplicate by stable event ID, persist the accepted event and return a 2xx response. Redirects are not followed. Delivery is at least once: transient failures, 408 and 429 can retry with exponential backoff, with up to five automatic attempts. A repeated delivery must not repeat your external side effect.

Retention and failure handling

Check delivery status in the app and retry failed deliveries only after fixing the cause. Expired/deleted responses are not sent. Disconnecting a destination removes its pending jobs but cannot recall an in-flight request. Payloads exclude visitor IP addresses and user agents; submitted answers may still contain personal data.