Docs (MVP)
Documentation
EvidenceForm receives form submissions and gives you Trace, Replay, and Evidence so you can explain and recover deliveries.
Quick start
- Create an account and a form in the console.
- Set Allowed domains to prevent abuse.
- Copy your Access key.
- Paste the HTML snippet into your site and deploy.
- Test submit, then check the console timeline.
Submit endpoint
Submit with form POST to:
POST /v1/submit/:formId
Accepts multipart/form-data or application/x-www-form-urlencoded. For JSON responses, set Accept: application/json.
cURL
curl -X POST "https://YOUR_DOMAIN/v1/submit/YOUR_FORM_ID" \
-H "Accept: application/json" \
-F "access_key=YOUR_ACCESS_KEY" \
-F "name=Jane Doe" \
-F "email=jane@company.com" \
-F "message=Hello!"fetch()
await fetch("https://YOUR_DOMAIN/v1/submit/YOUR_FORM_ID", {
method: "POST",
headers: { Accept: "application/json" },
body: new URLSearchParams({
access_key: "YOUR_ACCESS_KEY",
name: "Jane Doe",
email: "jane@company.com",
message: "Hello!",
}),
});Fields & validation
- access_key: required, must match the form's access key.
- email: must be a valid email when provided.
- message: required in the default examples; you can submit any fields you want.
If you configured allowed domains for the form, requests must include a matching Origin or Referer header.
Honeypot spam trap
Add a hidden field named website. Bots often fill it; we store the submission as spam and still return success to avoid tipping them off.
HTML
<input type="hidden" name="website" value="" />Redirects (HTML)
If the request Accept header includes text/html, EvidenceForm redirects to your configured success/error URL. We append query params for easier UX:
- submission_id on success
- error on failure
Webhooks
When configured, we POST JSON to your webhook URL and include a signature header:
x-evidenceform-signature: HMAC-SHA256(secret, raw_json_body) (hex)
Node.js verification
import crypto from "node:crypto";
export function verifyEvidenceFormSignature(req, rawBody) {
const secret = process.env.EVIDENCEFORM_WEBHOOK_SECRET;
const sig = req.headers["x-evidenceform-signature"] ?? req.headers["x-pro3-signature"];
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
return sig && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}