# Sync contacts

Keep the contacts that pop up on calls in step with your own system.

1. `GET /v1/contacts/fields` returns your field names. Fields with `is_match` decide which contact a row updates. Fields with `is_phone` hold numbers.
2. `POST /v1/contacts` takes up to 500 contacts per request. A row updates the contact whose match fields all equal it, or creates a new one.
3. `DELETE /v1/contacts` removes the ids you deleted on your side, up to 500 per request.

**curl**

```bash
# 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] }'
```

**Node**

```javascript
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] });
```

**Python**

```python
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**

```php
<?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 OKCopy**

```json
{
  "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/fields` returns 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 `200` with a summary, and one entry in `errors` for each row that failed, by its index in your batch. A single contact sent as `{"fields": {...}}` answers `201` when created and `200` when updated.
