Overview
Why Webhooks vs Polling
| Approach | Pros | Cons |
|---|---|---|
| Webhooks | Real-time notifications, no wasted API calls, scales efficiently | Requires public HTTPS endpoint, more complex setup |
| Polling | Simple to implement, works behind firewalls | Delayed updates, wastes API quota, doesn’t scale well |
When to Use Webhooks
Use webhooks when you need:- Real-time updates - React to events as they happen
- Scalable architecture - Handle thousands of concurrent operations
- Efficient resource usage - Eliminate unnecessary API calls
- Production systems - Build reliable, event-driven workflows
Setup
1. Configure Your Webhook URL
Configure your webhook endpoint in the Sully Dashboard. Requirements:- URL must use HTTPS (HTTP endpoints are rejected)
- Endpoint must be publicly accessible
- Must respond with 2xx status code within 30 seconds
2. Obtain Your Signing Secret
After configuring your webhook URL, you’ll receive a signing secret. Store this securely - you’ll need it to verify incoming webhook signatures.Event Types
Sully.ai sends webhook events for transcription, note generation, and medical coding operations.audio_transcription.succeeded
Triggered when an audio transcription completes successfully.audio_transcription.failed
Triggered when an audio transcription fails.note_generation.succeeded
Triggered when a clinical note is generated successfully.note_generation.failed
Triggered when note generation fails.coding.succeeded
Triggered when medical coding completes successfully.coding.failed
Triggered when medical coding fails.Signature Verification
Every webhook request includes anx-sully-signature header containing a timestamp and HMAC signature:
Signature Components
| Component | Description |
|---|---|
t | Unix timestamp when the request was signed |
v1 | HMAC-SHA256 signature of the payload |
Verification Steps
- Extract the timestamp and signature from the header
- Construct the signed payload:
{timestamp}.{raw_body} - Compute HMAC-SHA256 using your webhook secret
- Compare signatures using constant-time comparison
- Validate timestamp is within tolerance (default: 5 minutes)
Complete Verification Implementation
Handling Events
Idempotency
Events may be delivered more than once. Use the event type and resource ID to deduplicate:For production systems, use a persistent store (Redis, database) instead of in-memory sets to handle deduplication across server restarts and multiple instances.
Event Ordering
Events may arrive out of order. Design your handlers to be order-independent or use timestamps to determine event sequence:Response Requirements
Your webhook endpoint must:- Respond quickly - Return within 30 seconds
- Return 2xx status - Even if processing fails internally
- Process asynchronously - Queue events for background processing if needed
Retry Behavior
If your endpoint returns a non-2xx status or times out, Sully.ai will retry the webhook:- Retry schedule: Exponential backoff over 24 hours
- Max retries: 5 attempts
- Best practice: Return 2xx and handle failures internally
Production Webhook Handler
Complete Express.js example with all best practices:Testing Webhooks
Local Development with ngrok
Use ngrok to expose your local server to the internet:https://abc123.ngrok.io. Configure this URL in your Sully Dashboard as your webhook endpoint.
Verify Signature Handling
Test that your signature verification works correctly:Testing Checklist
Before going to production, verify:- Signature verification rejects invalid signatures
- Signature verification rejects expired timestamps
- All event types are handled correctly
- Duplicate events are handled idempotently
- Handler errors don’t cause 5xx responses
- Response time is under 30 seconds
Next Steps
Events Overview
Detailed reference for all webhook event types and payloads
Webhook Security
Deep dive into signature verification and security best practices
Notes Guide
Learn how to generate clinical notes that trigger webhook events
TypeScript SDK
Use the official SDK for type-safe API interactions