Destinations
Destinations define where form submissions are delivered. Each form can have multiple destinations, and each submission is delivered to all enabled destinations independently.
All destination endpoints require the x-tenant-key header.
Destination Types
formdata.dev supports three destination types as a discriminated union on the type field:
| Type |
Description |
webhook |
HTTP request to any URL |
smtp |
Email via SMTP with AUTH LOGIN |
google_sheets_webhook |
HTTP request to a Google Apps Script web app |
Add Destination
Request
POST /v1/admin/forms/:id/destinations
Content-Type: application/json
x-tenant-key: sk_live_abc123...
The request body is a discriminated union keyed on type. The config object varies by type.
Webhook Config
| Field |
Type |
Required |
Default |
Constraints |
Description |
type |
"webhook" |
Yes |
— |
— |
Destination type |
config.url |
string |
Yes |
— |
Valid URL |
Endpoint to receive the SubmissionEnvelope |
config.method |
string |
No |
"POST" |
POST, PUT, or PATCH |
HTTP method |
config.headers |
Record<string, string> |
No |
{} |
— |
Custom headers to include |
isEnabled |
boolean |
No |
true |
— |
Whether this destination is active |
curl -X POST https://api.formdata.dev/v1/admin/forms/FORM_ID/destinations \
-H "Content-Type: application/json" \
-H "x-tenant-key: sk_live_abc123..." \
-d '{
"type": "webhook",
"config": {
"url": "https://hooks.slack.com/services/T00/B00/xxx",
"method": "POST",
"headers": {}
},
"isEnabled": true
}'
SMTP Config
| Field |
Type |
Required |
Default |
Constraints |
Description |
type |
"smtp" |
Yes |
— |
— |
Destination type |
config.host |
string |
Yes |
— |
min 1 char |
SMTP server hostname |
config.port |
number |
Yes |
— |
1 - 65535 |
SMTP server port |
config.secureTransport |
string |
No |
"starttls" |
off, starttls, or on |
TLS mode |
config.username |
string |
Yes |
— |
min 1 char |
SMTP auth username |
config.password |
string |
Yes |
— |
min 1 char |
SMTP auth password |
config.from |
string |
Yes |
— |
Valid email |
Sender address |
config.to |
string[] |
Yes |
— |
min 1, each valid email |
Recipient addresses |
config.subjectTemplate |
string |
No |
"New submission: {{formName}}" |
min 1 char |
Subject line with template variables |
Template variables for subjectTemplate:
| Variable |
Replaced With |
{{formName}} |
The form's display name |
{{submissionId}} |
The unique submission UUID |
curl -X POST https://api.formdata.dev/v1/admin/forms/FORM_ID/destinations \
-H "Content-Type: application/json" \
-H "x-tenant-key: sk_live_abc123..." \
-d '{
"type": "smtp",
"config": {
"host": "smtp.gmail.com",
"port": 587,
"secureTransport": "starttls",
"username": "[email protected]",
"password": "your-app-password",
"from": "[email protected]",
"to": ["[email protected]"],
"subjectTemplate": "New submission: {{formName}}"
},
"isEnabled": true
}'
Google Sheets Webhook Config
| Field |
Type |
Required |
Default |
Constraints |
Description |
type |
"google_sheets_webhook" |
Yes |
— |
— |
Destination type |
config.url |
string |
Yes |
— |
Valid URL |
Apps Script web app URL |
config.method |
string |
No |
"POST" |
POST or PUT |
HTTP method |
config.authHeader |
string |
No |
— |
— |
Value for the Authorization header |
isEnabled |
boolean |
No |
true |
— |
Whether this destination is active |
curl -X POST https://api.formdata.dev/v1/admin/forms/FORM_ID/destinations \
-H "Content-Type: application/json" \
-H "x-tenant-key: sk_live_abc123..." \
-d '{
"type": "google_sheets_webhook",
"config": {
"url": "https://script.google.com/macros/s/AKfycb.../exec",
"method": "POST"
},
"isEnabled": true
}'
Response (200)
All destination types return the same response shape:
{
"ok": true,
"destination": {
"id": "d1234567-89ab-cdef-0123-456789abcdef",
"formId": "f1234567-...",
"type": "webhook",
"config": {
"url": "https://hooks.slack.com/services/T00/B00/xxx",
"method": "POST",
"headers": {}
},
"isEnabled": true
}
}
Errors
| Status |
Error |
Cause |
400 |
Validation error |
Invalid config for the specified type |
404 |
Form not found |
Invalid form ID or belongs to another organization |
Remove Destination
Request
DELETE /v1/admin/forms/:id/destinations/:destId
x-tenant-key: sk_live_abc123...
Example
curl -X DELETE https://api.formdata.dev/v1/admin/forms/FORM_ID/destinations/DEST_ID \
-H "x-tenant-key: sk_live_abc123..."
Response (200)
Errors
| Status |
Error |
Cause |
404 |
Form not found |
Invalid form ID or belongs to another organization |
404 |
Destination not found |
Invalid destination ID or belongs to another form |