Receive real-time HTTP notifications when form responses start, submit, or trigger alerts.
Webhooks
Webhooks send HTTP POST requests from Sayify to your endpoint. Use them to sync new submissions to your CRM, data warehouse, ticketing system, automation server, or any custom backend.
For step-by-step setup, start with the Webhook Integration guide. This page is the detailed payload, signature, retry, and reference documentation for webhook consumers.
There are two webhook delivery paths:
| Path | Where configured | Payload sent |
|---|---|---|
| Custom Webhook integration | Integrations page or Form Builder > Automation > Always-On Integrations | Full event payloads: response.started and response.submitted |
| Notification Settings webhook | Workspace Global Settings / notification channel | Alert payloads for alert notifications; for form-submit global webhooks, the full response.submitted payload |
For most integrations, use a Custom Webhook from the Integrations page. It includes delivery logs, retry state, event subscriptions, and per-form assignment.
Configure A Webhook
- Open Integrations.
- Choose Custom Webhook.
- Enter your endpoint URL, for example
https://api.example.com/sayify/webhook. - Choose the events to send.
- Save, then use Test to verify delivery.
You can also assign webhooks from Form Builder > Automation > Global Settings > Always-On Integrations. Assigned integrations receive every submission for that form.
Events
| Event | When it fires | Payload size |
|---|---|---|
response.started |
A respondent opens the form and a response session starts. | Lightweight session metadata |
response.submitted |
A respondent completes the form. Delivery waits for AI/evaluation data when available. | Full response, contact, AI, extracted fields, and metadata |
Headers
Custom Webhook integrations include:
| Header | Description |
|---|---|
Content-Type |
application/json |
X-Sayify-Event |
Event name, such as response.submitted. |
X-Sayify-Delivery-Id |
Unique delivery UUID for idempotency. |
X-Sayify-Signature |
Optional HMAC-SHA256 signature if a secret is configured. Format: sha256=<hex>. |
User-Agent |
Sayify-Webhooks/1.0 |
Notification Settings raw URL deliveries include Content-Type, X-Sayify-Event, and optional X-Sayify-Signature.
Payload: response.started
{
"event": "response.started",
"timestamp": "2026-02-17T10:13:15.123Z",
"session": {
"uuid": "abc123-session-uuid-456",
"link_name": "Product Feedback Survey",
"link_slug": "product-feedback",
"link_uuid": "def789-link-uuid-012",
"started_at": "2026-02-17T10:13:15.123Z"
},
"respondent": {
"ip_address": "192.0.2.1",
"user_agent": "Mozilla/5.0",
"location": {
"country": "US",
"city": "San Francisco"
}
},
"workspace": {
"uuid": "workspace-uuid-123",
"name": "Acme Corp"
},
"use_case": "lead_qualification"
}
Payload: response.submitted
This is the payload sent when a form is submitted through Custom Webhook integrations and Global Settings form-submit webhooks.
{
"event": "response.submitted",
"timestamp": "2026-02-17T10:13:30.794Z",
"session": {
"uuid": "abc123-session-uuid-456",
"link_name": "Product Feedback Survey",
"link_slug": "product-feedback",
"link_uuid": "def789-link-uuid-012",
"started_at": "2026-02-17T10:13:15.123Z",
"completed_at": "2026-02-17T10:13:30.794Z",
"duration_seconds": 15.67
},
"respondent": {
"ip_address": "192.0.2.1",
"user_agent": "Mozilla/5.0",
"location": {
"country": "US",
"city": "San Francisco"
}
},
"contact": {
"name": "Alex Johnson",
"email": "alex@acmecorp.com",
"phone": "+14155551234",
"company": "Acme Corp",
"status": "lead"
},
"responses": {
"overall_experience": {
"question": "How would you rate your overall experience?",
"response_type": "voice",
"value": "I love the analytics feature, but I need better export options.",
"audio_url": "https://resource.sayify.pro/responses/abc123/audio.mp3",
"transcript": "I love the analytics feature, but I need better export options.",
"ai_evaluation": {
"clarity_score": 87,
"completion_status": "complete",
"extracted_fields": {
"sentiment": "positive",
"mentioned_features": ["analytics", "dashboard"],
"pain_points": ["export_options"]
},
"confidence_score": 0.92,
"insights": {
"sentiment_score": 8,
"urgency_level": "medium",
"feature_mention": ["analytics", "dashboard", "export"],
"action_required": "follow_up_on_export_feature",
"persona_tag": "power_user",
"executive_summary": "User likes analytics and needs export improvements."
}
},
"follow_ups": [
{
"question": "What specific export formats would you like?",
"value": "PDF and PowerPoint would be great for presentations",
"ai_evaluation": {
"clarity_score": 95,
"extracted_fields": {
"requested_formats": ["PDF", "PowerPoint"],
"use_case": "presentations"
}
}
}
]
},
"feature_rating": {
"question": "Rate our analytics feature",
"response_type": "rating",
"value": 9,
"rating_details": {
"value": 9,
"max_value": 10,
"scale_type": "stars"
}
},
"preferred_design": {
"question": "Select your preferred design",
"response_type": "image_choice",
"value": "Modern Blue",
"selected_card": {
"card_id": "card-uuid-1",
"label": "Modern Blue",
"media_url": "https://resource.sayify.pro/cards/modern-blue.jpg",
"media_type": "image"
}
}
},
"ai_evaluation": {
"clarity_score": 85,
"completion_status": "complete",
"follow_up_count": 1,
"insights": {
"sentiment_score": 8,
"urgency_level": "medium",
"feature_mention": ["analytics", "dashboard", "export"],
"action_required": "follow_up_call",
"persona_tag": "power_user",
"executive_summary": "User likes analytics but needs better export options."
}
},
"metadata": {
"total_questions": 3,
"answered_questions": 3,
"average_response_time": "5s",
"completion_percentage": 100
},
"workspace": {
"uuid": "workspace-uuid-123",
"name": "Acme Corp"
},
"use_case": "lead_qualification",
"extracted_data": {
"company_size": "50-100",
"industry": "SaaS",
"budget": "1000-5000",
"decision_process": "Finance approval required",
"custom_fields": {
"procurement_owner": "Jordan Lee"
}
},
"custom_fields": {
"decision_process": "Finance approval required",
"procurement_owner": "Jordan Lee"
},
"use_case_metrics": {
"icp_fit": "Strong Fit",
"buyer_intent": "Ready to Buy",
"lead_score": 88,
"pain_points_detected": ["export_options"]
},
"use_case_key_points": {
"buying_signals": ["Asked about implementation timeline"],
"risks": ["Needs export options"]
},
"extracted_fields": {
"Field:company_size": "50-100",
"Field:industry": "SaaS",
"Field:budget": "1000-5000",
"Field:decision_process": "Finance approval required"
},
"ai_metrics": {
"Metric:icp_fit": "Strong Fit",
"Metric:buyer_intent": "Ready to Buy",
"Metric:lead_score": 88,
"Metric:pain_points_detected": ["export_options"]
}
}
Top-Level Fields
| Field | Type | Description |
|---|---|---|
event |
string | Event name. |
timestamp |
string | ISO-8601 delivery timestamp. |
session |
object | Response session identity, form identity, and timing. |
respondent |
object | Browser/IP metadata and approximate location if available. |
contact |
object | Resolved CRM contact fields. Values are null for anonymous respondents. |
responses |
object | Answers keyed by each question's field_key. |
ai_evaluation |
object | Session-level AI summary when AI features are available. |
metadata |
object | Counts, average response time, and completion percentage. |
workspace |
object | Workspace identity. |
use_case |
string | Form use-case key, such as lead_qualification, support_intake, client_intake, or general. |
extracted_data |
object | Unprefixed form-level AI extracted fields, flattened from the confidence schema. |
custom_fields |
object | Business-specific custom AI fields from form schema and per-answer custom field extraction. |
use_case_metrics |
object | Canonical use-case metrics for the form's use case, such as lead score, ICP fit, ticket severity, or client readiness. |
use_case_key_points |
object | Structured use-case-specific arrays/summaries, when generated. |
extracted_fields |
object | Backward-compatible flattened AI fields. Keys are prefixed with Field:. |
ai_metrics |
object | Backward-compatible use-case metrics. Keys are prefixed with Metric:. |
Use-Case, Metrics, And Custom Fields
Sayify includes both unprefixed fields for new integrations and prefixed fields for existing consumers:
| Block | Best for | Notes |
|---|---|---|
extracted_data |
Reading all form-level extracted fields exactly by key. | Values are flattened from {value, confidence} objects to plain values. |
custom_fields |
Reading only business-specific custom fields. | Includes extracted_data.custom_fields, form extraction_schema.fields[] marked is_custom, and per-answer extracted_fields.custom_fields. |
use_case_metrics |
Reading canonical use-case metrics. | Schema depends on use_case; examples include lead qualification, support intake, client intake, and general. |
use_case_key_points |
Reading generated use-case-specific summaries or arrays. | Included when the AI pipeline generated structured key points. |
extracted_fields |
Existing webhook consumers. | Same data as extracted fields but prefixed as Field:<key>. |
ai_metrics |
Existing webhook consumers and Zapier-style mapping. | Same metric data but prefixed as Metric:<key>. |
Metric schema definitions are documented here instead of repeated in every webhook delivery. The live payload sends the extracted values in use_case_metrics.
Response Object Fields
Each item in responses is keyed by the question field_key.
| Field | Type | Description |
|---|---|---|
question |
string | Prompt shown to the respondent. |
response_type |
string | Question type, such as voice, text, rating, image_choice, contact_info, or voice_text_fallback. |
value |
any | The normalized answer value. |
audio_url |
string | Voice answer audio URL, when available. |
transcript |
string | Voice answer transcript, when available. |
selected_card |
object | Image-choice card metadata, when applicable. |
rating_details |
object | Rating scale metadata, when applicable. |
ai_evaluation |
object | Per-answer clarity, extracted fields, confidence, and insights. |
follow_ups |
array | AI follow-up answers, when dynamic probing was used. |
Alert Notification Payloads
When a workflow or alert notification sends to a webhook channel, the payload is alert-shaped instead of response-shaped:
{
"event": "alert.urgent_detected",
"timestamp": "2026-02-17T10:14:01.000Z",
"alert": {
"uuid": "alert-uuid",
"type": "urgent_detected",
"severity": "critical",
"title": "Urgent response detected",
"message": "Urgency score: 9/10",
"created_at": "2026-02-17T10:14:01.000Z"
},
"case": {
"uuid": "case-uuid",
"status": "new",
"priority": "urgent",
"ai_summary": "Customer needs immediate support.",
"sentiment": "negative",
"urgency_score": 9
},
"form_name": "Support Intake",
"workspace_uuid": "workspace-uuid",
"dashboard_url": "https://app.sayify.pro/inbox/case-uuid",
"questions": [
{
"prompt": "What happened?",
"field_key": "issue_summary",
"response_type": "text",
"answer": "My account is locked and customers are waiting."
}
],
"use_case": "support_intake",
"extracted_data": {
"issue_area": "Login",
"affected_account": "Enterprise workspace"
},
"custom_fields": {
"internal_escalation_note": "Route to identity team"
},
"use_case_metrics": {
"severity": "Critical",
"sla_priority": "P1"
},
"use_case_key_points": {
"risks": ["Customers are blocked"]
}
}
Alert webhook payloads include the same use_case, extracted_data, custom_fields, use_case_metrics, and use_case_key_points blocks when the alert is tied to a case.
Signature Verification
If a secret is configured, Sayify signs the raw JSON body with HMAC-SHA256.
import crypto from "crypto";
function isValidSayifySignature(rawBody, header, secret) {
const received = header.replace(/^sha256=/, "");
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(received, "hex"),
Buffer.from(expected, "hex")
);
}
Retry Policy
Custom Webhook integrations retry failed deliveries with exponential backoff:
| Retry | Delay |
|---|---|
| 1 | 1 minute |
| 2 | 5 minutes |
| 3 | 15 minutes |
| 4 | 1 hour |
| 5 | 6 hours |
An endpoint is considered successful when it returns any 2xx status code.
Notification Settings raw URL deliveries are fire-and-forget for form-submit global webhooks. Use a Custom Webhook integration if you need delivery logs and retries.
Consumer Tips
- Return a 2xx response quickly, then process the payload asynchronously.
- Use
X-Sayify-Delivery-Idfor idempotency when available. - Store the raw payload during development for easier debugging.
- Treat
responseskeys as dynamic because they come from your form field keys. - Expect optional fields to be missing or
nulldepending on question type, respondent identity, and plan features. - Use HTTPS endpoints because payloads can include respondent data.
Related Docs
- Integrations - One-stop guide for Slack, Google Sheets, Zapier, and webhooks.
- Webhook Integration - Setup-focused custom webhook guide.
- Zapier - Flattened payload format for Zapier.
- API Reference - REST API documentation.