Persona Manager โ API reference
All endpoints are routed through the existing NestJS API and inherit:
JwtAuthGuardfor authenticationOrgRlsInterceptorfor Postgres-level RLS (SET LOCAL app.current_org_id)OrgThrottlerGuard(globalAPP_GUARD) for per-org rate limits
Webhook endpoints use HMAC-SHA256 instead of JWT.
SuperAdmin: function-call libraryโ
| Method | Path | Roles |
|---|---|---|
| GET | /ops/personas/function-calls?kind=onboarding|reporting&includeInactive=true | superadmin, account_manager |
| GET | /ops/personas/function-calls/:id | superadmin, account_manager |
| POST | /ops/personas/function-calls | superadmin |
| PATCH | /ops/personas/function-calls/:id | superadmin |
| POST | /ops/personas/function-calls/:name/versions | superadmin |
| DELETE | /ops/personas/function-calls/:id | superadmin |
Body shapes match TavusFunctionDefinition in api/src/tavus/tavus-function-definition.entity.ts.
Tavus catalogueโ
| Method | Path | Roles |
|---|---|---|
| GET | /tavus/replicas | superadmin, account_manager, client_admin, org_admin |
Returns the cached (5min TTL) replica list from Tavus.
Environment Profileโ
| Method | Path | Auth |
|---|---|---|
| GET | /environment-profiles/:id | JwtAuthGuard + service-layer org-scope check |
| GET | /environment-profiles/by-assignment/:assignmentId | same |
| PATCH | /environment-profiles/:id ({ data: {...} }) | same |
| POST | /environment-profiles/:id/approve | same |
Meetingsโ
| Method | Path | Notes |
|---|---|---|
| POST | /assignments/:assignmentId/onboarding/start | Idempotent. Returns { meeting, conversationUrl, created }. |
| POST | /assignments/:assignmentId/meetings | Schedule a reporting meeting. |
| POST | /assignments/:assignmentId/meetings/:meetingId/start | Start a scheduled reporting meeting. Assembles the brief and creates the persona. |
| GET | /assignments/:assignmentId/meetings | List meetings for an assignment. |
| GET | /meetings/:id | Single meeting detail. |
Tavus webhooksโ
| Method | Path | Headers |
|---|---|---|
| POST | /tavus/webhooks/function-call | Tavus-Signature (or X-Tavus-Signature) = HMAC-SHA256 hex of raw body, keyed on TAVUS_WEBHOOK_SECRET. |
| POST | /tavus/webhooks/transcript-ready | same |
Idempotency: keyed off event_id / idempotency_key in the body or the Tavus-Idempotency-Key header. 24-hour Redis TTL; in-memory fallback when Redis is unreachable.
Error contractโ
Errors return JSON { code, message } with status codes:
| Code | Meaning |
|---|---|
tavus_unconfigured (503) | TAVUS_API_KEY is unset on the API. |
tavus_unauthorised (401/403) | Upstream Tavus rejected the call. |
tavus_not_found (404) | Upstream resource missing. |
tavus_conflict (409) | Upstream conflict (e.g. archiving an already-deleted persona โ swallowed). |
tavus_rate_limited (429) | Upstream rate limit. |
tavus_upstream_error (5xx) | Anything else from Tavus. |
tavus_network (502) | Network-level failure reaching Tavus. |
replica_not_set (409) | No TAVUS_DEFAULT_REPLICA_ID configured and the request didn't override. |
onboarding_in_inconsistent_state (409) | A prior start crashed mid-flight; archive the row and retry. |
meeting_already_terminal (409) | Can't restart a completed/cancelled meeting. |
The controller never leaks raw upstream payloads.
Socket.io eventsโ
Namespace: /notifications (existing).
| Event | Room | Payload |
|---|---|---|
meeting_started | org:<orgId> | { meeting_id, kind, assignment_id } |
meeting_function_call | org:<orgId> | { meeting_id, function_name, ... } |
meeting_completed | org:<orgId> | { meeting_id, kind } |