atteq API
  • Guides
  • Recipes
  • Cookbook
  • API Reference
Information
agents
    List AgentsgetCreate AgentpostDocument AttachmentsgetGet VersiongetEdit DraftpatchReplace Draft GraphputPublish VersionpostGet AgentgetDelete AgentdeleteCopy AgentpostGet DraftgetGet Agent MapgetPending ChangesgetList PlacementsgetRestore VersionpostList VersionsgetGet Mapget
voice_agent
    Open Browser CallpostEnd Browser CalldeleteGet Agent Test LinkgetGet Bridge CeilinggetSet Bridge Ceilingpatch
ai_profiles
    Get Ai Profile CapabilitiesgetList Live SettingsgetCreate Live SettingspostDelete Live SettingsdeleteUpdate Live SettingspatchList Llm SettingsgetCreate Llm SettingspostDelete Llm SettingsdeleteUpdate Llm SettingspatchList ProfilesgetCreate ProfilepostGet ProfilegetDelete ProfiledeleteUpdate ProfilepatchCopy ProfilepostSet Text SectionputSet Voice SectionputList Stt SettingsgetCreate Stt SettingspostDelete Stt SettingsdeleteUpdate Stt SettingspatchList Tts SettingsgetCreate Tts SettingspostDelete Tts SettingsdeleteUpdate Tts SettingspatchList Vad SettingsgetCreate Vad SettingspostDelete Vad SettingsdeleteUpdate Vad Settingspatch
analyst
    List Agent FindingsgetCall Back FindingpostDismiss FindingpostUndo Finding DismissaldeleteTeach FindingpostWatch FindingpostList Question ChartsgetList Tracked QuestionsgetCreate Tracked QuestionpostGet Question Search CostgetSearch For Tracked QuestionpostPropose Tracked QuestionpostDelete Tracked QuestiondeleteUpdate Tracked QuestionpatchGet Reading SwitchgetSet Reading SwitchputGet Agent Summaryget
analytics
    List ChartsgetCreate ChartpostPreview ChartpostGet ChartgetDelete ChartdeleteUpdate ChartpatchRun ChartpostList DatasetsgetList BoardsgetCreate BoardpostGet TraversalgetGet BoardgetDelete BoarddeleteUpdate Boardpatch
authentication
    List InvitationsgetInvite MemberpostRevoke InvitationdeleteResend InvitationpostList MembersgetRemove MemberdeleteGet Member Conversation AccessgetSet Member Conversation AccesspatchSet Member FlagspatchSet Member RolepatchGet OrganizationgetUpdate OrganizationpatchGet Role FlagsgetSet Role Flagspatch
automations
    List AutomationsgetCreate AutomationpostGet AutomationgetDelete AutomationdeleteUpdate AutomationpatchSet Automation EnabledputGet Automation MapgetRun AutomationpostList Automation RunsgetGet Automation Runget
billable-metrics
    List MetricsgetUsage SummarygetGet Metricget
outbound_calls
    Place CallpostList CampaignsgetCreate CampaignpostGet CampaigngetDelete CampaigndeleteUpdate CampaignpatchActivate CampaignpostLink CollectionpostAdd ContactspostAdd Contacts From CollectionpostRemove Contacts From CollectionpostSet Campaign HoursputPreview Campaign HourspostPause CampaignpostGet Campaign SummarygetExclude ContactpostInclude Contactpost
channels
    List ChannelsgetCreate ChannelpostList Thread SubjectsgetClose Channel ThreadpostList Thread DecisionsgetGet Thread Contact FilegetHand Thread To AgentpostList Thread MailgetGet Prepared ReplygetAsk Again For Prepared ReplypostDiscard Prepared ReplypostSend Prepared ReplypostReply On Channel ThreadpostGet ChannelgetDelete ChanneldeleteUpdate ChannelpatchSend On ChannelpostList Channel ThreadsgetList RostergetCreate Roster EntrypostGet Own Roster EntrygetGet Roster EntrygetDelete Roster EntrydeleteUpdate Roster EntrypatchAdd Roster AddresspostChange Roster AddressputRemove Roster Addressdelete
custom-data
    List CollectionsgetCreate CollectionpostList Collection NamesgetGet CollectiongetDelete CollectiondeleteUpdate CollectionpatchAdd FieldpostDelete FielddeleteUpdate FieldpatchImport RecordspostPlan ImportpostPropose ImportpostGet ImportgetList RecordsgetCreate RecordpostBulk Delete RecordspostBulk Set FieldpostCount RecordsgetList Records Of ContactgetDelete Records Of ContactdeleteGet RecordgetDelete RecorddeleteUpdate Recordpatch
connections
    List ConnectionsgetCreate ConnectionpostCreate Forwarded AddresspostCreate Mail ServerpostDiscover Mail ServerpostAuthorize Microsoft MailboxpostList ProvidersgetGet ConnectiongetDelete ConnectiondeleteUpdate ConnectionpatchGet Forwarded AddressgetCheck Forwarded AddresspostList Person GrantsgetSet Person GrantputRemove Person GrantdeleteGet Mail ServergetUpdate Mail ServerpatchList Mail Server FoldersgetEnter Mail Server PasswordputChange Mail Server ServersputTest Mail Server AgainpostGet Microsoft MailboxgetUpdate Microsoft MailboxpatchList Microsoft Mailbox FoldersgetConsent To Microsoft Mailbox WritespostWithdraw Microsoft Mailbox Writesdelete
custom-tools
    List Custom ToolsgetCreate Custom ToolpostGet Custom ToolgetDelete Custom TooldeleteGet Custom Tool DraftgetEdit Custom Tool DraftpatchPublish Custom ToolpostRestore Custom Tool VersionpostTry Custom ToolpostList Custom Tool Versionsget
rag
    List DocumentsgetUpload DocumentpostSearch DocumentspostGet DocumentgetDelete DocumentdeleteDownload DocumentgetReingest Documentpost
flows
    List FlowsgetCreate FlowpostGet FlowgetDelete FlowdeleteRename FlowpatchAdd Flow EdgepostDelete Flow EdgedeleteSet Entry SteppatchAdd SteppostDelete StepdeleteUpdate SteppatchTest FlowpostList Flow Testsget
dynamic_context
    Create GraphpostGet GraphgetDelete GraphdeleteAdd EdgepostDelete EdgedeleteAdd NodepostDelete NodedeleteUpdate NodepatchSet Rootput
inbox
    Get Inbox Open CountgetSet Inbox PreferencespatchGet Inbox RailgetCreate Inbox ViewpostDelete Inbox ViewdeleteUpdate Inbox Viewpatch
handoff
    Assign Threadpost
interactions
    List InteractionsgetCount InteractionsgetGet InteractiongetSet Conversation LabelspostGet TracegetGet TranscriptgetList LabelsgetCreate LabelpostDelete LabeldeleteUpdate Labelpatch
legal
    Agree To Processing AgreementpostAgree To TermspostLegal BoxesgetList Legal DocumentsgetRead Legal DocumentgetList Legal VersionsgetRead Legal VersiongetDownload Legal VersiongetOrganization Legal HistorygetOwn Legal HistorygetObject To SubprocessorspostWithdraw ObjectionpostLegal Pendingget
not-a-tool
    Agree To Processing AgreementpostAgree To TermspostObject To SubprocessorspostWithdraw Objectionpost
memory
    List MemoriesgetList Memory LinesgetCreate Memory LinepostDelete Memory LinedeleteUpdate Memory LinepatchList Memory PeoplegetGet Memory PersongetForget PersondeleteGet Memory SwitchgetSet Memory SwitchputWipe ContactdeleteGet Conversation MemorygetRecall MemoriespostGet MemorygetDelete MemorydeletePatch Memorypatch
notifications
    List InboxgetGet Unread CountgetMark ReadpostMark Unreaddelete
recipes
    List RecipesgetList Installed RecipesgetGet Installed RecipegetUninstall RecipedeleteSet Recipe EnabledputUpdate Recipe ParameterspatchUpdate RecipepostInstall Recipepost
data-retention
    Get RetentiongetSet Retentionpatch
text
    Open ConversationpostClose ConversationpostAnswer ConfirmationpostGet Sent FilegetSend MessagepostSet Modepatch
tools
    List ToolsgetCreate ToolpostList BuiltinsgetImport Mcp ServerpostImport OpenapipostPreview Openapi ImportpostSuggest Tool ExamplespostGet ToolgetDelete TooldeleteUpdate ToolpatchTest ToolpostList Tool Testsget
trunks
    List Transfer DirectorygetCreate Transfer Directory EntrypostGet Transfer Directory EntrygetDelete Transfer Directory EntrydeleteUpdate Transfer Directory EntrypatchList TrunksgetCreate TrunkpostGet TrunkgetDelete TrunkdeleteUpdate TrunkpatchList Forward Recordsget
Schemas
powered by Zudoku
attek API
attek API

interactions


List Interactions

GET
/api/v1/interactions

List every conversation of the organization, open and ended, newest first. Use to browse, search or filter the conversation log. Every filter is optional; several narrow together, and one given several values matches any of them. An unrecognized query parameter is refused with 422 naming it.

  • channel: voice for calls, text for messages.
  • state: open or ended.
  • channel_key: one or more inbox channels.
  • holder: agent, waiting or a person's id, each matching open conversations only; unassigned is every conversation nobody is answering -- waiting for a person, or ended while it waited.
  • counterparty: the other party's number (any spelling), an address prefix, or the conversation's own id.
  • handed_over: whether a person was ever asked for or ever had it.
  • unreplied=true: an inbound conversation never answered.
  • unanswered=true: an ended conversation the other party never spoke in.
  • draft_test: true narrows to agent-draft tests, false excludes them.
  • min_duration_seconds / max_duration_seconds: ended calls only.
  • record_id: conversations tied to one record.
  • label: one or more label ids; a conversation carrying any of them.
  • prepared_reply: ready or outdated, or both; an open thread whose agent prepared a reply for a person to review, in that state.
  • since / until: bound when it last moved, [since, until), each with a UTC offset.

A value a filter cannot read is refused with 422. GET /interactions/count says how many match, with the same filters and no paging. A reader without conversation_details gets each row without the details-only fields.

List Interactions › query Parameters

inbox_order
​boolean
Default: false
limit
​integer · min: 1 · max: 200
Default: 50
offset
​integer · min: 0
Default: 0
channel
​
direction
​
agent_id
​
answered_by
​
end_reason
​
open_only
​boolean
Default: false
unanswered
​
draft_test
​
campaign_id
​
person_state
​
since
​
until
​
state
​
channel_key
​
holder
​
counterparty
​
handed_over
​
unreplied
​
min_duration_seconds
​
max_duration_seconds
​
record_id
​
label
​
prepared_reply
​

List Interactions › Responses

Successful Response

​InteractionOut[]
One conversation, as the log shows it.
InteractionOut
channel
​Channel · enum · required

Voice and text are two channels over one graph, not two kinds of record.

Enum values:
voice
text
direction
​backend__features__interactions__schemas__Direction · enum · required
Enum values:
inbound
outbound
id
​string · uuid · required
is_open
​boolean · required
org_id
​string · uuid · required
​RunSettings · required

The settings a conversation actually ran with, copied in as values.

An AI profile is not frozen into an agent's published version, so the version alone cannot say how a conversation sounded. The profile id is kept for provenance; the provider, model and voice are kept because they are the answer. used_standby records that a standby served the conversation instead of some component's first choice — the same fields still describe what was actually served — and standby_component names which one switched.

​backend__features__interactions__schemas__Source · required

Source attribution, as recorded. kind says which of the rest is meaningful; the others stay unset.

connection_id and address are CHANNEL's pair, and they are two fields for the reason the thread itself is identified by two: "Threads are per connection; contacts are per organization" (channels.md). The connection says which of the organization's accounts the message arrived on — "reply on this thread has to know which account it leaves by" — and the address says who wrote, in whatever shape the provider's own namespace has: a phone number in E.164 on WhatsApp, an opaque user id elsewhere, "decided when each is built".

address is personal data and connection_id is not. The address is the contact — "on a channel, the contact is their address" — so the retention purge clears it exactly as it clears number, which is the same datum arriving by a different road; the connection names one of the organization's own accounts and survives, like trunk_id beside it.

provider is CHANNEL's third, and it is stored as a value rather than read off the connection. interactions.md: "a conversation that arrived on a channel names the provider it arrived on, beside the contact's address", because an address alone does not say whether the person was reached on WhatsApp, by mail or somewhere else. It is written by the channel at open, from the provider it is already speaking to, for the reason the run settings beside it are values too: a connection is what it is now, and this answers what the conversation arrived on then. It also keeps connection_id the opaque reference it is — nothing here dereferences a connection to render a row. Not personal data: it names a kind of account of the organization's own and nobody outside it, so it survives the purge exactly as connection_id does.

started_at
​string · date-time · required
​
​
​
​
​
channel_key
​string
Default:
contact_spoke
​boolean
Default: false
​
​
​
draft_test
​boolean
Default: false
​
​
​
​
​
​
​
label_ids
​string[]
​
​
​
​
​
​
​
rang
​boolean
Default: false
​
​
​
​
unreplied
​boolean
Default: false
​object
GET/api/v1/interactions
curl /api/v1/interactions \ --header 'Authorization: Bearer <token>'
Example Responses
[ { "agent_id": "00000000-0000-0000-0000-000000000000", "agent_version_id": "00000000-0000-0000-0000-000000000000", "answered_at": "2024-08-25T15:00:00Z", "answered_by": "person", "bridge_seconds": 0, "channel": "voice", "channel_key": "", "contact_spoke": false, "content_purged_at": "2024-08-25T15:00:00Z", "cuts": { "backchannel": 0, "before_line": 0, "confirmed_by_duration": 0, "confirmed_by_words": 0, "cuts": 0, "empty": 0, "overtaken": 0, "phantom": 0, "proposed": 0, "resumed": 0, "withdrawn": 0, "withdrawn_by_budget": 0 }, "direction": "inbound", "disconnect_reason": "string", "draft_test": false, "duration_seconds": 0, "end_reason": "string", "ended_at": "2024-08-25T15:00:00Z", "handoff_reason": "string", "handoff_reason_code": "kept_for_people", "held_by_person_id": "00000000-0000-0000-0000-000000000000", "hung_up_by": "contact", "id": "00000000-0000-0000-0000-000000000000", "is_open": true, "label_ids": [ "00000000-0000-0000-0000-000000000000" ], "last_activity_at": "2024-08-25T15:00:00Z", "last_line": { "actor_person_id": "00000000-0000-0000-0000-000000000000", "at": "2024-08-25T15:00:00Z", "speaker": "agent", "text": "text" }, "org_id": "00000000-0000-0000-0000-000000000000", "person_state": "waiting", "person_state_since": "2024-08-25T15:00:00Z", "pickup": { "decided_by": "classifier", "duration_ms": 0, "model": "string", "path": "spoke", "provider": "string" }, "prepared_outdated_by": "contact", "prepared_reply": "ready", "rang": false, "recording_duration_seconds": 0, "recording_size_bytes": 0, "recording_url": "string", "settings": { "ai_profile_id": "00000000-0000-0000-0000-000000000000", "arrangement_attempts": [], "arrangement_kind": "string", "arrangement_position": 0, "live_model": "string", "live_provider": "string", "live_resumptions": 0, "live_thinking": "string", "live_voice": "string", "llm_model": "string", "llm_provider": "string", "llm_thinking": "string", "standby_component": "llm", "stt_model": "string", "stt_provider": "string", "tts_provider": "string", "tts_voice": "string", "used_standby": false }, "source": { "address": "string", "api_key_id": "00000000-0000-0000-0000-000000000000", "campaign_id": "00000000-0000-0000-0000-000000000000", "connected_app_id": "00000000-0000-0000-0000-000000000000", "connection_id": "00000000-0000-0000-0000-000000000000", "context": { "key": "string" }, "kind": "inbound_number", "number": "string", "provider": "string", "trunk_id": "00000000-0000-0000-0000-000000000000", "wanted": "string", "widget": "string" }, "started_at": "2024-08-25T15:00:00Z", "transfer_outcome": "handed_over", "unreplied": false, "usage": { "key": "string" } } ]
json
application/json

Count Interactions

GET
/api/v1/interactions/count

How many conversations match. Use when you need a count rather than the rows themselves — GET /interactions' filters, with the same meanings and the same refusals, and no paging.

Count Interactions › query Parameters

channel
​
direction
​
agent_id
​
answered_by
​
end_reason
​
open_only
​boolean
Default: false
unanswered
​
draft_test
​
campaign_id
​
person_state
​
since
​
until
​
state
​
channel_key
​
holder
​
counterparty
​
handed_over
​
unreplied
​
min_duration_seconds
​
max_duration_seconds
​
record_id
​
label
​
prepared_reply
​

Count Interactions › Responses

Successful Response

How many conversations match a set of filters (inbox.md rule 3).
InteractionCount
count
​integer · required
GET/api/v1/interactions/count
curl /api/v1/interactions/count \ --header 'Authorization: Bearer <token>'
Example Responses
{ "count": 0 }
json
application/json

Get Interaction

GET
/api/v1/interactions/{interaction_id}

Fetch one conversation by id. Use when you already have the interaction's id and need its current state. A reader without conversation_details is sent it without what only the details view shows (inbox.md rule 22), nor, without recording, the address of its audio (#968).

Get Interaction › path Parameters

interaction_id
​string · uuid · required

Get Interaction › query Parameters

agent_id
​

Answer only if the conversation is this agent's; another agent's is not found.

Answer only if the conversation is this agent's; another agent's is not found.

Get Interaction › Responses

Successful Response

One conversation, as the log shows it.
InteractionOut
channel
​Channel · enum · required

Voice and text are two channels over one graph, not two kinds of record.

Enum values:
voice
text
direction
​backend__features__interactions__schemas__Direction · enum · required
Enum values:
inbound
outbound
id
​string · uuid · required
is_open
​boolean · required
org_id
​string · uuid · required
​RunSettings · required

The settings a conversation actually ran with, copied in as values.

An AI profile is not frozen into an agent's published version, so the version alone cannot say how a conversation sounded. The profile id is kept for provenance; the provider, model and voice are kept because they are the answer. used_standby records that a standby served the conversation instead of some component's first choice — the same fields still describe what was actually served — and standby_component names which one switched.

​backend__features__interactions__schemas__Source · required

Source attribution, as recorded. kind says which of the rest is meaningful; the others stay unset.

connection_id and address are CHANNEL's pair, and they are two fields for the reason the thread itself is identified by two: "Threads are per connection; contacts are per organization" (channels.md). The connection says which of the organization's accounts the message arrived on — "reply on this thread has to know which account it leaves by" — and the address says who wrote, in whatever shape the provider's own namespace has: a phone number in E.164 on WhatsApp, an opaque user id elsewhere, "decided when each is built".

address is personal data and connection_id is not. The address is the contact — "on a channel, the contact is their address" — so the retention purge clears it exactly as it clears number, which is the same datum arriving by a different road; the connection names one of the organization's own accounts and survives, like trunk_id beside it.

provider is CHANNEL's third, and it is stored as a value rather than read off the connection. interactions.md: "a conversation that arrived on a channel names the provider it arrived on, beside the contact's address", because an address alone does not say whether the person was reached on WhatsApp, by mail or somewhere else. It is written by the channel at open, from the provider it is already speaking to, for the reason the run settings beside it are values too: a connection is what it is now, and this answers what the conversation arrived on then. It also keeps connection_id the opaque reference it is — nothing here dereferences a connection to render a row. Not personal data: it names a kind of account of the organization's own and nobody outside it, so it survives the purge exactly as connection_id does.

started_at
​string · date-time · required
​
​
​
​
​
channel_key
​string
Default:
contact_spoke
​boolean
Default: false
​
​
​
draft_test
​boolean
Default: false
​
​
​
​
​
​
​
label_ids
​string[]
​
​
​
​
​
​
​
rang
​boolean
Default: false
​
​
​
​
unreplied
​boolean
Default: false
​object
GET/api/v1/interactions/{interaction_id}
curl /api/v1/interactions/:interaction_id \ --header 'Authorization: Bearer <token>'
Example Responses
{ "agent_id": "00000000-0000-0000-0000-000000000000", "agent_version_id": "00000000-0000-0000-0000-000000000000", "answered_at": "2024-08-25T15:00:00Z", "answered_by": "person", "bridge_seconds": 0, "channel": "voice", "channel_key": "", "contact_spoke": false, "content_purged_at": "2024-08-25T15:00:00Z", "cuts": { "backchannel": 0, "before_line": 0, "confirmed_by_duration": 0, "confirmed_by_words": 0, "cuts": 0, "empty": 0, "overtaken": 0, "phantom": 0, "proposed": 0, "resumed": 0, "withdrawn": 0, "withdrawn_by_budget": 0 }, "direction": "inbound", "disconnect_reason": "string", "draft_test": false, "duration_seconds": 0, "end_reason": "string", "ended_at": "2024-08-25T15:00:00Z", "handoff_reason": "string", "handoff_reason_code": "kept_for_people", "held_by_person_id": "00000000-0000-0000-0000-000000000000", "hung_up_by": "contact", "id": "00000000-0000-0000-0000-000000000000", "is_open": true, "label_ids": [ "00000000-0000-0000-0000-000000000000" ], "last_activity_at": "2024-08-25T15:00:00Z", "last_line": { "actor_person_id": "00000000-0000-0000-0000-000000000000", "at": "2024-08-25T15:00:00Z", "speaker": "agent", "text": "text" }, "org_id": "00000000-0000-0000-0000-000000000000", "person_state": "waiting", "person_state_since": "2024-08-25T15:00:00Z", "pickup": { "decided_by": "classifier", "duration_ms": 0, "model": "string", "path": "spoke", "provider": "string" }, "prepared_outdated_by": "contact", "prepared_reply": "ready", "rang": false, "recording_duration_seconds": 0, "recording_size_bytes": 0, "recording_url": "string", "settings": { "ai_profile_id": "00000000-0000-0000-0000-000000000000", "arrangement_attempts": [], "arrangement_kind": "string", "arrangement_position": 0, "live_model": "string", "live_provider": "string", "live_resumptions": 0, "live_thinking": "string", "live_voice": "string", "llm_model": "string", "llm_provider": "string", "llm_thinking": "string", "standby_component": "llm", "stt_model": "string", "stt_provider": "string", "tts_provider": "string", "tts_voice": "string", "used_standby": false }, "source": { "address": "string", "api_key_id": "00000000-0000-0000-0000-000000000000", "campaign_id": "00000000-0000-0000-0000-000000000000", "connected_app_id": "00000000-0000-0000-0000-000000000000", "connection_id": "00000000-0000-0000-0000-000000000000", "context": { "key": "string" }, "kind": "inbound_number", "number": "string", "provider": "string", "trunk_id": "00000000-0000-0000-0000-000000000000", "wanted": "string", "widget": "string" }, "started_at": "2024-08-25T15:00:00Z", "transfer_outcome": "handed_over", "unreplied": false, "usage": { "key": "string" } }
json
application/json

Set Conversation Labels

POST
/api/v1/interactions/{interaction_id}/labels

Put labels on a conversation and take labels off it, by id. Use to sort a conversation: a thread, a call or a text conversation, open or ended, that the caller may read. A conversation carries at most 5; a label already on stays on and one already off stays off. Each change is on the record with who made it.

Set Conversation Labels › path Parameters

interaction_id
​string · uuid · required

Set Conversation Labels › Request Body

Labels to put on a conversation and to take off it, by id. Either may be empty; a label already on is left on and one already off is left off, saying nothing on the record.
LabelsChange
add
​string[] · maxItems: 50
remove
​string[] · maxItems: 50

Set Conversation Labels › Responses

Successful Response

The labels a conversation carries after a change, by id, in the order they were put on.
ConversationLabels
interaction_id
​string · uuid · required
label_ids
​string[] · required
POST/api/v1/interactions/{interaction_id}/labels
curl /api/v1/interactions/:interaction_id/labels \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <token>' \ --data '{ "add": [ "00000000-0000-0000-0000-000000000000" ], "remove": [ "00000000-0000-0000-0000-000000000000" ] }'
Example Request Body
{ "add": [ "00000000-0000-0000-0000-000000000000" ], "remove": [ "00000000-0000-0000-0000-000000000000" ] }
json
Example Responses
{ "interaction_id": "00000000-0000-0000-0000-000000000000", "label_ids": [ "00000000-0000-0000-0000-000000000000" ] }
json
application/json

Get Trace

GET
/api/v1/interactions/{interaction_id}/trace

The exact path one conversation walked: nodes entered, hops refused, tools run with the values they actually ran with, and everything said. Use when debugging what the agent actually did, not just what was said.

Get Trace › path Parameters

interaction_id
​string · uuid · required

Get Trace › query Parameters

agent_id
​

Answer only if the conversation is this agent's; another agent's is not found.

Answer only if the conversation is this agent's; another agent's is not found.

Get Trace › Responses

Successful Response

*"Per-interaction trace — see the exact path through the node graph for one conversation."* The record and its events, in the order they happened.
InteractionTraceOut
​InteractionEventOut[] · required
​InteractionOut · required

One conversation, as the log shows it.

GET/api/v1/interactions/{interaction_id}/trace
curl /api/v1/interactions/:interaction_id/trace \ --header 'Authorization: Bearer <token>'
Example Responses
{ "events": [ { "actor_person_id": "00000000-0000-0000-0000-000000000000", "agent_id": "00000000-0000-0000-0000-000000000000", "agent_settings": { "ai_profile_id": "00000000-0000-0000-0000-000000000000", "arrangement_attempts": [], "arrangement_kind": "string", "arrangement_position": 0, "live_model": "string", "live_provider": "string", "live_resumptions": 0, "live_thinking": "string", "live_voice": "string", "llm_model": "string", "llm_provider": "string", "llm_thinking": "string", "standby_component": "llm", "stt_model": "string", "stt_provider": "string", "tts_provider": "string", "tts_voice": "string", "used_standby": false }, "agent_version_id": "00000000-0000-0000-0000-000000000000", "assignee_person_id": "00000000-0000-0000-0000-000000000000", "attachment": {}, "began_at": "2024-08-25T15:00:00Z", "blocked_hops": 0, "blocked_reason": "hop_limit", "colleague": false, "confirmation_decision": "confirmed", "confirmation_mode": "ask", "confirmation_person_id": "00000000-0000-0000-0000-000000000000", "confirmation_request_id": "00000000-0000-0000-0000-000000000000", "error": "string", "flow_act": false, "handoff_act": "handed_over", "handoff_reason_code": "kept_for_people", "held": false, "id": "00000000-0000-0000-0000-000000000000", "label_added": true, "label_id": "00000000-0000-0000-0000-000000000000", "mailbox_address": "string", "node_id": "00000000-0000-0000-0000-000000000000", "occurred_at": "2024-08-25T15:00:00Z", "overlapped": false, "prepared_by_agent_id": "00000000-0000-0000-0000-000000000000", "prepared_changed": false, "ref_id": "00000000-0000-0000-0000-000000000000", "returned_to_flow": false, "seq": 0, "speaker": "agent", "target_node_id": "00000000-0000-0000-0000-000000000000", "text": "string", "tool_arguments": {}, "tool_call_key": "00000000-0000-0000-0000-000000000000", "tool_connection_id": "00000000-0000-0000-0000-000000000000", "tool_fixed_parameters": [ "string" ], "tool_id": "00000000-0000-0000-0000-000000000000", "tool_name": "string", "tool_outcome": "ok", "tool_phase": "pre", "tool_result": {}, "tool_roster_entry_id": "00000000-0000-0000-0000-000000000000", "tool_version_id": "00000000-0000-0000-0000-000000000000", "turn_stages": { "dead_air_ms": 0, "eou_delay_ms": 0, "first_audio_ms": 0, "held_ms": 0, "model_ms": 0, "queue_ms": 0, "record_ms": 0, "think_ms": 0, "tools_ms": 0, "tts_ttfb_ms": 0 }, "type": "node_entered", "unvoiced": false, "usage_model": "string", "usage_provider": "string", "usage_resolved_model": "string", "usage_unit": "string", "usage_units": "string" } ], "interaction": { "agent_id": "00000000-0000-0000-0000-000000000000", "agent_version_id": "00000000-0000-0000-0000-000000000000", "answered_at": "2024-08-25T15:00:00Z", "answered_by": "person", "bridge_seconds": 0, "channel": "voice", "channel_key": "", "contact_spoke": false, "content_purged_at": "2024-08-25T15:00:00Z", "cuts": { "backchannel": 0, "before_line": 0, "confirmed_by_duration": 0, "confirmed_by_words": 0, "cuts": 0, "empty": 0, "overtaken": 0, "phantom": 0, "proposed": 0, "resumed": 0, "withdrawn": 0, "withdrawn_by_budget": 0 }, "direction": "inbound", "disconnect_reason": "string", "draft_test": false, "duration_seconds": 0, "end_reason": "string", "ended_at": "2024-08-25T15:00:00Z", "handoff_reason": "string", "handoff_reason_code": "kept_for_people", "held_by_person_id": "00000000-0000-0000-0000-000000000000", "hung_up_by": "contact", "id": "00000000-0000-0000-0000-000000000000", "is_open": true, "label_ids": [ "00000000-0000-0000-0000-000000000000" ], "last_activity_at": "2024-08-25T15:00:00Z", "last_line": { "actor_person_id": "00000000-0000-0000-0000-000000000000", "at": "2024-08-25T15:00:00Z", "speaker": "agent", "text": "text" }, "org_id": "00000000-0000-0000-0000-000000000000", "person_state": "waiting", "person_state_since": "2024-08-25T15:00:00Z", "pickup": { "decided_by": "classifier", "duration_ms": 0, "model": "string", "path": "spoke", "provider": "string" }, "prepared_outdated_by": "contact", "prepared_reply": "ready", "rang": false, "recording_duration_seconds": 0, "recording_size_bytes": 0, "recording_url": "string", "settings": { "ai_profile_id": "00000000-0000-0000-0000-000000000000", "arrangement_attempts": [], "arrangement_kind": "string", "arrangement_position": 0, "live_model": "string", "live_provider": "string", "live_resumptions": 0, "live_thinking": "string", "live_voice": "string", "llm_model": "string", "llm_provider": "string", "llm_thinking": "string", "standby_component": "llm", "stt_model": "string", "stt_provider": "string", "tts_provider": "string", "tts_voice": "string", "used_standby": false }, "source": { "address": "string", "api_key_id": "00000000-0000-0000-0000-000000000000", "campaign_id": "00000000-0000-0000-0000-000000000000", "connected_app_id": "00000000-0000-0000-0000-000000000000", "connection_id": "00000000-0000-0000-0000-000000000000", "context": { "key": "string" }, "kind": "inbound_number", "number": "string", "provider": "string", "trunk_id": "00000000-0000-0000-0000-000000000000", "wanted": "string", "widget": "string" }, "started_at": "2024-08-25T15:00:00Z", "transfer_outcome": "handed_over", "unreplied": false, "usage": { "key": "string" } } }
json
application/json

Get Transcript

GET
/api/v1/interactions/{interaction_id}/transcript

The conversation itself — what was said and the gate around it — with none of the technical trace get_trace also carries. Use when you want what was said, not the technical trace. Behind interactions alone (rule 34, 2026-09-28 amendment): a person who can read this interaction's detail can always read this, whether or not they also hold interaction_traces.

Not gated by require_flag — open_router. Rule 24's exemption (_readable_without_interactions_flag): a caller without interactions still reaches this for a test they started themselves or an Architect conversation of their own organization; service.describe_transcript raises PermissionDenied (403, {"detail": "interactions"} — the same body require_flag would have given) for anything else, including an id that does not exist or belongs to another organization — indistinguishable on purpose, so a caller without the flag cannot use 404-vs-403 to learn whether an id it may not read exists at all.

Get Transcript › path Parameters

interaction_id
​string · uuid · required

Get Transcript › query Parameters

agent_id
​

Answer only if the conversation is this agent's; another agent's is not found.

Answer only if the conversation is this agent's; another agent's is not found.

Get Transcript › Responses

Successful Response

The conversation, without its technical trace (live-view.md rule 34, 2026-09-28 amendment): the record and only the events that are the conversation itself — what was said, the door's later correction, the confirmation gate, an agent taking a thread over, a thread handed to a person and every take and release, what a branch of the flow sent (a `TOOL_CALL` marked `flow_act`), a turn that produced no reply, and a call's missing recording. **Never** a `NODE_ENTERED` or `NAVIGATION_BLOCKED` row (node traversal), any other `TOOL_CALL` (tool payloads), a `PROVIDER_USAGE` row (provider metadata) or a `TURN_TIMED` row (latencies) — `service.describe_transcript`'s filter is what keeps those off this shape, so a person with `interactions` but not `interaction_traces` never receives them. `service._is_transcript_event` names the exact set.
InteractionTranscriptOut
​InteractionEventOut[] · required
​InteractionOut · required

One conversation, as the log shows it.

GET/api/v1/interactions/{interaction_id}/transcript
curl /api/v1/interactions/:interaction_id/transcript \ --header 'Authorization: Bearer <token>'
Example Responses
{ "events": [ { "actor_person_id": "00000000-0000-0000-0000-000000000000", "agent_id": "00000000-0000-0000-0000-000000000000", "agent_settings": { "ai_profile_id": "00000000-0000-0000-0000-000000000000", "arrangement_attempts": [], "arrangement_kind": "string", "arrangement_position": 0, "live_model": "string", "live_provider": "string", "live_resumptions": 0, "live_thinking": "string", "live_voice": "string", "llm_model": "string", "llm_provider": "string", "llm_thinking": "string", "standby_component": "llm", "stt_model": "string", "stt_provider": "string", "tts_provider": "string", "tts_voice": "string", "used_standby": false }, "agent_version_id": "00000000-0000-0000-0000-000000000000", "assignee_person_id": "00000000-0000-0000-0000-000000000000", "attachment": {}, "began_at": "2024-08-25T15:00:00Z", "blocked_hops": 0, "blocked_reason": "hop_limit", "colleague": false, "confirmation_decision": "confirmed", "confirmation_mode": "ask", "confirmation_person_id": "00000000-0000-0000-0000-000000000000", "confirmation_request_id": "00000000-0000-0000-0000-000000000000", "error": "string", "flow_act": false, "handoff_act": "handed_over", "handoff_reason_code": "kept_for_people", "held": false, "id": "00000000-0000-0000-0000-000000000000", "label_added": true, "label_id": "00000000-0000-0000-0000-000000000000", "mailbox_address": "string", "node_id": "00000000-0000-0000-0000-000000000000", "occurred_at": "2024-08-25T15:00:00Z", "overlapped": false, "prepared_by_agent_id": "00000000-0000-0000-0000-000000000000", "prepared_changed": false, "ref_id": "00000000-0000-0000-0000-000000000000", "returned_to_flow": false, "seq": 0, "speaker": "agent", "target_node_id": "00000000-0000-0000-0000-000000000000", "text": "string", "tool_arguments": {}, "tool_call_key": "00000000-0000-0000-0000-000000000000", "tool_connection_id": "00000000-0000-0000-0000-000000000000", "tool_fixed_parameters": [ "string" ], "tool_id": "00000000-0000-0000-0000-000000000000", "tool_name": "string", "tool_outcome": "ok", "tool_phase": "pre", "tool_result": {}, "tool_roster_entry_id": "00000000-0000-0000-0000-000000000000", "tool_version_id": "00000000-0000-0000-0000-000000000000", "turn_stages": { "dead_air_ms": 0, "eou_delay_ms": 0, "first_audio_ms": 0, "held_ms": 0, "model_ms": 0, "queue_ms": 0, "record_ms": 0, "think_ms": 0, "tools_ms": 0, "tts_ttfb_ms": 0 }, "type": "node_entered", "unvoiced": false, "usage_model": "string", "usage_provider": "string", "usage_resolved_model": "string", "usage_unit": "string", "usage_units": "string" } ], "interaction": { "agent_id": "00000000-0000-0000-0000-000000000000", "agent_version_id": "00000000-0000-0000-0000-000000000000", "answered_at": "2024-08-25T15:00:00Z", "answered_by": "person", "bridge_seconds": 0, "channel": "voice", "channel_key": "", "contact_spoke": false, "content_purged_at": "2024-08-25T15:00:00Z", "cuts": { "backchannel": 0, "before_line": 0, "confirmed_by_duration": 0, "confirmed_by_words": 0, "cuts": 0, "empty": 0, "overtaken": 0, "phantom": 0, "proposed": 0, "resumed": 0, "withdrawn": 0, "withdrawn_by_budget": 0 }, "direction": "inbound", "disconnect_reason": "string", "draft_test": false, "duration_seconds": 0, "end_reason": "string", "ended_at": "2024-08-25T15:00:00Z", "handoff_reason": "string", "handoff_reason_code": "kept_for_people", "held_by_person_id": "00000000-0000-0000-0000-000000000000", "hung_up_by": "contact", "id": "00000000-0000-0000-0000-000000000000", "is_open": true, "label_ids": [ "00000000-0000-0000-0000-000000000000" ], "last_activity_at": "2024-08-25T15:00:00Z", "last_line": { "actor_person_id": "00000000-0000-0000-0000-000000000000", "at": "2024-08-25T15:00:00Z", "speaker": "agent", "text": "text" }, "org_id": "00000000-0000-0000-0000-000000000000", "person_state": "waiting", "person_state_since": "2024-08-25T15:00:00Z", "pickup": { "decided_by": "classifier", "duration_ms": 0, "model": "string", "path": "spoke", "provider": "string" }, "prepared_outdated_by": "contact", "prepared_reply": "ready", "rang": false, "recording_duration_seconds": 0, "recording_size_bytes": 0, "recording_url": "string", "settings": { "ai_profile_id": "00000000-0000-0000-0000-000000000000", "arrangement_attempts": [], "arrangement_kind": "string", "arrangement_position": 0, "live_model": "string", "live_provider": "string", "live_resumptions": 0, "live_thinking": "string", "live_voice": "string", "llm_model": "string", "llm_provider": "string", "llm_thinking": "string", "standby_component": "llm", "stt_model": "string", "stt_provider": "string", "tts_provider": "string", "tts_voice": "string", "used_standby": false }, "source": { "address": "string", "api_key_id": "00000000-0000-0000-0000-000000000000", "campaign_id": "00000000-0000-0000-0000-000000000000", "connected_app_id": "00000000-0000-0000-0000-000000000000", "connection_id": "00000000-0000-0000-0000-000000000000", "context": { "key": "string" }, "kind": "inbound_number", "number": "string", "provider": "string", "trunk_id": "00000000-0000-0000-0000-000000000000", "wanted": "string", "widget": "string" }, "started_at": "2024-08-25T15:00:00Z", "transfer_outcome": "handed_over", "unreplied": false, "usage": { "key": "string" } } }
json
application/json

List Labels

GET
/api/v1/labels

List the organization's labels, by name: each with what belongs under it and how many conversations carry it. Use to see the vocabulary a conversation can be sorted by, and what deleting a label would take it off.

List Labels › Responses

200

Successful Response

​LabelOut[]
One label of the organization's vocabulary. `conversation_count` is how many conversations carry it -- what deleting it takes it off (rule 62), said before it is confirmed.
LabelOut
description
​string · required
id
​string · uuid · required
name
​string · required
conversation_count
​integer
Default: 0
GET/api/v1/labels
curl /api/v1/labels \ --header 'Authorization: Bearer <token>'
Example Responses
[ { "conversation_count": 0, "description": "description", "id": "00000000-0000-0000-0000-000000000000", "name": "name" } ]
json
application/json

Create Label

POST
/api/v1/labels

Add a label: a name, and one line saying what belongs under it. An owner's or admin's. An organization keeps at most 50, each name once whatever its case.

Create Label › Request Body

A label to create: a name, and one line saying what belongs under it (interactions.md rule 58). No colour -- the spec names none.
LabelIn
name
​string · minLength: 1 · maxLength: 60 · required
description
​string · maxLength: 300
Default:

Create Label › Responses

Successful Response

One label of the organization's vocabulary. `conversation_count` is how many conversations carry it -- what deleting it takes it off (rule 62), said before it is confirmed.
LabelOut
description
​string · required
id
​string · uuid · required
name
​string · required
conversation_count
​integer
Default: 0
POST/api/v1/labels
curl /api/v1/labels \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <token>' \ --data '{ "description": "", "name": "name" }'
Example Request Body
{ "description": "", "name": "name" }
json
Example Responses
{ "conversation_count": 0, "description": "description", "id": "00000000-0000-0000-0000-000000000000", "name": "name" }
json
application/json

Delete Label

DELETE
/api/v1/labels/{label_id}

Delete a label: it comes off every conversation it is on, each taking-off on the record with who did it. An owner's or admin's. GET /labels says how many conversations that is, to show before confirming.

Delete Label › path Parameters

label_id
​string · uuid · required

Delete Label › Responses

Successful Response

No data returned
DELETE/api/v1/labels/{label_id}
curl /api/v1/labels/:label_id \ --request DELETE \ --header 'Authorization: Bearer <token>'
Example Responses
No example specified for this content type

Update Label

PATCH
/api/v1/labels/{label_id}

Rename a label or change its line. An owner's or admin's. The label stays on every conversation it is on.

Update Label › path Parameters

label_id
​string · uuid · required

Update Label › Request Body

What changes on a label; anything left out stays. Renaming keeps the label on every conversation it is on (rule 62).
LabelUpdate
​
​

Update Label › Responses

Successful Response

One label of the organization's vocabulary. `conversation_count` is how many conversations carry it -- what deleting it takes it off (rule 62), said before it is confirmed.
LabelOut
description
​string · required
id
​string · uuid · required
name
​string · required
conversation_count
​integer
Default: 0
PATCH/api/v1/labels/{label_id}
curl /api/v1/labels/:label_id \ --request PATCH \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <token>' \ --data '{ "description": "string", "name": "string" }'
Example Request Body
{ "description": "string", "name": "string" }
json
Example Responses
{ "conversation_count": 0, "description": "description", "id": "00000000-0000-0000-0000-000000000000", "name": "name" }
json
application/json

handofflegal