Form submissions and privacy
What Amplify UP keeps when a visitor submits a form, for how long, and how to delete it.
Forms is in preview. This page describes how form submissions are handled once forms go live on your site.
You choose how much of a submission Amplify UP keeps, and you can choose to keep none of it. When answers are kept, they're limited to what the form asks, encrypted, hidden by default in the dashboard, kept for a short time, and removable on request. A visitor's consent choice always overrides the form's settings.
Choose what Amplify UP keeps
Each form has three separate settings. Any combination works.
| Setting | Options | What it means |
|---|---|---|
| Keep submissions | Keep answers (default) | Answers are kept so you can see them on the form's Submissions tab. |
| Forward only | Answers go to your destinations and are never kept. Amplify UP keeps only when the form was submitted, which form and version, the page it was on, and whether delivery worked. | |
| Record only | Answers aren't kept or sent anywhere. Webhooks are told a submission arrived, without its answers. | |
| Destinations | Webhooks | Where each submission is sent. A form can send to several. A forward-only form needs at least one. |
| Visitor profile | Off (default) / On | When on, only the fields you map are added to the visitor's profile. Nothing else from the form reaches the profile. |
Receiving submissions on a webhook
Each submission is sent as a POST with a JSON body to every webhook that's on:
{
"event": "form.submission",
"test": false,
"formId": "…",
"formKey": "form_contact",
"version": 3,
"submissionId": "…",
"submittedAt": "2026-10-12T10:00:00.000Z",
"page": "/contact",
"consent": "granted",
"values": { "email": "ada@example.com", "company": "Analytical" },
"fields": { "email": { "pii": true }, "company": { "pii": false } }
}
- Reply with any
2xxstatus within 10 seconds. Anything else is retried twice over the next few minutes, and the result shows in the form's Submissions tab. X-AmplifyUp-Deliveryis the same on every retry of one submission to one webhook. Use it to ignore repeats.- Send test next to a webhook posts a made-up submission with
"test": true.
Check that a request came from Amplify UP
When you add a webhook you get its signing secret (whsec_…), shown once. Every request carries:
| Header | Value |
|---|---|
X-AmplifyUp-Timestamp | Seconds since 1970 when it was sent |
X-AmplifyUp-Signature | sha256= followed by the hex HMAC-SHA256 of <timestamp>.<raw body>, keyed with the signing secret |
- Read the raw request body before parsing it.
- Compute
sha256=+ HMAC-SHA256(secret,timestamp + "." + rawBody) in hex. - Compare it with
X-AmplifyUp-Signatureusing a constant-time comparison. - Reject requests whose timestamp is more than 5 minutes old.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function isFromAmplifyUp(rawBody, headers, secret) {
const timestamp = headers['x-amplifyup-timestamp'];
const signature = headers['x-amplifyup-signature'] ?? '';
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = `sha256=${createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex')}`;
return expected.length === signature.length && timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
Personal data in answers
Fields that usually hold personal data (email, phone, name, address, date of birth) are marked Personal data automatically. You can change the mark on any field in the builder.
Answers in personal data fields are:
- encrypted when they're stored
- hidden in the dashboard until someone with permission reveals them, and every reveal is recorded
- marked as personal data when they're sent to your destinations, so your own systems can treat them the same way
Payment card numbers are refused. A form that receives one shows the visitor an error and nothing is stored.
How long answers are kept
Answers are deleted 90 days after they're submitted. You can shorten or lengthen this per form (up to a year). You can also choose to delete answers as soon as every destination has received them.
How consent changes this
Your consent banner tells Amplify UP each visitor's choice through the SDK (setConsent). Under Forms › Visitor consent you choose whether to rely on it, and whether a visitor who hasn't chosen counts as agreed (only where visitors may opt out rather than in).
When a visitor hasn't consented, or their choice is unknown, their submission is handled as forward only, whatever the form's settings:
- their answers are sent to your destinations, marked as sent without consent, and not kept
- the visitor isn't identified, and nothing is added to a profile
- only the page path is recorded, without query details
Consent to be identified can also be tied to a checkbox on the form itself, so a visitor is only identified when they tick it.
Identifying visitors
When a form is set to identify visitors, Amplify UP keeps a one-way code made from their email address or phone number, not the address or number itself. The plain value is only added to the profile when you map that field to a profile attribute. Identifying a visitor links their future visits to the same profile. It doesn't copy their earlier browsing onto it.
Deleting submissions
- Delete a single submission from the form's Submissions tab.
- Delete everything about one person: every submission from them, the attributes forms added to their profile, and the link between their visits and that profile.
- Deleting a form deletes all of its kept submissions.
- If your consent banner lets visitors withdraw consent, it can ask Amplify UP to delete their submissions and profile details at the same time.