Contacts
Manage the tenant's contact directory — list, search, create, update, delete, and bulk-import.
The Contacts API manages your tenant's address book. Contacts are the targets of message sends and the unit of grouping for campaigns.
| Scope | Endpoints |
|---|---|
contacts:read | GET /contacts, POST /contacts/search, GET /contacts/{id} |
contacts:write | POST /contacts, POST /contacts/bulk, PATCH /contacts/{id}, DELETE /contacts/{id} |
Base path: /api/v1/public/contacts
Contact object
| Field | Type | Notes |
|---|---|---|
id | UUID | Server-assigned. Persistent across updates. |
first_name | string (1-255) | Required on create. |
last_name | string | null | |
phone | string (≤20) | null | E.164 format recommended (e.g. +919999999999). |
email | string | null | RFC-5322 valid email. |
company | string | null | |
job_title | string | null | |
status | string | null | Free-form. Conventional values: active, lead, customer. |
tags | string[] | Arbitrary labels. |
custom_fields | object | Free-form JSON. Used by template variable mapping in campaigns. |
created_at | ISO-8601 | |
updated_at | ISO-8601 | null |
GET /contacts — List contacts
Paginated list of contacts. Supports a free-text search and a status filter.
Query parameters
| Param | Type | Default | Notes |
|---|---|---|---|
search | string | — | Matches first_name, last_name, email, company. |
status | string | — | Exact match. |
page | integer ≥1 | 1 | |
limit | 1-100 | 20 |
curl "https://api.lynkist.io/api/v1/public/contacts?search=acme&page=1&limit=20" \
-H "Authorization: Bearer $LYNKIST_API_KEY"200 OK
{
"data": [
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"first_name": "Anurag",
"last_name": "Sharma",
"phone": "+919999999999",
"email": "anurag@acme.test",
"company": "Acme Corp",
"job_title": "Founder",
"status": "lead",
"tags": ["india", "saas"],
"custom_fields": { "plan": "starter" },
"created_at": "2026-05-12T08:00:00Z",
"updated_at": "2026-05-25T11:14:33Z"
}
],
"pagination": {
"page": 1, "limit": 20,
"total_items": 134, "total_pages": 7,
"has_next": true, "has_prev": false
}
}POST /contacts/search — Structured search
Same shape as GET /contacts, but the filters come in the body. Useful when filter values are
long or contain characters awkward to URL-encode.
curl -X POST "https://api.lynkist.io/api/v1/public/contacts/search?page=1&limit=20" \
-H "Authorization: Bearer $LYNKIST_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "search_term": "acme", "status": "lead", "tag": "india" }'Response is identical to GET /contacts.
POST /contacts — Create a contact
curl -X POST https://api.lynkist.io/api/v1/public/contacts \
-H "Authorization: Bearer $LYNKIST_API_KEY" \
-H "Idempotency-Key: 7c4d2e1a-…" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Anurag",
"last_name": "Sharma",
"phone": "+919999999999",
"email": "anurag@acme.test",
"company": "Acme Corp",
"job_title": "Founder",
"tags": ["india", "saas"],
"custom_fields": { "plan": "starter" }
}'201 Created — returns the full contact object (see Contact object).
Emits the contact.created webhook event.
POST /contacts/bulk — Bulk create
Create up to 100 contacts in one request. A per-item error never aborts the batch — failed rows are reported back with the index that failed.
curl -X POST https://api.lynkist.io/api/v1/public/contacts/bulk \
-H "Authorization: Bearer $LYNKIST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contacts": [
{ "first_name": "Anurag", "phone": "+919999999999" },
{ "first_name": "Lara", "email": "lara@acme.test" },
{ "first_name": "" }
]
}'201 Created
{
"total": 3,
"created": 2,
"failed": 1,
"errors": [
{ "index": 2, "error": "first_name must be at least 1 character" }
]
}Each successful item emits a contact.created webhook event.
GET /contacts/{id} — Get a contact
curl https://api.lynkist.io/api/v1/public/contacts/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
-H "Authorization: Bearer $LYNKIST_API_KEY"200 OK — the contact object. 404 if not found.
PATCH /contacts/{id} — Update a contact
Partial update — only the fields you send are changed. Send null to clear a nullable field.
curl -X PATCH https://api.lynkist.io/api/v1/public/contacts/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
-H "Authorization: Bearer $LYNKIST_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "customer", "tags": ["india", "saas", "paid"] }'200 OK — the updated contact. 404 if not found.
Emits contact.updated.
DELETE /contacts/{id} — Archive a contact
Soft-delete: the contact is hidden from listings but its history (messages, campaign membership) is preserved.
curl -X DELETE https://api.lynkist.io/api/v1/public/contacts/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
-H "Authorization: Bearer $LYNKIST_API_KEY"200 OK
{ "message": "Contact deleted" }Emits contact.deleted. 404 if not found.
Errors
| Status | When |
|---|---|
400 | Body missing required fields or malformed JSON |
401 | Missing / invalid API key |
403 | Key lacks contacts:read or contacts:write |
404 | Contact ID does not exist or belongs to another tenant |
422 | Validation error (Pydantic) — see field-level details |
429 | Rate limit hit |
See Errors for the response envelope.
Webhooks
| Event | When |
|---|---|
contact.created | After POST /contacts or bulk-create row |
contact.updated | After PATCH /contacts/{id} |
contact.deleted | After DELETE /contacts/{id} |
contact.note_added | When a note is attached (dashboard today) |
contact.communication_added | When communication history is recorded |