{"openapi":"3.0.3","info":{"title":"Callingtap API","version":"1.0.0","description":"Tenant-facing API for the Callingtap voice-AI platform. All tenant endpoints are scoped by the bearer token. Pricing figures exposed to tenants are credits only."},"servers":[{"url":"https://api.callingtap.com/api/v1","description":"Production"}],"tags":[{"name":"Insights","description":"Post-call analytics: latency, action items, scorecards, suggestions."},{"name":"Pricing","description":"Plans and per-agent credit rates (credits only)."},{"name":"Inbox","description":"Omnichannel unified inbox, broadcasts and SMS."},{"name":"Handoffs","description":"Human handoff with full call context."},{"name":"Contacts","description":"Contacts and their unified conversation history."},{"name":"Widgets","description":"Website widgets: session tokens and verified visitor identity."}],"security":[{"bearerAuth":[]}],"paths":{"/agent-latency/{agentId}":{"get":{"tags":["Insights"],"summary":"Per-turn latency statistics for one agent (Wave 1, item 1.1)","parameters":[{"name":"agentId","in":"path","required":true,"description":"Agent id (must belong to the authenticated tenant).","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Max recent sessions to aggregate (default 50).","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"tenantId":{"type":"string"},"agentId":{"type":"string"},"sessions":{"type":"integer"},"turnsWithTiming":{"type":"integer"},"stages":{"type":"object","description":"Per-stage timing aggregates (count/p50/p95/min/max in ms) for stt_ms, llm_ms, llm_first_token_ms, tts_first_sentence_ms, tts_total_ms, turn_total_ms.","additionalProperties":{"type":"object","properties":{"count":{"type":"integer"},"p50":{"type":"number"},"p95":{"type":"number"},"min":{"type":"number"},"max":{"type":"number"}}}}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/call-action-items":{"get":{"tags":["Insights"],"summary":"List structured action items extracted from calls (Wave 1, WS-3)","parameters":[{"name":"call_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","done","dismissed"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/CallActionItem"}}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/call-action-items/{id}":{"patch":{"tags":["Insights"],"summary":"Update an action item (status)","parameters":[{"name":"id","in":"path","required":true,"description":"Action item id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","done","dismissed"]}},"required":["status"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/CallActionItem"}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/{id}/scorecard":{"get":{"tags":["Insights"],"summary":"Coaching scorecard for one agent (Wave 1, WS-3)","parameters":[{"name":"id","in":"path","required":true,"description":"Agent id.","schema":{"type":"string"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":365}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","description":"Aggregated QA rubric scores (greeting/discovery/compliance/resolution), call counts and outcome mix for the window.","additionalProperties":true}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agent-suggestions":{"get":{"tags":["Insights"],"summary":"List self-improvement suggestions for agents (Wave 1, WS-5)","parameters":[{"name":"agent_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","applied","dismissed"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"suggestions":{"type":"array","items":{"type":"object","additionalProperties":true}}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agent-suggestions/generate":{"post":{"tags":["Insights"],"summary":"Generate suggestions for one agent from its recent calls (owner/admin/campaign_manager)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"agent_id":{"type":"string"},"window_days":{"type":"integer","minimum":1,"maximum":365}},"required":["agent_id"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"created":{"type":"integer"},"skippedDuplicates":{"type":"integer"},"callsConsidered":{"type":"integer"}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agent-suggestions/{id}/apply":{"post":{"tags":["Insights"],"summary":"Apply a pending suggestion (explicit human action — suggestions never auto-apply)","parameters":[{"name":"id","in":"path","required":true,"description":"Suggestion id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agent-suggestions/{id}/dismiss":{"post":{"tags":["Insights"],"summary":"Dismiss a pending suggestion","parameters":[{"name":"id","in":"path","required":true,"description":"Suggestion id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/enabled-providers":{"get":{"tags":["Pricing"],"summary":"Enabled providers + tenant pricing economics (CREDITS ONLY — no costs, USD or margins)","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","description":"Provider catalogue with per-component creditsPerMinute figures from the tenant economics projection.","additionalProperties":true}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/{id}":{"get":{"tags":["Pricing"],"summary":"One agent, including its Billing v2 rate block { billing: { credits_per_minute, rate_source } }","parameters":[{"name":"id","in":"path","required":true,"description":"Agent id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"billing":{"type":["object","null"],"properties":{"credits_per_minute":{"type":"number"},"rate_source":{"type":"string","enum":["override","stack","subscription","default"]}}}},"additionalProperties":true}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/public/catalog":{"get":{"tags":["Pricing"],"summary":"Public plan catalogue (no auth)","security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}},"required":["success","data"]}}}}}}},"/inbox/threads":{"get":{"tags":["Inbox"],"summary":"Unified inbox threads, AI-prioritised (Wave 2, item 2.4)","parameters":[{"name":"channel","in":"query","required":false,"schema":{"type":"string","enum":["voice","whatsapp","sms","email"]}},{"name":"unread","in":"query","required":false,"schema":{"type":"string","enum":["1","true"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"threads":{"type":"array","items":{"$ref":"#/components/schemas/InboxThread"}}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/inbox/threads/{threadKey}":{"get":{"tags":["Inbox"],"summary":"One inbox thread with its messages (threadKey is URL-encoded, e.g. whatsapp%3A919876543210)","parameters":[{"name":"threadKey","in":"path","required":true,"description":"Thread key: <channel>:<counterparty-key>.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"thread":{"$ref":"#/components/schemas/InboxThread"},"messages":{"type":"array","items":{"type":"object","additionalProperties":true}}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/inbox/threads/{threadKey}/state":{"patch":{"tags":["Inbox"],"summary":"Update thread state (read / starred / assignee)","parameters":[{"name":"threadKey","in":"path","required":true,"description":"Thread key.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"is_read":{"type":"boolean"},"is_starred":{"type":"boolean"},"assignee_user_id":{"type":["string","null"]}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"thread_key":{"type":"string"},"is_read":{"type":"boolean"},"is_starred":{"type":"boolean"},"assignee_user_id":{"type":["string","null"]}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/inbox/broadcasts":{"get":{"tags":["Inbox"],"summary":"Broadcast history (Wave 2, item 2.5)","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"broadcasts":{"type":"array","items":{"type":"object","additionalProperties":true}}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Inbox"],"summary":"Create a broadcast — WhatsApp sends ONLY approved registry templates; SMS uses the tenant provider config","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channel":{"type":"string","enum":["whatsapp","sms"]},"templateId":{"type":"string"},"templateName":{"type":"string"},"variables":{"type":"object","additionalProperties":true},"body":{"type":"string","description":"SMS body (required for channel=sms)."},"contactIds":{"type":"array","items":{"type":"string"},"maxItems":200}},"required":["channel","contactIds"]}}}},"responses":{"201":{"description":"Broadcast completed (per-recipient outcomes in recipients[])","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/BroadcastResult"}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/inbox/broadcasts/{id}":{"get":{"tags":["Inbox"],"summary":"One broadcast with per-recipient outcomes","parameters":[{"name":"id","in":"path","required":true,"description":"Broadcast id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/inbox/sms":{"post":{"tags":["Inbox"],"summary":"Send a single SMS through the tenant telephony provider config (Wave 2, item 12)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string"},"body":{"type":"string"}},"required":["to","body"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"status":{"type":"string","enum":["sent"]},"provider":{"type":"string"},"messageId":{"type":"string"}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/calls/{callId}/handoff":{"post":{"tags":["Handoffs"],"summary":"Create a human handoff for a call — returns the full context package (Wave 2, item 2.7)","parameters":[{"name":"callId","in":"path","required":true,"description":"Call id.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string"}}}}}},"responses":{"201":{"description":"Handoff created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending"]},"transfer_number":{"type":["string","null"]},"context":{"$ref":"#/components/schemas/HandoffPackage"}}}},"required":["success","data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/handoffs":{"get":{"tags":["Handoffs"],"summary":"List handoffs","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","acknowledged","completed","cancelled"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"handoffs":{"type":"array","items":{"type":"object","additionalProperties":true}}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/handoffs/{id}":{"get":{"tags":["Handoffs"],"summary":"One handoff including its frozen context package","parameters":[{"name":"id","in":"path","required":true,"description":"Handoff id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/handoffs/{id}/transition":{"post":{"tags":["Handoffs"],"summary":"Move a handoff through its lifecycle (pending → acknowledged → completed | cancelled)","parameters":[{"name":"id","in":"path","required":true,"description":"Handoff id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","enum":["acknowledged","completed","cancelled"]}},"required":["to"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/widget/token":{"post":{"tags":["Widgets"],"summary":"Public widget session token. Anonymous by default; an optional visitor block carries an HMAC-verified identity (hex HMAC-SHA256 of [contact_id, phone, email].join(newline) under the per-widget identity secret) plus explicit consent — a verified identity activates caller memory for voice sessions. Invalid or unconsented identities are ignored, never an error.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["public_key"],"properties":{"public_key":{"type":"string"},"visitor":{"type":"object","properties":{"contact_id":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"signature":{"type":"string"},"consent":{"type":"boolean"}}}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/WidgetToken"}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/tenant/widgets/{id}/identity-secret":{"get":{"tags":["Widgets"],"summary":"Whether verified visitor identity is enabled for this widget (owner/admin; the secret itself is never readable).","parameters":[{"name":"id","in":"path","required":true,"description":"Widget id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"enabled":{"type":"boolean"}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Widgets"],"summary":"Generate/rotate the per-widget identity HMAC secret. The plaintext secret is returned exactly once, in this response.","parameters":[{"name":"id","in":"path","required":true,"description":"Widget id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"secret":{"type":"string"},"note":{"type":"string"}}}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Widgets"],"summary":"Disable verified visitor identity for this widget.","parameters":[{"name":"id","in":"path","required":true,"description":"Widget id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/contacts/{id}/history":{"get":{"tags":["Contacts"],"summary":"Unified conversation history for one contact — voice calls, WhatsApp, SMS and CRM activities in one timeline (Wave 2, item 5.7)","parameters":[{"name":"id","in":"path","required":true,"description":"Contact id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ContactHistory"}},"required":["success","data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Tenant access token from POST /api/v1/auth/login."}},"responses":{"BadRequest":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string"}},"required":["code","message"]}},"required":["success","error"]}}}},"Unauthorized":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string"}},"required":["code","message"]}},"required":["success","error"]}}}},"NotFound":{"description":"Not found for this tenant","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string"}},"required":["code","message"]}},"required":["success","error"]}}}}},"schemas":{"CallActionItem":{"type":"object","properties":{"id":{"type":"string"},"call_id":{"type":"string"},"agent_id":{"type":["string","null"]},"title":{"type":"string"},"detail":{"type":["string","null"]},"owner_label":{"type":["string","null"]},"due_at":{"type":["string","null"],"format":"date-time"},"status":{"type":"string","enum":["pending","done","dismissed"]},"created_at":{"type":"string","format":"date-time"}}},"InboxThread":{"type":"object","properties":{"threadKey":{"type":"string","example":"whatsapp:919876543210"},"channel":{"type":"string","enum":["voice","whatsapp","sms","email"]},"counterparty":{"type":"string"},"contactId":{"type":["string","null"]},"contactName":{"type":["string","null"]},"lastMessageAt":{"type":["string","null"],"format":"date-time"},"lastPreview":{"type":"string"},"messageCount":{"type":"integer"},"failedCount":{"type":"integer"},"sentiment":{"type":["string","null"]},"leadScore":{"type":["number","null"]},"emotion":{"type":["string","null"],"description":"Dominant emotion tag from the latest analysed call."},"priorityScore":{"type":"integer"},"priority":{"type":"string","enum":["urgent","high","normal","low"]},"reasons":{"type":"array","items":{"type":"string"},"description":"Why the thread has this priority — every point is explained."},"isRead":{"type":"boolean"},"isStarred":{"type":"boolean"},"assigneeUserId":{"type":["string","null"]}}},"BroadcastResult":{"type":"object","properties":{"id":{"type":"string"},"channel":{"type":"string","enum":["whatsapp","sms"]},"status":{"type":"string","enum":["completed","completed_with_failures","failed"]},"total":{"type":"integer"},"sent":{"type":"integer"},"failed":{"type":"integer"},"skipped":{"type":"integer"},"recipients":{"type":"array","items":{"type":"object","properties":{"contactId":{"type":["string","null"]},"phone":{"type":"string"},"status":{"type":"string","enum":["sent","failed","skipped"]},"detail":{"type":["string","null"]},"messageId":{"type":"string"}}}}}},"HandoffPackage":{"type":"object","description":"The frozen context a human receives: call summary, transcript and caller history.","properties":{"call":{"type":"object","additionalProperties":true},"summary":{"type":"string"},"transcript":{"type":"array","items":{"type":"object","properties":{"speaker":{"type":"string"},"text":{"type":"string"},"time":{"type":"number"}}}},"callerHistory":{"type":"string","description":"WS-5 caller-memory block (bounded, PII-redacted); empty for unknown callers."},"contact":{"type":["object","null"],"additionalProperties":true},"reason":{"type":["string","null"]}}},"WidgetToken":{"type":"object","properties":{"token":{"type":"string"},"room":{"type":"string"},"ws_url":{"type":"string"},"agent_expected":{"type":"boolean"}}},"ContactHistory":{"type":"object","properties":{"contact":{"type":"object","additionalProperties":true},"entries":{"type":"array","description":"One chronological timeline (newest first) across voice calls, WhatsApp, SMS and CRM activities.","items":{"type":"object","properties":{"kind":{"type":"string","enum":["call","whatsapp","sms","activity"]},"at":{"type":["string","null"],"format":"date-time"},"title":{"type":"string"},"text":{"type":"string"},"status":{"type":["string","null"]},"meta":{"type":"object","additionalProperties":true}}}}}}}}}