Webhook Best Practices for Reliable Form Delivery
With a webhook form, your endpoint is the destination for a response. That gives you control over where it lives, but it also makes your receiver's behavior part of the user's form experience. Here is a short checklist to test before sending real submissions.
Verify the signed headers
SingleForm sends X-SingleForm-Signature, X-SingleForm-Timestamp, X-SingleForm-Nonce, and X-SingleForm-Form-Id when submission authentication is available. The HMAC-SHA256 signature covers {formId}.{timestamp}.{nonce} with your webhook secret. It does not cover the request body. Use HTTPS for transport integrity and confidentiality, and treat signature verification as one control rather than a body checksum.
The Express, Python, and Rails packages handle the signature and timestamp check. Here is the Express shape:
import express from "express";
import { singleform } from "singleform-express-webhook";
const app = express();
app.use(express.json());
app.post(
"/webhooks/singleform",
singleform({ secret: process.env.SINGLEFORM_SECRET }),
async (req, res) => {
const submissionId = await saveSubmission(req.body);
res.singleformSuccess({ submissionId, message: "Received" });
}
);Keep the secret on your server. Do not expose it in a website or mobile bundle. If you implement verification yourself, reject stale timestamps and compare signatures in constant time. A timestamp only limits the replay window; to reject a duplicate within that window, your receiver must remember a used nonce or enforce idempotency using its own durable key. The current Express middleware validates the signature and timestamp but does not keep a nonce store for you.
Respond quickly and clearly
Finish any work needed to make the submission durable, then return a response promptly. If you queue later work, make sure the queue accepted the job before you report success. Otherwise a 200 can tell the user the response was received when it was actually lost.
SingleForm can show a structured error to the person submitting the form. For example:
{
"success": false,
"error": {
"type": "DUPLICATE_SUBMISSION",
"message": "This email is already registered"
}
}Use a message the person can act on. Keep personal data out of error text and logs. The response format also supports field-level validation errors.
Handle duplicates and failures
There are no server-side retries: SingleForm does not retain a submission body for later redelivery. Your receiver should still be idempotent, because users can submit twice and networks can leave the sender unsure whether the first attempt succeeded. Choose a stable key for your own workflow and make a repeat safe.
Monitor your endpoint's availability and SingleForm's delivery status. Test at least three paths before launch: a success response, a validation error, and an unavailable endpoint. If a failed submission matters to your workflow, make sure the person submitting knows what to do next.
Follow the quick start to build a test receiver, or create a form and point it at your own endpoint.