Recipes
Look up a caller
Written beside the API’s code, and read from it every hour.
Two routes answer "who is this?". One is rich, one is lean.
| Route | Answers with | Use it for |
|---|---|---|
GET /v1/callers/{number} | Contacts (up to 5), recent calls with who handled them and the AI summary, texts and WhatsApp messages, and the last call each way | An AI agent or a screen that needs context before hello |
GET /v1/contacts/lookup?phone= | The contact records for the number, up to 10 | Matching a caller to a record in your CRM |
# Everything about one number: the last 30 days, up to 5 calls
curl "https://api.vocatech.com/v1/callers/7185550142?days=30&limit=5" \
-H "Authorization: Bearer $VOCATECH_API_KEY"
# Only the contact records
curl "https://api.vocatech.com/v1/contacts/lookup?phone=7185550142" \
-H "Authorization: Bearer $VOCATECH_API_KEY"import { vt } from './vocatech.mjs';
// Everything about one number: the last 30 days, up to 5 calls
const who = await vt('GET', '/v1/callers/7185550142?days=30&limit=5');
const lastCall = who.last_call ? who.last_call.summary : 'no calls';
console.log(who.counts, lastCall);
// Only the contact records, for a screen pop or a CRM match
const hit = await vt('GET', '/v1/contacts/lookup?phone=7185550142');
if (hit.found) console.log(hit.contacts.map((c) => c.fields));from vocatech import vt
# Everything about one number: the last 30 days, up to 5 calls
who = vt("GET", "/v1/callers/7185550142", params={"days": 30, "limit": 5})
print(who["counts"], who["last_call"]["summary"] if who["last_call"] else "no calls")
# Only the contact records, for a screen pop or a CRM match
hit = vt("GET", "/v1/contacts/lookup", params={"phone": "7185550142"})
if hit["found"]:
print([c["fields"] for c in hit["contacts"]])<?php
require __DIR__ . '/vocatech.php';
// Everything about one number: the last 30 days, up to 5 calls
$who = vt('GET', '/v1/callers/7185550142?days=30&limit=5');
echo $who['last_call']['summary'] ?? 'no calls', PHP_EOL;
// Only the contact records, for a screen pop or a CRM match
$hit = vt('GET', '/v1/contacts/lookup?phone=7185550142');
if ($hit['found']) {
print_r(array_column($hit['contacts'], 'fields'));
}GET /v1/callers response200 OKTrimmed
{
"number": "7185550142",
"days": 30,
"contacts": [
{ "id": 5012, "fields": { "Name": "Jordan Reyes", "Phone": "7185550142", "Account": "A-1042" } }
],
"calls": [
{
"call_id": "8a1f3c2e-5b7d-4e9a-9c1b-2d4e6f8a0b1c",
"direction": "incoming",
"status": "answered",
"start_time": "2026-09-24T13:02:11.000Z",
"end_time": "2026-09-24T13:06:49.000Z",
"duration": 278,
"remote_name": "Jordan Reyes",
"remote_number": "7185550142",
"our_number": "7185550100",
"handled_by": { "extension": "104", "name": "Maya Chen" },
"summary": "Jordan asked to move the Thursday visit to Friday morning. Maya booked Friday at 9 AM.",
"journey": [
{
"order": 2,
"type": "user",
"extension": "104",
"extension_name": "Maya Chen",
"start_time": "2026-09-24T13:02:24.000Z",
"duration": 265,
"summary": "Jordan asked to move the Thursday visit to Friday morning. Maya booked Friday at 9 AM."
}
]
}
],
"messages": [
{
"channel": "text",
"direction": "outgoing",
"body": "Hi Jordan, your appointment is confirmed for Friday at 9 AM.",
"sent_time": "2026-09-24T13:15:02Z",
"our_number": "7185550100",
"remote_number": "7185550142"
}
],
"last_call": { "call_id": "8a1f3c2e-5b7d-4e9a-9c1b-2d4e6f8a0b1c", "direction": "incoming" },
"last_incoming": { "call_id": "8a1f3c2e-5b7d-4e9a-9c1b-2d4e6f8a0b1c", "direction": "incoming" },
"last_outgoing": null,
"counts": { "contacts": 1, "calls": 1, "messages": 1 }
}GET /v1/contacts/lookup response200 OK
{
"phone": "7185550142",
"found": true,
"contacts": [
{ "id": 5012, "fields": { "Name": "Jordan Reyes", "Phone": "7185550142", "Account": "A-1042" } }
]
}- Any formatting works in the number, and a leading 1 is dropped. It needs at least 7 digits.
dayslooks back 1 to 365 days, 90 by default.limitcaps the calls, and the messages, at 1 to 50, 10 by default.last_call,last_incomingandlast_outgoingrepeat an entry fromcalls, or arenull.- Transcripts stay out unless you add
include=transcripts. Every read is written to your HIPAA access log.
