Overview
The contact lookup webhook lets you identify unknown inbound callers by looking up their phone number in your system before the call connects. When enabled, telli sends a POST request to your endpoint with the caller’s phone number, and your endpoint responds with the contact’s details.
This is useful when you want to:
- Greet callers by name
- Route calls based on customer data
- Pass custom properties to your agent’s prompt via dynamic variables
The webhook is called before the call connects. The timeout you configure adds to the caller’s ringing time. Keep your endpoint fast and set the timeout as low as possible.
Setup
- Go to Settings → Integrations
- Select Contact Lookup Webhook
- Enter your webhook URL
- Set a timeout (1–10 seconds)
- Optionally add custom headers and query parameters
- Enable the integration and click Save
Request
When an inbound call arrives from an unknown number, telli sends a POST request to your webhook URL:
{
"event": "contact_lookup",
"phone_number": "+14155551234"
}
| Field | Type | Description |
|---|
event | string | Always "contact_lookup" |
phone_number | string | The caller’s phone number in E.164 format |
Any custom headers and query parameters you configured in the integration settings are included in the request.
Signature verification
The request includes an x-telli-signature header that you can use to verify the request was sent by telli. The signature is an HMAC-SHA256 hash of the request body, signed with your account’s API key.
Response
Your endpoint should return a JSON response with the contact’s details:
{
"contact": {
"first_name": "Jane",
"last_name": "Doe",
"salutation": "Ms.",
"email": "[email protected]",
"external_id": "usr_12345",
"external_url": "https://crm.example.com/contacts/12345",
"phone_number": "+14155551234",
"properties": {
"plan": "enterprise",
"account_manager": "John Smith",
"priority": 1
}
}
}
| Field | Type | Required | Description |
|---|
first_name | string | Yes | Contact’s first name (1–50 characters) |
last_name | string | Yes | Contact’s last name (1–50 characters) |
salutation | string | No | Salutation or title (e.g. “Mr.”, “Ms.”, “Dr.”) |
email | string | No | Contact’s email address |
external_id | string | No | Your system’s identifier for the contact. If a contact with this ID already exists, it will be updated instead of creating a duplicate. |
external_url | string | No | A URL to the contact in your system |
phone_number | string | No | The contact’s phone number (defaults to the caller’s number if omitted) |
properties | object | No | Custom contact properties. Keys must match your configured property keys. Values must match the property’s data type (string, number, boolean, date, select value, or array for multi-select). |
Unknown caller
If the phone number is not found in your system, return an empty contact:
Custom properties
The properties object lets you pass custom data that matches your contact properties configuration. Property keys must match the keys you’ve defined in Settings → Contact properties. Values that don’t match a defined property key are ignored.
Error handling
- If your endpoint returns a non-2xx status code, the call proceeds with an unknown contact
- If your endpoint doesn’t respond within the configured timeout, the call proceeds with an unknown contact
- If the response body doesn’t match the expected format, the call proceeds with an unknown contact
In all error cases, the call is never blocked — the caller will always be connected.
Example implementation
Here’s a minimal example using Node.js and Express:
app.post("/telli/contact-lookup", (req, res) => {
const { phone_number } = req.body;
// Look up the contact in your database
const contact = db.findContactByPhone(phone_number);
if (!contact) {
return res.json({ contact: null });
}
res.json({
contact: {
first_name: contact.firstName,
last_name: contact.lastName,
email: contact.email,
external_id: contact.id,
properties: {
plan: contact.plan,
account_manager: contact.accountManager,
priority: contact.priority,
},
},
});
});