Aria conversations
Aria is the Perceive8 AI assistant. Conversations are persistent chat threads scoped to a workspace — including threads about analysis results, reports, and live meetings — and each thread is typed so Aria loads the right context (transcript, report, business profile) automatically. These endpoints live under /aria, not /v1. Chat endpoints either return a complete JSON reply or stream the reply as Server-Sent Events (SSE).
Base URL: https://api.perceive8.com. Authenticate with X-API-Key: pk_live_xxxxxxxxxxxx (or Authorization: Bearer <jwt>, or ?token= for SSE). Most endpoints require a workspace role of manager or higher; read endpoints require user or higher; delete and save endpoints require admin (or owner). Role order: none < user < manager < admin < owner.
Conversation object
| Field | Type | Description |
|---|---|---|
id |
UUID | Conversation identifier. |
user_id |
string | External ID of the user who created the conversation. |
title |
string | null | Thread title. |
conversation_type |
string | See type table below. Responses return the stored value; note playbook_builder is stored and returned as scenario_builder. |
context_analysis_id |
UUID | null | Analysis this thread is about, if any. |
context_playbook_id |
UUID | null | Playbook this thread is about, if any. |
context_report_id |
UUID | null | Report this thread is about, if any. |
metadata |
object | Arbitrary client metadata. |
created_at, updated_at |
datetime | Creation and last-update timestamps. |
messages |
array | Messages (only included by single-get and create responses; empty in list responses). |
Message object: id (UUID), conversation_id (UUID), role (string, user or assistant), content (string | null), artifacts (array), sources (array), created_at (datetime).
Valid conversation_type values accepted on create: playbook_builder, transcript_analyst, report_analyst, results_analyst, data_analyst, skill_creator, business_profile_setup, meeting_assistant, workspace_assistant.
POST /aria/conversations
Create a conversation. Requires workspace role manager or higher. If conversation_type is meeting_assistant and you send an X-Workspace-Id header, the request fails with 403 when that workspace is not accessible to the credential (fail-closed for machine callers).
Request body
{
"title": "Q3 discovery call review",
"conversation_type": "transcript_analyst",
"context_analysis_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"metadata": {}
}
curl -X POST https://api.perceive8.com/aria/conversations \
-H "X-API-Key: pk_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"conversation_type": "transcript_analyst", "title": "Q3 discovery call review"}'
Response 200 — conversation object (with empty messages). Invalid conversation_type returns 400.
GET /aria/conversations
List the workspace's 50 most recently updated conversations, newest first. Requires role user or higher. Users below manager only see their own conversations. messages is empty in each item.
Response 200 — array of conversation objects.
GET /aria/conversations/{conversation_id}
Get one conversation with all messages. Requires role user or higher.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
conversation_id |
path | UUID | Conversation identifier. |
Response 200 — conversation object including messages; 404 if not found.
PATCH /aria/conversations/{conversation_id}
Update a conversation's title. Requires role manager or higher. Only the title field is applied.
Request body
{ "title": "New title" }
Response 200 — updated conversation object; 404 if not found.
DELETE /aria/conversations/{conversation_id}
Delete a conversation. Requires workspace role admin or owner.
Response 204 — no body; 404 if not found.
POST /aria/conversations/{conversation_id}/auto-title
Generate and save a short title (max 8 words) from the thread's first user message. Requires role manager or higher.
Response 200 — updated conversation object; 404 if not found; 503 if OpenAI is not configured on the server.
POST /aria/conversations/{conversation_id}/messages
Send a message and stream Aria's reply as SSE (text/event-stream, Cache-Control: no-cache, X-Accel-Buffering: no). Requires role manager or higher. The user message is persisted before streaming starts; the assistant reply (text plus any artifacts) is persisted when the stream completes. message is required (400 if empty).
Request body
{
"message": "Summarize the objections raised in this call.",
"context": {
"page_path": "/audio/results",
"page_name": "Results",
"page_suggestions": ["Show concerns"],
"attachments": [{ "filename": "notes.pdf", "source_id": "7c9e..." }]
}
}
context is optional. page_path, page_name, and page_suggestions are only used by workspace_assistant threads; attachments (filename plus optional source_id) are only annotated onto business_profile_setup threads.
SSE events
| Event | When sent | Payload fields |
|---|---|---|
text-delta |
Incremental assistant text | type, textDelta (string) |
tool-status |
Aria runs a tool (e.g. calendar or file lookup) | type, tool (string), status (running or done), label (string, only on running) |
artifact |
A tool produced a structured artifact (e.g. a business_profile_draft) |
type, artifact (object; shape depends on the producing skill) |
error |
Streaming failed mid-response | type, error (string); followed by [DONE] |
[DONE] |
End of stream | literal data: [DONE] |
Results chat
POST /aria/results/chat
Chat with Aria about a completed report — SSE stream, same wire format as above. Requires role manager or higher. If conversation_id is omitted, a new results_analyst conversation titled Report Analysis: <playbook name> is created and reused for follow-ups. Every message passes an LLM-as-a-judge check; rejected prompts stream a single text-delta containing the server's rejection message, then [DONE].
Request body
{
"report_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"message": "Which concerns were flagged in the second half of the call?",
"conversation_id": null
}
| Field | Type | Description |
|---|---|---|
report_id |
string (UUID) | Report to discuss. 400 if malformed, 404 if not found, 403 if owned by another user. |
message |
string | 1–10000 characters. |
conversation_id |
string (UUID) | null | Existing thread to continue; omit to start a new one. 404 if not found. |
SSE events
| Event | When sent | Payload fields |
|---|---|---|
text-delta |
Incremental assistant text | type, textDelta |
error |
Streaming failed mid-response | type, error; followed by [DONE] |
[DONE] |
End of stream | literal data: [DONE] |
Playbook builder
POST /aria/playbook-builder/chat
Multi-turn chat where Aria interviews the user and drafts a playbook. Requires role manager or higher. Returns a complete JSON reply (not SSE). When Aria emits a <playbook_draft> block with 3 or more questions, the block is parsed out of the message and returned as playbook_draft with is_complete: true.
Request body
{
"messages": [
{ "role": "user", "content": "I need a playbook for inbound sales qualification calls." }
],
"template_id": null,
"use_case_slug": "sales-coaching",
"current_playbook": null
}
| Field | Type | Description |
|---|---|---|
messages |
array | Prior turns, each {role, content} (user or assistant). |
template_id |
UUID | null | Start from this playbook template; its name, description, and sample questions seed the reply. |
use_case_slug |
string | null | Use case the playbook targets. |
current_playbook |
object | null | Partial draft to keep building on. |
Response 200
{
"message": "Here is a first draft of your playbook…",
"playbook_draft": {
"name": "Inbound Sales Qualification",
"description": "Scores rep behavior on inbound qualification calls.",
"use_case_slug": "sales-coaching",
"questions": [
{ "id": "q1", "text": "Did the rep confirm budget authority?", "type": "boolean", "weight": 1.0 }
]
},
"is_complete": false,
"suggested_name": "Inbound Sales Qualification"
}
playbook_draft and suggested_name are null until Aria produces a draft. is_complete is true only when the draft has at least 3 questions.
POST /aria/playbook-builder/generate
Single-shot playbook generation from a description. Requires role manager or higher.
Request body
{
"description": "A playbook that scores support escalation calls for empathy and resolution.",
"template_id": null,
"use_case_slug": null
}
Response 200 — the generated playbook as raw JSON:
{
"name": "Support Escalation Quality",
"description": "Scores support escalation calls for empathy and resolution.",
"use_case_slug": "customer-support",
"questions": [
{
"id": "q1",
"prompt": "Did the agent acknowledge the customer's frustration?",
"category": "Empathy",
"severity_level": "INFO",
"sort_order": 0
}
]
}
POST /aria/playbook-builder/save
Persist a playbook draft as a user playbook. Requires workspace role admin or owner.
Request body
{
"playbook_draft": {
"name": "Support Escalation Quality",
"description": "Scores support escalation calls.",
"use_case_slug": "customer-support",
"questions": [
{ "prompt": "Did the agent acknowledge frustration?", "category": "Empathy", "severity_level": "INFO", "sort_order": 0 }
]
},
"set_as_active": true,
"template_id": null
}
Questions accept either prompt or text for the question text; entries without either are skipped. severity_level defaults to INFO, sort_order to the array index. When set_as_active is true (the default), the saved playbook becomes the user's active playbook.
Response 200
{
"id": "8b1a...",
"name": "Support Escalation Quality",
"description": "Scores support escalation calls.",
"user_id": "2d4c...",
"is_builtin": false,
"is_system_template": false,
"template_id": null,
"use_case_slug": "customer-support",
"created_at": "2026-08-19T06:00:00Z",
"updated_at": "2026-08-19T06:00:00Z",
"questions": [
{
"id": "f12b...",
"playbook_id": "8b1a...",
"prompt": "Did the agent acknowledge frustration?",
"category": "Empathy",
"severity_level": "INFO",
"sort_order": 0,
"created_at": "2026-08-19T06:00:00Z"
}
],
"active": true
}
Skill creator
Skills define how Aria analyzes audio (the analytical lens), as opposed to playbooks, which define what to analyze.
POST /aria/skill-creator/chat
Multi-turn chat where Aria drafts a skill. Requires role manager or higher. Returns complete JSON (not SSE). If conversation_id is omitted or malformed, a new skill_creator conversation is created; an unknown-but-valid UUID returns 404.
Request body
{
"message": "I want a skill that flags compliance risks in collections calls.",
"conversation_id": null,
"messages": []
}
| Field | Type | Description |
|---|---|---|
message |
string | The new user message. |
conversation_id |
string (UUID) | null | Existing skill-creator thread to continue. |
messages |
array | Prior turns, each {role, content}; only user/assistant entries with content are used. |
Response 200
{
"message": "Got it — which regulations should the skill watch for?",
"conversation_id": "a1b2c3d4-0000-4000-8000-000000000000",
"skill_draft": null,
"is_complete": false
}
When Aria has enough information it calls its create_skill tool and skill_draft is populated with {name, description, system_prompt, focus_areas, evaluation_criteria, output_format} and is_complete becomes true. The draft is also stored as an artifact on the assistant message.
POST /aria/skill-creator/save
Persist a skill draft as a user skill. Requires workspace role admin or owner. skill_draft.name is required (400 otherwise).
Request body
{
"skill_draft": {
"name": "Collections Compliance Checker",
"description": "Flags compliance risks in collections calls.",
"system_prompt": "You are a compliance analyst…",
"focus_areas": ["Required disclosures", "Prohibited threats"],
"evaluation_criteria": ["Missing mini-Miranda disclosure"],
"output_format": "Bullet list of findings with timestamps"
},
"conversation_id": "a1b2c3d4-0000-4000-8000-000000000000"
}
Response 201
{
"id": "5e6f...",
"user_id": "2d4c...",
"name": "Collections Compliance Checker",
"description": "Flags compliance risks in collections calls.",
"source": "user_created",
"system_prompt": "You are a compliance analyst…",
"focus_areas": ["Required disclosures", "Prohibited threats"],
"evaluation_criteria": ["Missing mini-Miranda disclosure"],
"output_format": "Bullet list of findings with timestamps",
"is_builtin": false,
"created_at": "2026-08-19T06:00:00Z",
"updated_at": "2026-08-19T06:00:00Z",
"conversation_id": "a1b2c3d4-0000-4000-8000-000000000000"
}