Skip to content

Create a CRM activity after a call

The smallest complete Talki integration: every finished call becomes an activity attached to a CRM person.

Create a webhook endpoint for call.ended and call.deleted and save its signing secret. Send a ping from the Talki app to prove the route is reachable.

On every request: capture the raw body, verify X-Talki-Signature, insert the envelope id under a unique constraint, and return 204 once the event is durably queued. An id you have already seen is a redelivery — answer 204 and do nothing else.

Read the Call from data.object. Prefer caller.contact_id once you have mapped it; on first encounter, match caller.phone_number in E.164. A withheld number is null, so file an unmatched activity rather than invent an identity.

caller.display_name holds only a name the owner curated or imported, and is legitimately null much of the time.

Key the activity on the Talki Call id. Store the summary, the timing, the caller mapping and whichever appointment_ids your CRM needs, and upsert, so redelivery and REST recovery repair the same record instead of adding one.

On call.deleted, delete the activity, and delete the tasks (step 6) whose request IDs are in data.deleted.unresolved_request_ids: the event is the only trace a deleted call leaves, and its unresolved requests are deleted with it without an event of their own.

Backfill once with GET /v1/calls?sync=true&limit=100. For every page:

  1. Upsert each Call by its Talki ID.
  2. Store next_cursor whenever it is non-null, including on the page where has_more becomes false.
  3. Continue immediately while has_more is true.

On startup and on a schedule, send the stored cursor back with sync=true and repeat. The cursor is a commit-ordered position, so there is no overlap window to tune. Keep the webhook path running for latency; the feed is what makes the copy complete after downtime.

A call where the assistant could not answer a question leaves an unresolved request: a question the assistant recorded, a number to call back, and a status that closes. Walk it with the same loop, on its own cursor:

Terminal window
curl --fail-with-body 'https://api.talki.it/v1/unresolved_requests?limit=100' \
-H "Authorization: Bearer $TALKI_API_KEY"

Create a task keyed on the Talki request ID, attached to the person you resolved in step 3, and link it to call_id so task and activity point at each other. Sync without the status filter: a request that moves to resolved or dismissed comes back through the feed, and that transition is what closes your task. Needs unresolved:read.

When your users close the task with an answer every caller should hear, you can also teach it to the assistant, with knowledge:write.