Appearance
panel-qualifier
58 endpoints.
GET /api/v1/panel/qualifier/agents
List Agents
200 — Successful Response
json
{}POST /api/v1/panel/qualifier/agents
Create Agent
Request body
json
{
"properties": {
"name": {
"type": "string",
"title": "Name"
},
"slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Slug"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Description"
},
"template": {
"type": "string",
"title": "Template",
"default": "BANT"
}
},
"type": "object",
"required": [
"name"
],
"title": "AgentCreate"
}201 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/panel/qualifier/agents/{slug}
Get Agent
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PATCH /api/v1/panel/qualifier/agents/{slug}
Update Agent
Edit an agent's display name / description. The slug (URL) stays stable so links and references don't break.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Name"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Description"
}
},
"type": "object",
"title": "AgentUpdate",
"description": "Edit an agent's display fields (the slug/URL stays stable)."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/panel/qualifier/agents/{slug}
Delete Agent
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/panel/qualifier/agents/{slug}/versions
List Versions
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/agents/{slug}/versions
Save Version
Compile + persist a new immutable version (spec §3.3). Operator prompt edits persist with the version.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"properties": {
"definition": {
"additionalProperties": true,
"type": "object",
"title": "Definition"
},
"compiled_system_prompt": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Compiled System Prompt"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Notes"
},
"activate": {
"type": "boolean",
"title": "Activate",
"default": true
}
},
"type": "object",
"required": [
"definition"
],
"title": "SaveVersionRequest"
}201 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/panel/qualifier/trainer-rules
Get Trainer Rules
200 — Successful Response
json
{}PUT /api/v1/panel/qualifier/trainer-rules
Set Trainer Rules
Set tenant-wide Trainer rules applied to EVERY agent's interview. Takes effect on new Trainer chats (the CLI keeps a session's original system prompt on resume).
Request body
json
{
"properties": {
"rules": {
"type": "string",
"title": "Rules",
"default": ""
}
},
"type": "object",
"title": "TrainerRulesIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PUT /api/v1/panel/qualifier/agents/{slug}/persona
Set Agent Persona
Save the Agent Persona AND fold it into THIS agent's definition. The persona text is stored workspace-wide (seeds the Trainer + overrides every call, as before); on top of that a focused reconcile pass maps it onto the agent's draft — persona fields (name/tone/language), any greeting/disclosure it states, and standing rules as instruction items — so saving the persona visibly updates the Agent Definition.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"properties": {
"rules": {
"type": "string",
"title": "Rules",
"default": ""
}
},
"type": "object",
"title": "TrainerRulesIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/agents/{slug}/persona/apply
Apply Agent Persona
Apply the CURRENT workspace Agent Persona to this agent's definition if it isn't already applied (idempotent via the persona hash — a no-op once applied). The Trainer calls this on load so the persona is applied automatically by default, no manual Save.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/agents/{slug}/trainer
Trainer Chat
One Trainer interview turn. Resumes the agent's persistent Trainer session; persists the evolving draft definition so re-entry resumes (spec §3.1).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"properties": {
"message": {
"type": "string",
"title": "Message"
},
"image_paths": {
"items": {
"type": "string"
},
"type": "array",
"title": "Image Paths"
}
},
"type": "object",
"required": [
"message"
],
"title": "TrainerMessageIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/agents/{slug}/trainer/fork
Trainer Fork Chat
Fork the interview at an operator bubble with an edited prompt. Seeds a fresh Claude session with the transcript up to the fork point (CLI sessions can't rewind), then continues. The fork becomes the agent's active Trainer session.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"properties": {
"message": {
"type": "string",
"title": "Message"
},
"history": {
"items": {
"properties": {
"role": {
"type": "string",
"title": "Role"
},
"text": {
"type": "string",
"title": "Text"
}
},
"type": "object",
"required": [
"role",
"text"
],
"title": "TrainerTurnIn",
"description": "One chat bubble in the operator/trainer transcript (for forking)."
},
"type": "array",
"title": "History"
},
"image_paths": {
"items": {
"type": "string"
},
"type": "array",
"title": "Image Paths"
}
},
"type": "object",
"required": [
"message"
],
"title": "TrainerForkIn",
"description": "Fork the interview at an operator bubble: replay the transcript up to (but\nnot including) that bubble into a fresh session, then send the edited message."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/agents/{slug}/trainer/reset
Trainer Reset
Start a NEW chat: drop the persistent Trainer session + transcript so the next message begins a fresh conversation. The built-up DRAFT DEFINITION is PRESERVED — a new chat must never discard the agent's knowledge/persona/criteria (never lose data).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/agents/{slug}/trainer/upload
Trainer Upload
Upload a file for the Trainer — an image (logo/brochure/screenshot, spec §3.2 brand cues) OR a document (price list / PDF / CSV). The file is extracted into the Knowledge base RIGHT HERE (one focused call) and persisted, so a price list lands as entries without a slow two-call chat turn. Returns {path, filename, added, definition}: if added>0 the frontend shows the new entries; if added==0 (e.g. a logo) it attaches the path to the next chat message for brand-cue analysis instead.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PATCH /api/v1/panel/qualifier/agents/{slug}/knowledge
Update Knowledge
Replace the draft's merged Knowledge base grid (product/company knowledge + training instructions as a list of rows) — a way to train the agent independent of the Trainer chat (spec §3.2 items 12–13). Persists to the draft so re-entry resumes it; these compile into the runtime system prompt on Save version.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"properties": {
"entries": {
"items": {
"properties": {
"type": {
"type": "string",
"title": "Type",
"default": "knowledge"
},
"topic": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Topic",
"default": ""
},
"content": {
"type": "string",
"title": "Content",
"default": ""
},
"source": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Source",
"default": ""
}
},
"type": "object",
"title": "KnowledgeEntryIn",
"description": "One row of the merged Knowledge base grid."
},
"type": "array",
"title": "Entries"
}
},
"type": "object",
"title": "KnowledgeUpdate",
"description": "Replace the draft's merged knowledge/instructions grid (Knowledge base sidebar),\nindependent of the Trainer chat. Blank-content rows are dropped server-side."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/agents/{slug}/compile
Compile Agent
Deterministically compile a definition + validate + preview the opening (spec §3.1).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"properties": {
"definition": {
"additionalProperties": true,
"type": "object",
"title": "Definition"
}
},
"type": "object",
"required": [
"definition"
],
"title": "CompileRequest"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PATCH /api/v1/panel/qualifier/agents/{slug}/persona-fields
Update Persona Fields
Set the agent's persona fields (name/tone/language/voice/call direction) DIRECTLY on the draft — no LLM, no reconcile, purely the values given. Non-destructive: only the fields you pass change; the rest of the definition (knowledge, criteria, …) is untouched. This is the 'Edit persona' control in the Agent Definition.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Name"
},
"tone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Tone"
},
"language": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Language"
},
"tts_voice": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Tts Voice"
},
"call_direction": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Call Direction"
}
},
"type": "object",
"title": "PersonaFieldsIn",
"description": "Direct edit of the agent's persona fields from the Agent Definition panel. Only\nprovided (non-None) fields are changed; everything else is left exactly as-is."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PATCH /api/v1/panel/qualifier/agents/{slug}/fields
Update Fields
Set multiple definition fields at once by dot-path — a batch of {path: value} (e.g. {"opening.greeting": "...", "qualification.threshold.min": 0.7}). No LLM; NON-DESTRUCTIVE: only the given paths change, everything else is left exactly as-is. Backs the per-section Edit dialogs in the Agent Definition. Type-safe via _apply_path (won't corrupt structure).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Body"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/agents/{slug}/apply-edit
Apply Edit
Apply a single suggested edit (field_path + proposed) to the draft definition — backs the Eval Report's one-click "Apply to Trainer" (spec §4.3).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"type": "object",
"additionalProperties": true,
"title": "Body"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/panel/qualifier/scenarios
List Scenarios
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
agent_id | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/scenarios
Create Scenario
Request body
json
{
"properties": {
"name": {
"type": "string",
"title": "Name"
},
"slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Slug"
},
"agent_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Agent Id"
},
"persona": {
"additionalProperties": true,
"type": "object",
"title": "Persona"
},
"ground_truth": {
"additionalProperties": true,
"type": "object",
"title": "Ground Truth"
},
"edge_cases": {
"items": {
"type": "string"
},
"type": "array",
"title": "Edge Cases"
},
"seed": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Seed"
},
"channel": {
"type": "string",
"title": "Channel",
"default": "inbound"
}
},
"type": "object",
"required": [
"name"
],
"title": "ScenarioCreate"
}201 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PATCH /api/v1/panel/qualifier/scenarios/{slug}
Update Scenario
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
Request body
json
{
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Name"
},
"persona": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"title": "Persona"
},
"ground_truth": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"title": "Ground Truth"
},
"edge_cases": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"title": "Edge Cases"
},
"seed": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Seed"
},
"enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Enabled"
},
"channel": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Channel"
}
},
"type": "object",
"title": "ScenarioUpdate"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/panel/qualifier/scenarios/{slug}
Delete Scenario
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
slug | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/scenarios/generate
Generate Scenario
Studio-generated caller persona + ground truth from a free-text brief (spec §4.2).
Request body
json
{
"properties": {
"agent_id": {
"type": "string",
"title": "Agent Id"
},
"brief": {
"type": "string",
"title": "Brief"
}
},
"type": "object",
"required": [
"agent_id",
"brief"
],
"title": "GenerateScenarioRequest"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/run
Run Test Call
Run a single test call against the agent's current Trainer config (draft) — so the test uses the latest Trainer data + the org Agent Identity — evaluate it, persist, and return the transcript + Eval Report (spec §4).
Request body
json
{
"properties": {
"agent_id": {
"type": "string",
"title": "Agent Id"
},
"scenario_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Scenario Id"
},
"scenario": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"title": "Scenario"
},
"mode": {
"type": "string",
"title": "Mode",
"default": "sim"
},
"max_turns": {
"type": "integer",
"title": "Max Turns",
"default": 30
}
},
"type": "object",
"required": [
"agent_id"
],
"title": "RunSimRequest"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/call-out
Call Out
Place a REAL outbound test call — the manual "Call now" trigger from Test Studio/the agent editor. See :func:place_outbound_call for the shared logic.
Request body
json
{
"properties": {
"agent_id": {
"type": "string",
"title": "Agent Id"
},
"to_number": {
"type": "string",
"title": "To Number"
},
"lead_name": {
"type": "string",
"title": "Lead Name",
"default": ""
}
},
"type": "object",
"required": [
"agent_id",
"to_number"
],
"title": "CallOutRequest"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/telephony/test-register
Telephony Test Register
Ask the voice worker to attempt a SIP REGISTER with the org's SIP account and report whether it succeeded — the Settings → Telephony "Register" button.
Request body
json
{
"properties": {
"sip_username": {
"type": "string",
"title": "Sip Username",
"default": ""
},
"sip_password": {
"type": "string",
"title": "Sip Password",
"default": ""
},
"sip_domain": {
"type": "string",
"title": "Sip Domain",
"default": ""
},
"sip_server": {
"type": "string",
"title": "Sip Server",
"default": ""
}
},
"type": "object",
"title": "TelephonyTestIn",
"description": "Settings → Telephony \"Register\" button. Tests the supplied values (so the\noperator can verify before saving); blanks fall back to the saved settings."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/run-suite
Run Suite
Run every enabled scenario for an agent — regression pass/fail dashboard (spec §4.3).
Request body
json
{
"properties": {
"agent_id": {
"type": "string",
"title": "Agent Id"
}
},
"type": "object",
"required": [
"agent_id"
],
"title": "RunSuiteRequest"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/panel/qualifier/plans
List Plans
The package ladder — what an upgrade prompt offers. Unpublished tiers are included so a tenant sitting on a retired plan still sees their own.
200 — Successful Response
json
{}GET /api/v1/panel/qualifier/plan
Get Plan
This tenant's package, its effective limits, and this period's usage — the Plan & Usage page in one request.
features is the full registry with a granted flag rather than only the granted keys, so the page can render the whole ladder with ticks and crosses (and name what an upgrade would add) without a second round trip.
200 — Successful Response
json
{}PUT /api/v1/panel/qualifier/plan
Assign Plan
Put this tenant on a package (or change/suspend the one they're on).
Owner-gated rather than admin: this is the row that decides what the tenant is billed AND whether they can see the app at all, so it isn't an ordinary admin edit. Selling through the shop writes the same row (see services/qualifier_billing.py); this is the manual path.
Request body
json
{
"properties": {
"plan_code": {
"type": "string",
"title": "Plan Code"
},
"status": {
"type": "string",
"title": "Status",
"default": "active"
},
"billing_day": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Billing Day"
},
"included_minutes_override": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Included Minutes Override"
},
"max_agents_override": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Max Agents Override"
},
"max_concurrent_override": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Max Concurrent Override"
},
"extra_features": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"title": "Extra Features"
},
"extra_languages": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"title": "Extra Languages"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Notes"
}
},
"type": "object",
"required": [
"plan_code"
],
"title": "PlanAssignIn",
"description": "Put a tenant on a package. ``plan_code`` is one of ``QualPlan.code``."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/panel/qualifier/usage/history
Usage History
Closed billing periods for this tenant — the metered history behind past invoices (see QualUsagePeriod on why only closed periods are stored).
200 — Successful Response
json
{}GET /api/v1/panel/qualifier/calls/{call_id}/recording
Get Recording
Stream a call's recording for the Call Logs player.
Served through the API rather than statically by nginx on purpose: these are recorded customer conversations, so every read goes through the same tenant-scoped auth as the transcript it belongs to.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
call_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/calls/{call_id}/recording
Upload Recording
Store the voice worker's mixed recording of a finished call.
Posted by the worker at teardown (telecloud-conversational-ai/app/brain.py upload_recording) with the token it already holds for this call, so no new auth path exists. answered_at is the worker's first-audio timestamp — the authoritative answer moment, more accurate than the backend's "when /voice-turn/open ran", so re-metering off it here corrects any ring time that slipped into the duration.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
call_id | path | yes | string | |
answered_at | query | no | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/retention/purge
Retention Purge
POPIA retention (spec §2): delete the transcript turns + eval reports and scrub captured lead fields for calls older than each agent's data_capture.retention_days. Runs daily via the in-process scheduler; this triggers it on demand for the caller's tenant. Returns purge counts.
200 — Successful Response
json
{}POST /api/v1/panel/qualifier/voice-turn/open
Voice Open
Start a live call: create the session and return the opening line.
The opening is DETERMINISTIC — the scripted greeting (+ disclosure) straight from the definition — so we DON'T spend an LLM round-trip on it. That round-trip (a cold Groq call) can take 10-15s, which the caller hears as DEAD AIR the moment they answer, and they hang up before the agent ever speaks. The greeting is fixed script text anyway (the LLM was only echoing it verbatim). The Groq brain is stateless and replays the transcript each turn, so persisting this opening as turn 0 gives the next (real) turn full continuity — there's no live session to warm here.
Request body
json
{
"properties": {
"agent_slug": {
"type": "string",
"title": "Agent Slug"
},
"mode": {
"type": "string",
"title": "Mode",
"default": "voice"
},
"to_number": {
"type": "string",
"title": "To Number",
"default": ""
},
"lead_name": {
"type": "string",
"title": "Lead Name",
"default": ""
},
"balance": {
"type": "string",
"title": "Balance",
"default": ""
}
},
"type": "object",
"required": [
"agent_slug"
],
"title": "VoiceOpenRequest"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/voice-turn/{call_id}
Voice Turn
Run one agent turn for an in-progress call (rehydrated from the call row).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
call_id | path | yes | string |
Request body
json
{
"properties": {
"caller_text": {
"type": "string",
"title": "Caller Text"
}
},
"type": "object",
"required": [
"caller_text"
],
"title": "VoiceTurnRequest"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/voice-turn/{call_id}/end
Voice Turn End
Finalize a live call when the CALLER hangs up (SIP BYE) — the worker calls this so the backend doesn't leave the session 'running' until the reaper sweeps it ~2 min later (the "agent still active" symptom). Closes the row AND — the important part — never loses an agreed callback: if the call is callback-mode, the caller showed interest, a callback day/time can be extracted from the transcript, and nothing was booked yet, it books it NOW (mid-call booking can miss when the caller drops the line before the model emits a wrap-up action). Idempotent.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
call_id | path | yes | string |
Request body
json
{
"properties": {
"reason": {
"type": "string",
"title": "Reason",
"default": "caller_hangup"
}
},
"type": "object",
"title": "VoiceEndRequest"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/voice-turn/{call_id}/stream
Voice Turn Stream
Streaming variant of voice-turn: emits NDJSON — {"t":"d","x":<delta>} lines as the agent speaks, then a final {"t":"done", ...} with the enforced decision. Lets the worker TTS sentence-by-sentence (talk on the first sentence). Persists the turn at the end; get_db commits after the streamed body completes.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
call_id | path | yes | string |
Request body
json
{
"properties": {
"caller_text": {
"type": "string",
"title": "Caller Text"
}
},
"type": "object",
"required": [
"caller_text"
],
"title": "VoiceTurnRequest"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/panel/qualifier/calls
List Calls
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
agent_id | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/panel/qualifier/calls/{call_id}
Get Call
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
call_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/calls/{call_id}/stop
Stop Call
Force-end a live (running) chat/call. Marks the session closed so the voice worker / sim loop stops driving it and it drops out of the active-chats list.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
call_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/calls/clear
Clear Calls
Clear the call log: soft-delete every ended call for the tenant (optionally scoped to one agent). Live ("running") calls are left untouched so in-progress chats aren't broken. Soft delete keeps booked callbacks intact (they SET NULL).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
agent_id | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/panel/qualifier/callbacks
List Callbacks
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
frm | query | no | ||
to | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/callbacks
Create Callback
Request body
json
{
"properties": {
"callback_at": {
"type": "string",
"format": "date-time",
"title": "Callback At"
},
"call_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Call Id"
},
"lead_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Lead Name"
},
"lead_phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Lead Phone"
},
"lead_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Lead Email"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Notes"
},
"lead_data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"title": "Lead Data"
}
},
"type": "object",
"required": [
"callback_at"
],
"title": "CallbackCreate"
}201 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PATCH /api/v1/panel/qualifier/callbacks/{callback_id}
Update Callback
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
callback_id | path | yes | string |
Request body
json
{
"properties": {
"callback_at": {
"anyOf": [
{
"type": "string",
"format": "date-time"
},
{
"type": "null"
}
],
"title": "Callback At"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Status"
},
"lead_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Lead Name"
},
"lead_phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Lead Phone"
},
"lead_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Lead Email"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Notes"
}
},
"type": "object",
"title": "CallbackUpdate"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/panel/qualifier/callbacks/{callback_id}
Delete Callback
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
callback_id | path | yes | string |
204 — Successful Response
422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/commitments/send-test-warning
Send Test Commitment Warning
Send the daily payment-deadline warning template right now, to a chosen email/phone, so an admin can check wording/delivery before the real job fires (see scheduler_engine._handler_debtor_commitment_warnings, which runs this same content for every commitment due today). Not tied to a real DebtorCommitment row — 'today' and the supplied name/amount (or sensible test defaults) stand in for a real one.
Request body
json
{
"properties": {
"to_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "To Email"
},
"to_phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "To Phone"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Name"
},
"amount": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Amount"
}
},
"type": "object",
"title": "CommitmentTestWarningIn"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/panel/qualifier/commitments
List Commitments
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
frm | query | no | ||
to | query | no |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/commitments
Create Commitment
Request body
json
{
"properties": {
"promised_at": {
"type": "string",
"format": "date-time",
"title": "Promised At"
},
"promised_amount": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Promised Amount"
},
"call_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Call Id"
},
"deal_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Deal Id"
},
"customer_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Customer Id"
},
"lead_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Lead Name"
},
"lead_phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Lead Phone"
},
"lead_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Lead Email"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Notes"
},
"lead_data": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"title": "Lead Data"
},
"allow_duplicate": {
"type": "boolean",
"title": "Allow Duplicate",
"default": false
}
},
"type": "object",
"required": [
"promised_at"
],
"title": "CommitmentCreate"
}201 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}PATCH /api/v1/panel/qualifier/commitments/{commitment_id}
Update Commitment
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
commitment_id | path | yes | string |
Request body
json
{
"properties": {
"promised_at": {
"anyOf": [
{
"type": "string",
"format": "date-time"
},
{
"type": "null"
}
],
"title": "Promised At"
},
"promised_amount": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Promised Amount"
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Status"
},
"lead_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Lead Name"
},
"lead_phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Lead Phone"
},
"lead_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Lead Email"
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Notes"
}
},
"type": "object",
"title": "CommitmentUpdate"
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/panel/qualifier/commitments/{commitment_id}
Delete Commitment
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
commitment_id | path | yes | string |
204 — Successful Response
422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/panel/qualifier/sms/status
Sms Status
Whether SMS sending is configured (so the UI can warn before composing).
200 — Successful Response
json
{}GET /api/v1/panel/qualifier/sms/balance
Sms Balance
Carrier (Panacea) SMS credit balance — ported from the portal's SyncSmsBalance.
200 — Successful Response
json
{}GET /api/v1/panel/qualifier/sms/inbox
Sms Inbox
Received SMS since last_id (Panacea messages_get) — ported from FetchSmsInbox.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
last_id | query | no | integer |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/panel/qualifier/sms/message-status/{message_id}
Sms Message Status
Delivery status of a previously sent message (Panacea message_status).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
message_id | path | yes | string |
200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/panel/qualifier/sms/send
Send Sms Bulk
Send one message to: pasted recipients + the captured phone numbers of the given callback_ids / call_ids. Numbers are merged, normalised and de-duped in the SMS client. Returns the per-number send result.
Request body
json
{
"properties": {
"message": {
"type": "string",
"title": "Message"
},
"recipients": {
"items": {
"type": "string"
},
"type": "array",
"title": "Recipients"
},
"callback_ids": {
"items": {
"type": "string"
},
"type": "array",
"title": "Callback Ids"
},
"call_ids": {
"items": {
"type": "string"
},
"type": "array",
"title": "Call Ids"
}
},
"type": "object",
"required": [
"message"
],
"title": "SmsSendRequest",
"description": "Bulk SMS send. ``recipients`` are pasted/typed numbers; ``callback_ids`` and\n``call_ids`` pull the captured lead phone numbers from those callbacks/calls. All\nsources are merged, normalised and de-duped before sending."
}200 — Successful Response
json
{}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}