Introduction to Webhooks
Webhooks allow you to receive real-time notifications about events in your Altur organization. When a specific event occurs (e.g., the end of a call), Altur sends an HTTP POST request with event-specific data to your configured endpoint. This enables seamless integration with your backend systems or CRM, ensuring they remain up-to-date.How Webhooks Work
-
Configure Your Endpoint
You can configure your webhook URL in the Altur platform. This URL will receive POST requests when specific events are triggered. -
Receive Notifications
When an event occurs, Altur sends a POST request with the event’s details in a structured JSON format to your endpoint. -
Acknowledge Delivery
Your endpoint should respond with a200 OKstatus code to confirm successful receipt. Altur waits up to 5 seconds for a response. Timeouts, connection errors,5xx,408and429responses are retried with exponential backoff (up to 5 total attempts). Any other4xxresponse fails immediately without retries, and redirects are not followed. See the Delivery Retry Policy.
Event Types
Webhooks can be triggered by the following event types:on_call_end: Triggered at the end of a call, this webhook sends detailed information about the call along with basic information about the AI agent and the end user.transfer_started: Triggered when a call transfer starts, so your human agents can prepare with real-time call context.transfer_completed: Triggered when a call transfer connects to the human leg.campaign.status_changed: Triggered when a Campaign transitions between lifecycle statuses. Includes the analytics snapshot when the campaign reachesfinished.campaign.cycle_completed: Triggered when a cycle iteration of a Campaign finishes, with the completed iteration number and the next scheduled iteration timestamp.
Campaign webhooks use a versioned envelope (
event_id, event_type,
occurred_at, api_version, project_id, data). Use event_id for
idempotent processing on your side. The call events (on_call_end,
transfer_started, transfer_completed) predate this envelope, keep their
flat top-level shape and have no event_id: deduplicate them on id (the
call ID) plus event_type.Securing Your Webhooks
To ensure secure communication and verify the authenticity of webhook requests, Altur includes an HMAC signature in theX-Altur-Signature header for every request.
How It Works
- Shared Secret: Each webhook integration is configured with a unique base64-encoded shared secret key.
- HMAC Generation: Altur generates an HMAC SHA-256 hash using the base64-decoded shared secret and the payload serialized as compact JSON (no spaces after
:or,, non-ASCII characters escaped as\uXXXX, e.g.Sofía→Sof\u00eda). This hash is base64-encoded and included in theX-Altur-Signatureheader. - Validation: Your endpoint must parse the body and re-serialize it in that same compact form before computing the HMAC.
Validation Function Example
Usage Example
Headers Sent with Webhook
Content-Type:application/jsonX-Altur-Signature: Base64-encoded HMAC SHA-256 hash of the compact JSON payload (see above; this is not the raw body)
Why This Matters
This mechanism ensures:- The request originates from Altur.
- The payload has not been tampered with during transmission.
Delivery Retry Policy
Any response other than2xx counts as a failure. Whether Altur retries depends on the failure:
Retries use:
- Maximum attempts: 5 (initial delivery plus 4 retries).
- Backoff: 60s after the first failure, doubling each attempt (60s, 2m, 4m, 8m).
Example Workflow
Here’s a typical workflow for handling webhooks effectively:-
Set Up Your Endpoint
Create an API endpoint in your backend, such as
/webhooks/altur/on-call-end. Ensure the endpoint is publicly accessible and configured to accept POST requests with aContent-Typeofapplication/json. - Parse Incoming Data Extract and process the JSON payload sent by Altur. Ensure your code handles possible issues, such as malformed payloads or missing fields, to prevent runtime errors.
-
Validate Request Authenticity
Use the
X-Altur-Signatureheader to verify the authenticity of the request. This involves:- Recomputing the HMAC signature using the shared secret and the parsed payload re-serialized as compact JSON.
- Comparing it with the signature provided in the header.
-
Respond Promptly
Return a
200 OKstatus code to acknowledge successful receipt. Altur times out the request after 5 seconds, so respond well before that to avoid unnecessary retries. - Log Events for Debugging Log the incoming request and processing steps to ensure traceability. This is particularly useful for debugging issues with payloads or retries.
- Handle Retries Gracefully Design your system to handle retries in case of temporary failures. Ensure your endpoint is idempotent so processing the same event multiple times does not create duplicate actions (e.g., duplicate database entries or API calls).
Best Practices
-
Secure Your Endpoint
- Authenticate Requests: Verify webhook authenticity using HMAC signatures. Always use a secure and unique shared secret for each integration.
- Restrict Access: Use IP whitelisting or firewalls to allow requests only from Altur’s servers.
- Encrypt Communication: Ensure your webhook endpoint uses HTTPS to encrypt data in transit.
-
Log Events
- Record Everything: Log all incoming webhook requests, including timestamps, headers, payloads, and responses.
- Monitor Failures: Implement alerts for repeated failures or invalid requests to quickly address issues.
- Enable Debugging: Retain logs for a reasonable period to aid in debugging or auditing as necessary.
-
Test Thoroughly
- Simulate Events: Use the Altur dashboard to simulate webhook events and confirm your endpoint handles them correctly.
- Handle Edge Cases: Test scenarios like malformed payloads, large payloads, or missing fields to ensure robustness.
- Use Staging Environments: Set up a dedicated staging endpoint for safe testing without affecting production systems.
-
Optimize Performance
- Respond Quickly: Altur times out after 5 seconds. If processing takes longer, acknowledge with
200 OKimmediately and handle the work asynchronously. - Minimize Processing: Perform lightweight validation and queuing at the webhook level, offloading heavy processing to background workers.
- Use Caching: Cache static responses for redundant requests when appropriate.
- Respond Quickly: Altur times out after 5 seconds. If processing takes longer, acknowledge with
-
Ensure Idempotency
- Avoid Duplicate Actions: Design your system to handle retries without causing duplicate operations (e.g., database inserts or API calls). For campaign events, deduplicate on
event_id. Call events (on_call_end,transfer_started,transfer_completed) have noevent_id, so deduplicate onidplusevent_type.
- Avoid Duplicate Actions: Design your system to handle retries without causing duplicate operations (e.g., database inserts or API calls). For campaign events, deduplicate on
-
Communicate Failures
- Return Meaningful Status Codes: Respond with appropriate HTTP status codes to help diagnose issues (e.g.,
400for invalid requests or500for server errors). Remember that4xxresponses other than408and429are not retried. - Log and Notify: Log failures and consider notifying your team if critical retries are exhausted.
- Return Meaningful Status Codes: Respond with appropriate HTTP status codes to help diagnose issues (e.g.,
Troubleshooting Signature Validation
If you’re having trouble with signature validation, check these common issues:1. JSON Serialization Format
Ensure you’re using the same JSON serialization format as Altur:- Parse, then re-serialize: Don’t compute the HMAC over the raw body. It contains spaces and won’t match.
- Compact format: No spaces after colons or commas.
- Escaped non-ASCII: Characters like
íorñmust be escaped as\uXXXX(Sofía→Sof\u00eda).JSON.stringifydoesn’t do this; see the JavaScript example. - Consistent ordering: Keep keys in the order they were received.
- PHP: Use
json_decode($raw), notjson_decode($raw, true). Associative arrays turn{}into[].
2. Secret Key Format
- Ensure your secret key is base64-encoded
- The secret should be the same one configured in your Altur webhook integration
3. Header Name
- The signature header is
X-Altur-Signature(case-sensitive in some frameworks) - Make sure you’re reading the correct header
4. Timing Attacks
Always use timing-safe comparison functions:- Python:
hmac.compare_digest() - Node.js:
crypto.timingSafeEqual() - PHP:
hash_equals()