Webhooks
Tomba can send data to your server in three ways: a callback for an individual API request when you add webhook_url, a signed event when a bulk job created with webhook_url ends, and a lead webhook that fires whenever a lead is created in your account.
Per-request callbacks
Add webhook_url to a supported request. The API still returns the result in the response as usual. When the result qualifies, Tomba also sends it to your URL.
Code
Supported endpoints
| Endpoint | Callback sent when |
|---|---|
GET /domain-search | At least one email address is returned |
GET /email-finder | An address is returned with a verification status other than unknown |
GET /author-finder | An address is returned |
GET /enrich | An address is returned with a verification status other than unknown |
GET /linkedin | An address is returned |
GET /email-verifier | The status is not disposable or unknown |
GET /phone-finder | A single valid phone number is returned. Not sent with full=true. |
GET /people/find | A person is returned |
GET /combined/find | A person is returned |
Other endpoints ignore webhook_url.
Delivery
Tomba sends a POST request whose body is the same JSON as the API response. These headers are included:
| Header | Value |
|---|---|
Content-Type | application/json |
Accept | application/json |
User-Agent | Tomba-Webhook/1.0 |
X-Tomba-Timestamp | Unix time, in seconds, of the delivery attempt |
- Each attempt times out after 30 seconds. A network error or a non-2xx response is retried, up to 4 attempts, 2 seconds apart. Respond with a 2xx status as soon as you've stored the payload.
- Callbacks aren't signed. Put a hard-to-guess token in the URL, as in the example above, and reject requests that don't carry it.
- The URL must use a public domain name; IP addresses and
localhostfail with422. Plainhttp://URLs are accepted, but usehttps://. - A callback is also sent for a duplicate request, which isn't charged. Changing
webhook_urlmakes the request a new one for the duplicate rule.
Bulk job events
Set webhook_url when you create a bulk job, and Tomba sends a signed POST request to that URL when the job ends:
type | Sent when |
|---|---|
bulk.completed | The job completed. data.metrics holds its results, and data.links.download its file. |
bulk.failed | The job failed. data.error_message says why. |
bulk.cancelled | The job was cancelled while running. Cancelling a pending job sends no event. |
A retried job sends a new event when it ends, with data.attempt increased by one.
Code
| Field | Description |
|---|---|
type, created_at | The event, and when it was created |
data.bulk_id, data.bulk_type, data.name, data.status | The job. Phone finder jobs are phone. |
data.attempt | 1 for the first run, then one more for each retry |
data.error_message | Why the job failed. bulk.failed only. |
data.started_at, data.completed_at | When the job started and completed |
data.metrics | The job's results, as in Job fields. bulk.completed only. |
data.billed_on_download | Always true: the job is charged when you first download its results, not when the event is sent. See Billing. |
data.links | api: the job. download: its results file, bulk.completed only. app: the job in the dashboard. |
Headers
The events follow the Standard Webhooks specification:
| Header | Value |
|---|---|
Content-Type | application/json |
User-Agent | Tomba-Webhooks/1.0 |
webhook-id | The event's ID, such as blk_4521_1_bulk.completed. It's the same on every attempt; use it to skip duplicates. |
webhook-timestamp | Unix time, in seconds, of the attempt |
webhook-signature | v1, followed by the base64-encoded HMAC-SHA256 signature |
Verify the signature
Get your secret from GET /v1/bulk/webhook-secret. It's created with your first bulk job that has a webhook_url, or by this call, and it signs the events of all your jobs. To verify an event:
- Remove the
whsec_prefix from the secret and base64-decode the rest: that's the key. - Compute the HMAC-SHA256 of
{webhook-id}.{webhook-timestamp}.{body}with the key, wherebodyis the raw request body, and base64-encode it. - Compare the result with the part of
webhook-signatureafterv1,. Reject events whose timestamp is more than 5 minutes old.
POST /v1/bulk/webhook-secret/rotate replaces the secret. The old one stops working at once, including for the events of jobs that are already running.
Delivery and retries
- Each attempt times out after 10 seconds. A network error or a non-2xx response is retried, up to 5 attempts: the first right away, then 10 seconds, 30 seconds, 2 minutes, and 5 minutes after the previous one. A
410 Goneresponse stops the retries. webhook_urlmust be anhttps://URL of at most 2,048 characters, without a username or password, whose host resolves to a public IP address. Otherwise, creating the job fails with422. Deliveries connect only to public IP addresses.- Each attempt is recorded in the job's history as
webhook_deliveredorwebhook_failed, with its HTTP status; seeGET /v1/bulk/{type}/{id}/history.
Lead events
The lead webhook calls your URL every time a lead is created in your account. It isn't sent when a lead is updated or deleted, and it requires a paid plan.
Set it up under Webhooks in the dashboard. An account has one lead webhook:
| Setting | Description |
|---|---|
| Name | 2 to 50 characters. |
| URL | Where Tomba sends the lead. Tomba stores the URL in lowercase, including the path and query, so use a lowercase URL. |
| Method | POST, PUT, PATCH, GET, or HEAD. Use POST. |
| Header | One custom header name and value, such as Authorization: Bearer <token>. Use it to authenticate Tomba's requests. |
| Status | Whether the webhook is enabled. New webhooks start disabled. |
Tomba sends the lead with Content-Type: application/json, the User-Agent Mozilla/5.0 (compatible; TombaHooks/1.0; +https://tomba.io), and your custom header:
Code
| Field | Type | Description |
|---|---|---|
email | string | Lead's email address |
website | string | Company website |
company | string or null | Company name |
first_name, last_name | string or null | Lead's name |
phone | string or null | Phone number |
position | string or null | Job title |
twitter, linkedin | string or null | Social profiles |
notes | string or null | Notes saved with the lead |
score | integer | Lead score |
The body has no event name, ID, or timestamp, and Tomba doesn't record whether delivery succeeded. If you need a complete record, reconcile with GET /v1/leads.