contacts:read (and contacts:write if you write the CRM’s id back), and a place to keep one timestamp between runs.
sync-contacts.mjs
lastRun, copies every contact.
- Writing
external_idchanges the contact, so it comes back once in the next run. Theif (!contact.external_id)check makes that second pass a no-op. - Each contact can have one
external_id, unique in the workspace. Two contacts with the same id return409conflict. - For the conversation behind a lead, list
GET /v1/conversations?has_lead=true&updated_since=…and match oncontact. - If you’d rather not poll, subscribe a webhook to
lead.capturedand upsert the contact indata.object. Keep this job as a nightly safety net for any webhook you miss.
GET /v1/contacts?email=… shows the CRM’s id as external_id.