Recipes
Sync contacts
Written beside the API’s code, and read from it every hour.
Keep the contacts that pop up on calls in step with your own system.
GET /v1/contacts/fieldsreturns your field names. Fields withis_matchdecide which contact a row updates. Fields withis_phonehold numbers.POST /v1/contactstakes up to 500 contacts per request. A row updates the contact whose match fields all equal it, or creates a new one.DELETE /v1/contactsremoves the ids you deleted on your side, up to 500 per request.
# 1. Your field names
curl https://api.vocatech.com/v1/contacts/fields \
-H "Authorization: Bearer $VOCATECH_API_KEY"
# 2. Create or update, up to 500 per request
curl -X POST https://api.vocatech.com/v1/contacts \
-H "Authorization: Bearer $VOCATECH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contacts": [
{ "fields": { "Name": "Jordan Reyes", "Phone": "7185550142", "Account": "A-1042" } },
{ "fields": { "Name": "Riley Morgan", "Phone": "7185550143;7185550144", "Account": "A-1043" } }
]
}'
# 3. Delete, up to 500 ids per request
curl -X DELETE https://api.vocatech.com/v1/contacts \
-H "Authorization: Bearer $VOCATECH_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "ids": [5031, 5032] }'import { vt } from './vocatech.mjs';
// 1. Your field names, and which ones decide "same contact"
const { fields } = await vt('GET', '/v1/contacts/fields');
console.log(fields.map((f) => (f.is_match ? `${f.name} (match)` : f.name)));
// 2. Create or update, up to 500 per request. Use your own field names.
const rows = [
{ fields: { Name: 'Jordan Reyes', Phone: '7185550142', Account: 'A-1042' } },
{ fields: { Name: 'Riley Morgan', Phone: '7185550143;7185550144', Account: 'A-1043' } },
];
for (let i = 0; i < rows.length; i += 500) {
const res = await vt('POST', '/v1/contacts', { contacts: rows.slice(i, i + 500) });
console.log(res.summary);
for (const e of res.errors) console.warn('row', i + e.index, e.message);
}
// 3. Remove the ones you deleted on your side
await vt('DELETE', '/v1/contacts', { ids: [5031, 5032] });from vocatech import vt
# 1. Your field names, and which ones decide "same contact"
fields = vt("GET", "/v1/contacts/fields")["fields"]
print([f["name"] + (" (match)" if f["is_match"] else "") for f in fields])
# 2. Create or update, up to 500 per request. Use your own field names.
rows = [
{"fields": {"Name": "Jordan Reyes", "Phone": "7185550142", "Account": "A-1042"}},
{"fields": {"Name": "Riley Morgan", "Phone": "7185550143;7185550144", "Account": "A-1043"}},
]
for i in range(0, len(rows), 500):
res = vt("POST", "/v1/contacts", {"contacts": rows[i:i + 500]})
print(res["summary"])
for e in res["errors"]:
print("row", i + e["index"], e["message"])
# 3. Remove the ones you deleted on your side
vt("DELETE", "/v1/contacts", {"ids": [5031, 5032]})<?php
require __DIR__ . '/vocatech.php';
// 1. Your field names, and which ones decide "same contact"
$fields = vt('GET', '/v1/contacts/fields')['fields'];
foreach ($fields as $f) {
echo $f['name'], $f['is_match'] ? ' (match)' : '', PHP_EOL;
}
// 2. Create or update, up to 500 per request. Use your own field names.
$rows = [
['fields' => ['Name' => 'Jordan Reyes', 'Phone' => '7185550142', 'Account' => 'A-1042']],
['fields' => ['Name' => 'Riley Morgan', 'Phone' => '7185550143;7185550144', 'Account' => 'A-1043']],
];
foreach (array_chunk($rows, 500) as $n => $batch) {
$res = vt('POST', '/v1/contacts', ['contacts' => $batch]);
foreach ($res['errors'] as $e) {
echo 'row ', $n * 500 + $e['index'], ': ', $e['message'], PHP_EOL;
}
}
// 3. Remove the ones you deleted on your side
vt('DELETE', '/v1/contacts', ['ids' => [5031, 5032]]);POST /v1/contacts response200 OK
{
"summary": { "total": 2, "created": 1, "updated": 1, "errors": 0 },
"contacts": [
{
"contact": { "id": 5012, "fields": { "Name": "Jordan Reyes", "Phone": "7185550142", "Account": "A-1042" } },
"action": "updated"
},
{
"contact": { "id": 5033, "fields": { "Name": "Riley Morgan", "Phone": "7185550143;7185550144", "Account": "A-1043" } },
"action": "created"
}
],
"errors": []
}- Use the field names exactly as
GET /v1/contacts/fieldsreturns them. Unknown names are ignored. - Phone fields keep digits only and drop a leading 1. Put several numbers in one field with semicolons:
7185550143;7185550144. - Values over 255 characters are cut.
- A batch answers
200with a summary, and one entry inerrorsfor each row that failed, by its index in your batch. A single contact sent as{"fields": {...}}answers201when created and200when updated.
