Documentation Index Fetch the complete documentation index at: https://docs-terra.withunify.org/llms.txt
Use this file to discover all available pages before exploring further.
Webhooks
Webhooks notify external systems when submissions are created or updated.
Webhook Configuration
CREATE TABLE webhook_configs (
id UUID PRIMARY KEY ,
form_id UUID REFERENCES forms(id),
name TEXT NOT NULL ,
url TEXT NOT NULL ,
events TEXT [] DEFAULT ARRAY ['submission.created'],
secret TEXT NOT NULL , -- HMAC signing key
headers JSONB DEFAULT '{}' ,
is_active BOOLEAN DEFAULT true
);
Events
Event Trigger submission.createdNew submission submission.updatedSubmission modified status.changedStatus updated
HMAC Signing
Every webhook is signed with HMAC-SHA256:
function signPayload ( payload : string , secret : string ) : string {
return crypto
. createHmac ( "sha256" , secret )
. update ( payload )
. digest ( "hex" );
}
// Headers sent:
// X-Webhook-Signature: sha256=abc123...
// X-Webhook-Timestamp: 1704000000
Verification (Receiver)
function verifyWebhook (
payload : string ,
signature : string ,
timestamp : string ,
secret : string
) : boolean {
// Check timestamp isn't too old (prevent replay)
const age = Date . now () / 1000 - parseInt ( timestamp );
if ( age > 300 ) return false ; // 5 minute window
// Verify signature
const expected = signPayload ( ` ${ timestamp } . ${ payload } ` , secret );
return crypto . timingSafeEqual (
Buffer . from ( signature ),
Buffer . from ( `sha256= ${ expected } ` )
);
}
Retry Strategy
Webhooks use the async queue with 5 retries and exponential backoff.
Queue Architecture How retries work
Background Jobs Queue processing