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 delivered by the platform SMTP relay
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.to string[] Yes — min 1, each valid email Recipient addresses
config.subjectTemplate string No "Form 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": {
      "to": ["[email protected]"],
      "subjectTemplate": "Form 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)

{
  "ok": true
}

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