Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.clarky.ai/llms.txt

Use this file to discover all available pages before exploring further.

Contacts represent the people in your CRM — leads, customers, prospects, and anyone else captured by your agents or imported from another system. Every contact belongs to a specific agent (bot_id) and inherits the workspace from your API key.

The Contact object

id
string
Unique contact identifier.
workspace_id
string
The workspace this contact belongs to.
bot_id
string
The agent that owns this contact.
first_name
string | null
last_name
string | null
emails
array
Array of { email, is_primary } objects. The first item is treated as primary if no is_primary flag is set.
phone_numbers
array
Array of { phone_number, is_primary } objects.
company
string | null
Free-text company name. Use company_id to link to a structured Company record.
company_id
string | null
Foreign key to a Company.
job_title
string | null
lead_source
string | null
tags
string[]
deal_value
number | null
Estimated deal value as a number (currency assumed to match workspace settings).
pipeline_stage_id
string | null
Current stage in a sales pipeline.
contact_type
string | null
Free-form classification (e.g. "lead", "customer").
address_line1
string | null
address_line2
string | null
city
string | null
state
string | null
postal_code
string | null
country
string | null
linkedin_url
string | null
notes
string | null
custom_fields
object
Workspace-defined custom fields, stored as a free-form JSON object.
last_contacted_at
string | null
ISO 8601 timestamp of the most recent activity.
created_at
string
ISO 8601 timestamp.
updated_at
string
ISO 8601 timestamp.

List contacts

method
GET
GET /api/v1/contacts
Returns a paginated list of contacts in the workspace.

Query parameters

ParamTypeDescription
searchstringMatch against name, email, phone, or company
tagsstringComma-separated list of tags to filter by
lead_sourcestringFilter by lead source
pipeline_stage_idstringFilter to contacts in a specific pipeline stage
bot_idstringFilter to contacts owned by a specific agent
created_afterstring (ISO 8601)Created at or after this timestamp
created_beforestring (ISO 8601)Created at or before this timestamp
updated_afterstring (ISO 8601)Updated at or after this timestamp
pageintegerSee Pagination
page_sizeintegerSee Pagination

Example

curl "https://clarky.ai/api/v1/contacts?search=ada&page_size=10" \
  -H "Authorization: Bearer ck_live_example"
{
  "data": [
    {
      "id": "c_01HXYZ...",
      "workspace_id": "w_01HABC...",
      "bot_id": "b_01HDEF...",
      "first_name": "Ada",
      "last_name": "Lovelace",
      "emails": [{ "email": "ada@example.com", "is_primary": true }],
      "phone_numbers": [],
      "company": "Analytical Engines Inc.",
      "company_id": null,
      "job_title": "Founder",
      "lead_source": "website",
      "tags": ["vip"],
      "deal_value": 25000,
      "pipeline_stage_id": "ps_01HGHI...",
      "contact_type": "lead",
      "address_line1": null,
      "address_line2": null,
      "city": "London",
      "state": null,
      "postal_code": null,
      "country": "UK",
      "linkedin_url": null,
      "notes": null,
      "custom_fields": {},
      "last_contacted_at": "2026-04-29T14:00:00.000Z",
      "created_at": "2026-04-12T09:30:00.000Z",
      "updated_at": "2026-04-29T14:00:00.000Z"
    }
  ],
  "pagination": { "page": 1, "page_size": 10, "total": 1, "total_pages": 1 }
}

Get contact by email

method
GET
GET /api/v1/contacts/by-email
Looks up a single contact by primary email address. Returns 404 not_found if no contact matches.

Query parameters

ParamTypeRequiredDescription
emailstringYesEmail to match (case-insensitive)

Example

curl "https://clarky.ai/api/v1/contacts/by-email?email=ada@example.com" \
  -H "Authorization: Bearer ck_live_example"
{
  "data": {
    "id": "c_01HXYZ...",
    "first_name": "Ada",
    "last_name": "Lovelace",
    "emails": [{ "email": "ada@example.com", "is_primary": true }],
    "phone_numbers": [],
    "company": "Analytical Engines Inc.",
    "tags": ["vip"],
    "created_at": "2026-04-12T09:30:00.000Z",
    "updated_at": "2026-04-29T14:00:00.000Z"
  }
}

Get a contact

method
GET
GET /api/v1/contacts/{id}

Example

curl https://clarky.ai/api/v1/contacts/c_01HXYZ \
  -H "Authorization: Bearer ck_live_example"
{
  "data": {
    "id": "c_01HXYZ...",
    "first_name": "Ada",
    "last_name": "Lovelace",
    "emails": [{ "email": "ada@example.com", "is_primary": true }],
    "phone_numbers": [],
    "tags": ["vip"],
    "created_at": "2026-04-12T09:30:00.000Z",
    "updated_at": "2026-04-29T14:00:00.000Z"
  }
}

Create a contact

method
POST
POST /api/v1/contacts
Requires a key with the write scope.

Body fields

FieldTypeRequiredDescription
bot_idstringYesAgent that should own this contact
first_namestringNo
last_namestringNo
emailsarrayNoArray of { email, is_primary }
phone_numbersarrayNoArray of { phone_number, is_primary }
companystringNoFree-text company name
company_idstringNoLink to an existing Company
job_titlestringNo
lead_sourcestringNo
tagsstring[]No
deal_valuenumberNo
pipeline_stage_idstringNo
contact_typestringNo
address_line1stringNo
address_line2stringNo
citystringNo
statestringNo
postal_codestringNo
countrystringNo
linkedin_urlstringNo
notesstringNo
custom_fieldsobjectNo

Example

curl https://clarky.ai/api/v1/contacts \
  -H "Authorization: Bearer ck_live_example" \
  -H "Content-Type: application/json" \
  -d '{
    "bot_id": "b_01HDEF",
    "first_name": "Ada",
    "last_name": "Lovelace",
    "emails": [{ "email": "ada@example.com", "is_primary": true }],
    "company": "Analytical Engines Inc.",
    "tags": ["vip"]
  }'
{
  "data": {
    "id": "c_01HXYZ...",
    "first_name": "Ada",
    "last_name": "Lovelace",
    "emails": [{ "email": "ada@example.com", "is_primary": true }],
    "company": "Analytical Engines Inc.",
    "tags": ["vip"],
    "created_at": "2026-04-29T18:42:00.000Z",
    "updated_at": "2026-04-29T18:42:00.000Z"
  }
}

Update a contact

method
PATCH
PATCH /api/v1/contacts/{id}
Updates the listed fields and leaves everything else untouched. Same fields as Create a contact, except bot_id cannot be changed.

Example

curl -X PATCH https://clarky.ai/api/v1/contacts/c_01HXYZ \
  -H "Authorization: Bearer ck_live_example" \
  -H "Content-Type: application/json" \
  -d '{
    "tags": ["vip", "newsletter"],
    "deal_value": 30000
  }'
{
  "data": {
    "id": "c_01HXYZ...",
    "tags": ["vip", "newsletter"],
    "deal_value": 30000,
    "updated_at": "2026-04-29T18:50:00.000Z"
  }
}

Delete a contact

method
DELETE
DELETE /api/v1/contacts/{id}
Returns 204 No Content with an empty body on success.

Example

curl -X DELETE https://clarky.ai/api/v1/contacts/c_01HXYZ \
  -H "Authorization: Bearer ck_live_example"
Deletion is permanent — there’s no undo.

Bulk upsert contacts

method
POST
POST /api/v1/contacts/upsert
Insert or update up to 200 contacts in a single request. Each input contact is matched against existing contacts in this order:
  1. Primary email (if provided)
  2. Primary phone number (if no email match)
If a match is found, the existing contact is updated. If not, a new contact is created.

Body fields

FieldTypeRequiredDescription
bot_idstringYesAgent to own newly created contacts
contactsarrayYesArray of contact objects (same fields as Create). Max 200.

Example

curl https://clarky.ai/api/v1/contacts/upsert \
  -H "Authorization: Bearer ck_live_example" \
  -H "Content-Type: application/json" \
  -d '{
    "bot_id": "b_01HDEF",
    "contacts": [
      {
        "first_name": "Ada",
        "emails": [{ "email": "ada@example.com", "is_primary": true }]
      },
      {
        "first_name": "Grace",
        "emails": [{ "email": "grace@example.com", "is_primary": true }]
      }
    ]
  }'

Response

{
  "data": {
    "created": [
      {
        "id": "c_01HNEW1...",
        "first_name": "Grace",
        "emails": [{ "email": "grace@example.com", "is_primary": true }]
      }
    ],
    "updated": [
      {
        "id": "c_01HXYZ...",
        "first_name": "Ada",
        "emails": [{ "email": "ada@example.com", "is_primary": true }]
      }
    ],
    "errors": []
  }
}
created
Contact[]
Contacts that were newly inserted.
updated
Contact[]
Contacts that matched an existing record and were updated.
errors
array
Per-row failures as { index, message }. The numeric index is the position of the failing item in the input contacts array. The rest of the batch still succeeds.
Upsert counts as a single write against your rate limit regardless of how many contacts are in the batch — much more efficient than a loop of POST /contacts calls.