Core concepts
Public objects
Section titled “Public objects”The public contract is intentionally smaller than Talki’s internal data model. Dashboard-only filing state, billing details, provider diagnostics, AI working memory, transcripts, and audio do not become public just because Talki stores or computes them.
REST responses and data.object in webhooks use the same serializers. When the
same Call appears through both surfaces, its public fields have the same names
and meanings.
Sources of truth
Section titled “Sources of truth”- Talki’s database is authoritative for appointments Talki owns. Whether a booking may be committed is decided there, under a lock, after a recount.
- External calendars contribute busy time. Google and Outlook events that Talki does not own become constraints the agent honours during a call. They never decide whether something may be booked.
A connected CRM calendar can eventually follow the same rule: it may block time, but Talki decides whether one of its own appointments commits.
Identifiers
Section titled “Identifiers”Treat every resource ID as an opaque, case-sensitive string. Do not parse it, infer a resource type from its shape, or generate one yourself. Store the Talki ID alongside your own record so webhook redelivery updates instead of duplicates.
Timestamps
Section titled “Timestamps”All public timestamps are RFC 3339 UTC and end in Z. Filter values should also
include an offset. GET /v1/account returns the account’s IANA timezone for UI
and scheduling contexts.
Call timing
Section titled “Call timing”started_atis when the call arrived and is the call-list ordering key.answered_atis when Talki answered.ended_atis an observed teardown time and can benullfor older rows.duration_secondsis the billed span. Do not recompute it from timestamps; small differences are expected.created_atis when the completed call record was written. Use this field for incremental recovery.
Phone identity
Section titled “Phone identity”A phone number in E.164 is how a caller is matched to a contact. Matching is narrower than you might expect on purpose — see the contact-matching rules before assuming a call and a contact will be linked.
Names inferred from a conversation are not published as trusted caller identity.
caller.display_name is null until the name came from a source the account
owner curated or imported.
Pagination
Section titled “Pagination”Call lists are newest-first and use keyset pagination. The cursor is an opaque, versioned position containing the ordering timestamp and an ID tie-breaker.
- Start without
cursor. - If
has_moreis true, sendnext_cursorback exactly as returned. - Keep the same filters while walking every page.
- A malformed or hand-edited cursor returns
invalid_cursor.
Incremental call recovery
Section titled “Incremental call recovery”Calls are immutable. Store the highest created_at you have processed. After an
outage, query created_after from that watermark minus a safety overlap,
walk every page, and deduplicate by call id.
The overlap is required because PostgreSQL assigns the timestamp when the write transaction starts, not when it becomes visible. One minute is ample for the current write path. The filter is inclusive, so seeing the boundary call twice is normal and safer than missing it.
Versioning
Section titled “Versioning”The major API generation lives in the path: /v1. The beta contract is tracked
as dated version 2026-10-01; explicit request-header pinning is planned but is
not required or negotiated by the current endpoints.
Additive fields and event types may appear without a path change. Ignore fields and enum values you do not recognise. Removals, renames, type changes, or meaning changes require a dated contract release and migration notice.
