Skip to main content

Overview

Webhooks allow you to receive real-time notifications when specific events occur in your TitanX account. Instead of polling our API for changes, webhooks push data to your server as events happen, enabling you to build responsive, event-driven integrations.
Understanding Webhook Documentation:
  • Webhook Management API - Endpoints you call to create, list, update, and delete webhook subscriptions
  • Webhook Callbacks - Documentation of the events TitanX sends to your webhook endpoints
  • This guide - Step-by-step instructions for implementing webhooks

How Webhooks Work

  1. Configure a webhook - Set up an HTTPS endpoint URL and subscribe to specific event types
  2. Events occur - When an event happens (e.g., a contact is scored), TitanX creates an event
  3. TitanX sends a POST request - We send the event data to your webhook URL with an HMAC signature
  4. Your server responds - Your endpoint processes the event and returns a 2xx status code
  5. Acknowledgment - We consider the delivery successful when we receive a 2xx response

Supported Events

job.contact.scored

Fired when a contact completes the scoring process. This event provides the full contact object with all phone numbers annotated with their propensity scores. When it fires:
  • After a contact has been fully processed and scored
  • For all of your contacts regardless of how they were submitted — via the scoring API or the TitanX App
  • Only for contacts belonging to the authenticated user

job.completed

Fired once per job, after the job reaches a terminal state — either all contacts were scored, or all contacts were rejected during enrichment (finalized as “Not Enriched”). This is a job-level bookkeeping signal that the batch is done — it carries no contact data. Your contact results are delivered separately and in real time via job.contact.scored (one event per contact); job.completed is just an optional checkpoint to know a whole batch has finished — for progress tracking or reconciliation — and is not required to receive results. See the job.completed callback reference for the full payload specification.

Webhook Payload Structure

All webhook events follow a consistent structure:

Fields

  • payload - The event data. For job.contact.scored events, contains a contact key with the full Contact object (see the Webhook Callbacks reference for the complete field list)
  • payload.contact - The complete scored Contact object with all available fields
  • payload.job - Context about the job that triggered this event
  • payload.job.id - The ID of the originating job. Use this to correlate events back to a specific job. May be null for legacy events.
  • payload.job.type - The type of job that produced this event. Use this to route handling logic, as different job types annotate different fields. May be null for legacy events.
  • eventType - The type of event (such as “job.contact.scored”)
  • timestamp - Unix timestamp in milliseconds when the event occurred
  • apiVersion - API version (currently “v2”)
  • id - Unique identifier for this webhook event (use for idempotency)

Example: job.contact.scored Payload

The payload.contact contains the complete Contact object with all fields. Here’s an example with commonly used fields:
The complete Contact object includes 60+ fields covering contact details, phone numbers, address information, company firmographics, and more. Phone data is provided in the canonical phones[] array — each entry includes number, status, type, country, region, position, and ivrPath, and the array also surfaces enrichment phones beyond the five-number cap. If you just want the one number to dial, read bestPhone — TitanX’s pick of the highest-propensity, most reachable number from phones[] (null when none is suitable). The flat phone/phone2phone5 fields (and their Status/Type/Country/Region variants) remain for backward compatibility but are deprecated. See the Webhook Callbacks reference for the exhaustive field list.

Security: Verifying Webhook Signatures

Every webhook request includes an X-TitanX-Signature header containing an HMAC-SHA256 signature. You must verify this signature to ensure the request came from TitanX and hasn’t been tampered with.

Signature Format

The signature is computed as:

Verification Example (Node.js)

Verification Example (Python)

Setting Up Webhooks

Step 1: Create Your Webhook Endpoint

Create an HTTPS endpoint that:
  • Accepts POST requests
  • Verifies the X-TitanX-Signature header
  • Returns a 2xx status code within 10 seconds
  • Handles events idempotently (using the event id field)
For detailed information about the webhook callback format and fields, see the Webhook Callbacks documentation.

Step 2: Create the Webhook via API

Use the Create Webhook endpoint from the Webhook Management API:
Important: The response includes the webhook secret which is only shown once. Store it securely - you’ll need it to verify webhook signatures.
Field naming: you send events, but responses return triggers. When you create a webhook you supply the subscribed event types in an events array. The webhook objects the API returns — both from this create call and from List All Webhooks — expose that same subscribed list under a field named triggers, not events. They mean the same thing; only the field name differs between request and response. When parsing webhook responses, read triggers.(Separately, each delivered webhook callback identifies its own event in an eventType field — see Webhook Callbacks. That value will be one of the event types you subscribed to.)

Step 3: Test Your Webhook

After creating your webhook, score some contacts via the API and verify your endpoint receives the events.

Rate Limiting

Webhooks are subject to rate limiting to prevent overwhelming your servers:
  • Default rate limit: 5 requests per second per user
  • Configurable: Rate limits can be adjusted via entitlements
  • Flow control: Webhooks for the same user and event type share a rate limit key
If you need higher rate limits, contact support.

Best Practices

1. Respond Quickly

Return a 2xx status code as soon as you receive the webhook. Process the event asynchronously if needed:

2. Implement Idempotency

Use the event id to prevent processing duplicate events:

3. Handle Errors Gracefully

If your endpoint returns a non-2xx status code, we’ll consider the delivery failed. Implement retry logic in your application for transient failures.

4. Monitor Webhook Health

  • Log all webhook events for debugging
  • Monitor success/failure rates
  • Set up alerts for consistent failures
  • Use the webhook status endpoint to pause webhooks during maintenance

5. Use HTTPS

Webhook URLs must use HTTPS. This ensures:
  • Data is encrypted in transit
  • Your endpoint is authenticated
  • Man-in-the-middle attacks are prevented

Managing Webhooks

List All Webhooks

Update Webhook Status

Pause a webhook without deleting it:
Reactivate:

Delete a Webhook

Understanding Contact Scores

When you receive a job.contact.scored event, the contact will include phone status annotations:

Phone Statuses

enum
The status of the phone number
IVR stands for Interactive Voice Response, which you may know as a dial tree

Lead Status

Each contact has an overall leadStatus field that represents the highest scoring phone number:
enum
The overall status of the contact based on the highest scoring phone status.

Troubleshooting

Webhook Not Firing

  • Verify the webhook status is “active”
  • Check that contacts belong to the authenticated user (the event fires for both API- and App-submitted contacts, so the source is not the issue)
  • Verify your endpoint is accessible from the internet

Signature Verification Failing

  • Ensure you’re using the raw request body (not parsed JSON)
  • Verify you’re using the correct webhook secret
  • Check that you’re computing Base64-encoded HMAC-SHA256
  • Verify the signature header name is exactly X-TitanX-Signature

Timeouts

  • Return a 2xx response within 10 seconds
  • Process events asynchronously if they take longer
  • Consider using a message queue for complex processing

Need Help?

If you have questions or need assistance with webhooks: