Skip to main content

Contacts

A contact is a person in your CRM. All contact endpoints require the crm.contacts.read or crm.contacts.write scope.

Endpoints

GET/api/workspace/v1/contacts
GET/api/workspace/v1/contacts/{id}
POST/api/workspace/v1/contacts
PATCH/api/workspace/v1/contacts/{id}

The contact object

FieldTypeDescription
first_namestringGiven name
last_namestringFamily name
emailstringPrimary email (normalised to lowercase)
phonestringPrimary phone (E.164 recommended, we normalise)
job_titlestringFree-form job title
crm_company_idintegerLink to an existing CRM company
lifecycle_stageenumOne of lead | customer | opportunity | other (default: lead)
timezonestringIANA zone e.g. Europe/Amsterdam
preferred_languagestring(2)ISO 639-1 code, e.g. nl or en
countrystring(2)ISO 3166-1 alpha-2, e.g. NL
notesstringFree-form internal notes (max 5000 chars)
custom_fieldsobjectMerged with existing custom fields on update

On create, at least one of email, phone, or (first_name + last_name) is required.

List contacts

Supports cursor pagination (limit, starting_after) and filters: email, phone, search, updated_after, created_after, archived.

curl "https://app.staffifyai.com/api/workspace/v1/contacts?limit=50&updated_after=2026-09-01T00:00:00Z" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY"

Retrieve a contact

curl "https://app.staffifyai.com/api/workspace/v1/contacts/1893" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY"

Create a contact

Idempotent when you pass an Idempotency-Key. Returns 201 with the new contact.

curl "https://app.staffifyai.com/api/workspace/v1/contacts" \
  -X POST \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 1c1a-4a8f-9b2e" \
  -d '{
    "first_name": "Jan",
    "last_name": "de Vries",
    "email": "[email protected]",
    "lifecycle_stage": "lead"
  }'

Update a contact

Only fields present in the body are updated. Pass is_archived: true to soft-delete (there is no hard DELETE endpoint).

curl "https://app.staffifyai.com/api/workspace/v1/contacts/1893" \
  -X PATCH \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "job_title": "CTO",
    "custom_fields": { "source": "website" }
  }'

Delete a contact

Soft-delete places the contact in a 30-day recycle bin. It disappears from default list queries and returns 404 on retrieve. Use ?deleted=true on list to see recycled contacts, or ?deleted=any for both live + deleted. Requires the crm.contacts.delete scope (separate from write).

curl -X DELETE "https://app.staffifyai.com/api/workspace/v1/contacts/1893" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY"

Restore a contact

Within the 30-day window you can restore a soft-deleted contact. After the window a nightly purge cron hard-deletes the row for good — restore returns 404 then.

curl -X POST "https://app.staffifyai.com/api/workspace/v1/contacts/1893/restore" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY"

Bulk-delete contacts

Soft-delete up to 500 contacts in one call. Response reports how many rows matched (a missing id is silently skipped, not an error). Idempotent — re-sending the same ids keeps the same deleted_at.

curl -X POST "https://app.staffifyai.com/api/workspace/v1/contacts/bulk-delete" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "ids": [1893, 1894, 1895] }'
Contacts - Workspace API - Staffify