Lynkist Developers

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.

ScopeEndpoints
contacts:readGET /contacts, POST /contacts/search, GET /contacts/{id}
contacts:writePOST /contacts, POST /contacts/bulk, PATCH /contacts/{id}, DELETE /contacts/{id}

Base path: /api/v1/public/contacts

Contact object

FieldTypeNotes
idUUIDServer-assigned. Persistent across updates.
first_namestring (1-255)Required on create.
last_namestring | null
phonestring (≤20) | nullE.164 format recommended (e.g. +919999999999).
emailstring | nullRFC-5322 valid email.
companystring | null
job_titlestring | null
statusstring | nullFree-form. Conventional values: active, lead, customer.
tagsstring[]Arbitrary labels.
custom_fieldsobjectFree-form JSON. Used by template variable mapping in campaigns.
created_atISO-8601
updated_atISO-8601 | null

GET /contacts — List contacts

Paginated list of contacts. Supports a free-text search and a status filter.

Query parameters

ParamTypeDefaultNotes
searchstringMatches first_name, last_name, email, company.
statusstringExact match.
pageinteger ≥11
limit1-10020
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

StatusWhen
400Body missing required fields or malformed JSON
401Missing / invalid API key
403Key lacks contacts:read or contacts:write
404Contact ID does not exist or belongs to another tenant
422Validation error (Pydantic) — see field-level details
429Rate limit hit

See Errors for the response envelope.

Webhooks

EventWhen
contact.createdAfter POST /contacts or bulk-create row
contact.updatedAfter PATCH /contacts/{id}
contact.deletedAfter DELETE /contacts/{id}
contact.note_addedWhen a note is attached (dashboard today)
contact.communication_addedWhen communication history is recorded
Contacts — Lynkist Developers | Lynkist