Skip to content
Back to Steward

Webhooks Guide

Webhooks let you receive real-time notifications when events occur in your Steward account. Instead of polling the API, Steward sends HTTP POST requests to your configured URL.

Terminal window
curl -X POST https://api.getsteward.ai/api/v1/webhooks \
-H "Authorization: Bearer stw_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/steward",
"events": ["application.submitted", "application.approved"]
}'

The response includes a signing secret - store it securely. It is only returned once.

{
"id": "wh_507f1f77bcf86cd799439011",
"url": "https://your-app.com/webhooks/steward",
"events": ["application.submitted", "application.approved"],
"secret": "whsec_abc123...",
"status": "ACTIVE"
}
EventDescription
application.createdA new application was created
application.onboarding_startedApplicant began the onboarding flow
application.submittedApplication was submitted for review
application.updatedAn application’s details were updated
application.approvedApplication was approved
application.rejectedApplication was rejected
screening.createdCompliance screening was initiated
screening.updatedScreening results were updated
screening.hit_updatedA screening hit status was changed
document.uploadedA document was uploaded
risk_score.createdRisk score was calculated
risk_score.updatedRisk score was recalculated
reviewer.assignedA reviewer was assigned to an application
reviewer.unassignedA reviewer was removed from an application
note.createdA note was added
note.updatedA note was modified
note.deletedA note was deleted

Each webhook delivery includes:

{
"event": "application.submitted",
"timestamp": "2026-03-30T15:00:00.000Z",
"data": {
"entityType": "APPLICATION",
"entityId": "507f1f77bcf86cd799439011",
"accountId": "acc_123"
}
}

Headers:

HeaderDescription
X-Webhook-SignatureHMAC-SHA256 signature of the request body
X-Webhook-EventEvent type (e.g., application.submitted)
X-Webhook-Delivery-IDUnique delivery ID for idempotency (stable on retries)
Content-Typeapplication/json

Verify the X-Webhook-Signature header to ensure the request came from Steward:

import { createHmac } from 'crypto'
function verifyWebhookSignature(body, signature, secret) {
const expected = createHmac('sha256', secret).update(body).digest('hex')
return signature === expected
}

Warning: Always verify webhook signatures before processing payloads. Without verification, an attacker could send fake events to your endpoint.

Each delivery includes an X-Webhook-Delivery-ID header that is unique per delivery and remains the same across retries. Use this ID to deduplicate events and ensure your handler processes each event only once.

const deliveryId = request.headers['x-webhook-delivery-id']
const alreadyProcessed = await cache.get(`webhook:${deliveryId}`)
if (alreadyProcessed) {
return res.status(200).send('OK')
}
// Process the event...
await cache.set(`webhook:${deliveryId}`, true, { ttl: 300 })

Failed deliveries are retried up to 5 times with exponential backoff:

AttemptDelay
130 seconds
22 minutes
310 minutes
41 hour
54 hours

After all retries are exhausted, the delivery is marked as failed. Use the deliveries endpoint to check delivery status.

Update or delete webhooks via the API:

Terminal window
# Update events
curl -X PATCH https://api.getsteward.ai/api/v1/webhooks/{id} \
-H "Authorization: Bearer stw_live_..." \
-d '{"events": ["application.submitted"]}'
# Pause
curl -X PATCH https://api.getsteward.ai/api/v1/webhooks/{id} \
-H "Authorization: Bearer stw_live_..." \
-d '{"status": "PAUSED"}'
# Delete
curl -X DELETE https://api.getsteward.ai/api/v1/webhooks/{id} \
-H "Authorization: Bearer stw_live_..."