Skip to content

Mirror a Talki appointment

Webhooks for immediate updates, the appointment change feed for backfill and repair. If the integration also writes bookings, idempotency and the event’s origin are what keep it from feeding itself.

  • Talki decides whether a Talki appointment commits. Mirror the result; do not re-arbitrate it.
  • Provider calendars can narrow availability, and are not the source of truth for Talki appointments.
  • The Talki appointment ID is the external unique key.

Subscribe to:

  • appointment.created: upsert the booking.
  • appointment.updated: replace the mirrored fields for the same ID, including a restored appointment.
  • appointment.cancelled: mark the same ID cancelled.

A reschedule on a call or through the API keeps the ID and arrives as appointment.updated; one in the Talki app can keep the existing ID too. Handle the event types literally.

notes is the note on the booking: what POST /v1/appointments sent as notes, or what the assistant wrote on a booking taken on a call. It is null when there is none.

Deleting a service sends no appointment event. Its bookings keep their ID, with service.id null and service.name the name they were booked under: a rename after booking does not carry over, so it can differ from the name you mirrored. Their updated_at does not change, so an incremental walk of the GET /v1/appointments feed does not return them again; a full walk shows them that way. On service.deleted, clear that service’s ID on the bookings you mirror.

Verify and deduplicate the envelope as in the call activity guide. On API writes, origin.credential_id names the key behind the event and origin.idempotency_key ties it to your request, so you can either skip your own writes or apply them as idempotent confirmations.

Walk GET /v1/appointments?limit=100 from no cursor. Cancelled appointments are in the feed and must stay in it during a sync. Upsert by ID, store every non-null next_cursor, continue while has_more is true.

Later polls resume from the stored cursor. It comes back on the final non-empty page because it records your position, not the existence of a next page. updated_at is not a watermark.

  1. Read the service from GET /v1/services/{service_id}.
  2. Query GET /v1/availability for the service, local date range, and quantity.
  3. Choose a start and end inside a returned window.
  4. Send POST /v1/appointments with a new Idempotency-Key.

Availability is advisory: on a booking conflict, refresh the windows and offer another time. Retry a lost or transient response with the same key and the same request, and the first result is replayed instead of booking twice.

PATCH /v1/appointments/{id} with both start_at and end_at moves a booking and keeps its ID. A booking of one service with a duration_minutes must keep that length or the length it has now, so a booking the owner lengthened in Talki can move as it is. A move that keeps neither is refused with 400 invalid_parameter, as moving one edge of such a booking normally is. A booking of several services, of a service booked by the day or night, of a deleted service or of none is not held to a length. DELETE, with an idempotency key, cancels it: the record stays readable with status: "cancelled" and stays in the feed.