Skip to main content

Webhooks API

Webhooks allow external systems to trigger Formstamper workflows by sending HTTP requests.

Send Webhook Event

POST /api/workflows/{workflowId}/webhook

Trigger a workflow by sending event data to its webhook endpoint.

note

This endpoint does not require authentication. The unique workflow ID serves as the identifier. For production use, consider implementing payload signing in your sending application.

Request Body:

{
"tenant_name": "Jane Doe",
"unit_address": "456 Oak Ave, Unit 2B",
"rent_owed": 2400,
"arrears_from": "2026-01-01",
"arrears_to": "2026-03-31",
"sign_date": "2026-04-12"
}

Response: 202 Accepted

Webhook received

Error Responses

CodeBodyMeaning
202Webhook receivedEvent accepted and queued
400Payload validation failed: ...JSON schema validation error
400Invalid JSON payloadRequest body is not valid JSON
400Invalid schema or payload: ...Schema parsing error
404Workflow not found!No workflow with the given ID

Get Latest Webhook Event

GET /api/workflows/{workflowId}/webhook/latest-event

Retrieve the most recently received webhook event for a workflow. Requires authentication.

Response: 200 OK

{
"eventId": "evt_abc123",
"workflowId": "wrk_01j5abc123",
"eventPayload": "{\"tenant_name\":\"Jane Doe\",...}",
"receivedAt": "2026-04-12T14:30:00"
}

Webhook Payload Format

Webhook payloads should be flat JSON objects where each key corresponds to a column name in your template's field mappings.

{
"tenant_name": "string",
"address": "string",
"amount": "number (or string)",
"date_field": "string (YYYY-MM-DD format preferred)"
}

Nested Payloads

If your external system sends nested JSON, use Compose or Select nodes in your workflow to flatten the data before it reaches the Template Node.

Incoming payload:

{
"tenant": {
"name": "Jane Doe",
"address": {
"street": "456 Oak Ave",
"unit": "2B"
}
},
"financials": {
"rent_owed": 2400
}
}

Compose Node mapping:

{
"tenant_name": "${event.tenant.name}",
"full_address": "${event.tenant.address.street}, ${event.tenant.address.unit}",
"amount": "${event.financials.rent_owed}"
}

Integration Examples

cURL

curl -X POST https://api.formstamper.com/api/workflows/wrk_01j5abc123/webhook \
-H "Content-Type: application/json" \
-d '{"tenant_name":"Jane Doe","address":"456 Oak Ave","rent_owed":2400}'

JavaScript (fetch)

await fetch('https://api.formstamper.com/api/workflows/wrk_01j5abc123/webhook', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
tenant_name: 'Jane Doe',
address: '456 Oak Ave',
rent_owed: 2400,
}),
});

Python (requests)

import requests

requests.post(
'https://api.formstamper.com/api/workflows/wrk_01j5abc123/webhook',
json={
'tenant_name': 'Jane Doe',
'address': '456 Oak Ave',
'rent_owed': 2400,
}
)

C# (HttpClient)

var client = new HttpClient();
var content = new StringContent(
JsonSerializer.Serialize(new {
tenant_name = "Jane Doe",
address = "456 Oak Ave",
rent_owed = 2400
}),
Encoding.UTF8,
"application/json"
);
await client.PostAsync(
"https://api.formstamper.com/api/workflows/wrk_01j5abc123/webhook",
content
);