Idempotent submissions
Prevent duplicate Qubeforms submissions with an idempotency key. Retry a logical form submission after network failures and understand replay behavior and retry limits.
1. Create a key for one logical submission
Send an unpredictable Idempotency-Key header, such as a UUID, with the final POST. Keep the same key for retries of the same data and attachments. Generate a new key for each intentional new submission. The key is scoped to one form, is trimmed, and is limited to 191 characters. Do not put email addresses or other personal data in it.
2. Try a repeatable request
Replace the public key and allowed Origin. Set QUBEFORMS_ATTEMPT_ID once to a fresh random UUID before the first command, then run this same command twice. On an active form without required CAPTCHA, both successful JSON responses should have the same submission_id. Do not generate a fresh UUID inside each retry.
curl --fail-with-body \
'https://api.qubeforms.io/v1/cf_pk_YOUR_KEY/submissions' \
--header 'Origin: https://www.example.com' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header "Idempotency-Key: ${QUBEFORMS_ATTEMPT_ID}" \
--data '{"email":"alex@example.com","message":"Please contact me."}'3. Understand replay behavior
When a matching stored record exists, the API returns that submission’s result with HTTP 201 for JSON responses. Reusing the key with changed fields does not update the original record and does not produce a payload-conflict error. Its returned status can reflect a later inbox status change. Keep a snapshot of the original request while its outcome is uncertain so a retry does not accidentally send edited values under the old key.
4. Handle network uncertainty
A timeout or unreadable response can occur after the server stored the submission. Keep the attempt key and retry with the same payload after any required delay, or confirm receipt in the inbox. Disable duplicate submit clicks while a request is running. After confirmed success, clear the attempt state before accepting a new submission. Native HTML forms cannot set this header; use JavaScript or a server integration when retries need it.
5. Know the limits
Replays still require an active form and an allowed origin, and each attempt consumes request-rate capacity. Honor Retry-After on 429. Deduplication depends on the original submission remaining stored; it is not a permanent guarantee after retention cleanup. Draft creation and updates do not use this header. Idempotent submission handling also does not guarantee that downstream email or webhook processing happens exactly once.
Public form keys can appear in browser code. Read keys, management credentials, and webhook signing secrets must stay on the server.