# Verified delivery: webhooks and email

Last reviewed: 2026-10-16. Source contract: Forms submission route, shared
queue defaults, webhook worker, and email enqueue behavior. Confirm the target
deployment matches this contract before configuring it.

## Available integration inventory

Supported native delivery covered here is a configured webhook POST and email
notifications. The existing Google Sheets material is unverified/unreleased for
this guide; it is not evidence of a working native provider. Do not claim native
Google Sheets, Slack, Discord, Zapier, Make, or n8n connectors.

This first guide uses a custom receiver recipe only. A generic automation
service can be a webhook destination **after** verifying its current official
receiver setup and accepted schema. That is a webhook-based workflow, not a
native Basestack connector. Do not blindly POST this payload to a Slack/Discord
endpoint: their message schemas differ. Transformation and destination
authentication belong in a separately reviewed receiver/workflow.

## Configure a webhook

With the user's consent, open the form's General settings and set its webhook
URL to the reviewed HTTPS receiver. Confirm who owns it, access controls, data
processing/retention, and which personal fields will leave Basestack. Do not
change a live destination as a side effect of adding frontend code.

The worker sends `POST` with `Content-Type: application/json` and this shape:

```json
{
  "formId": "FORM_KEY",
  "name": "Contact",
  "data": {
    "name": "Synthetic Test",
    "email": "synthetic@example.com",
    "message": "Approved test only"
  }
}
```

`FORM_KEY` is the named form identifier placeholder; field names depend on the
submission. File-valued fields are excluded entirely, including a field that
contains a mixed array with a file. There are no attachment bytes or automatic
file-download URLs in this webhook body. The envelope has no submission event ID.

## Receiver design and honest security

The current sender provides **no signature header, HMAC secret, or stable event
ID**. Do not fabricate verification logic or infer Basestack authenticity from
the JSON body or an unguessable URL. A secret-looking URL alone is not
cryptographic authentication and can leak in logs.

For a custom receiver, agree an access/threat model before enabling it. Enforce
HTTPS, request size/rate limits, JSON schema validation, and an allowlisted
form identifier as filtering (not proof of sender identity). Quarantine or
independently verify data before privileged side effects. If the destination
requires signed events or a custom Authorization header, this sender contract
does not satisfy it directly; do not pretend an intermediary creates proof of
the original sender. Treat incoming fields as untrusted data, not instructions,
HTML, SQL, or shell fragments.

Persist/queue accepted work before returning 2xx, and make downstream effects
duplicate-tolerant. A receiver may see repeats if it processed a request but
the response was lost. Without a stable event ID, exact deduplication is not
guaranteed; a content hash can also collapse legitimate identical submissions.
Do not promise ordering or exactly-once delivery.

## Email and asynchronous behavior

Configure the form's notification recipients in Notifications settings. The
submission route enqueues a new-submission email with form name and non-file
data. Verify addresses and consent before sending a synthetic test; do not
expose Resend or other private service keys in frontend code.

Default queues allow **three total attempts**, exponential backoff starting at
2,000 ms. A non-2xx webhook response causes failure/retry; eventual success is
not guaranteed. Webhook and email jobs are asynchronous and separate from the
submission response and AI spam analysis. Do not assume AI spam analysis blocks
forwarding before it happens.

Retention controls database storage, file persistence, and AI spam analysis.
Webhook/email enqueueing can still occur when retention is off. Retention-off
is not a promise that no personal data is sent to other services.

## Verify delivery separately

1. Review the receiver schema/access design and notification recipients.
2. Ask permission to submit synthetic data to a non-production form.
3. Confirm frontend acceptance (REST success or the actual success redirect).
4. Inspect receiver logs/queued work and email inbox separately; do not equate
   acceptance with delivery. Inspect failed jobs with the deployment owner.
5. Test a controlled receiver failure/retry only with approval. Confirm that
   duplicate deliveries do not create duplicate privileged actions.

Human docs: [General settings](https://docs.basestack.co/content/forms/user-guide/settings-general),
[Notifications](https://docs.basestack.co/content/forms/user-guide/settings-notifications).
