API Reference
Base URL: https://api.h.work (prod) / https://api.h852.work (staging)
Auth: Authorization: Bearer <jwt> on all protected endpoints unless noted.
Global rate limit: 100 req/min per IP. Auth endpoints: 10 req/min.
โ ๏ธ Frontend โ API surface. The
/ops/*prefix exists on the frontend (Next.js, underfrontend/src/app/ops/), but most ops surfaces on the API are still served from/am/orgs/*,/superadmin/*, or/admin/*. The real/ops/*API routes today are the Tavus function-call admin under/ops/tavus/function-calls(renamed from/ops/personas/function-callsvia #1031 โ old paths return 308 redirects for ~30 days) and the legacy tombstonePOST /ops/orgs/:orgId/ragflow-provision, which returns a compatibility response. Server-side redirects from/am/*and/superadmin/*to/ops/*apply to frontend routes only; the underlying API paths have not moved. Tracked: #247.
Auth column legend: JWT = JwtAuthGuard only ยท SA = superadmin ยท AM = account_manager+ ยท Expert = expert+ ยท OrgAdmin/OrgMember/OrgOwner = OrgRolesGuard role ยท Token = onboarding/invite token ยท Agent = AgentTokenGuard HMAC.
Healthโ
Source: health.controller.ts, common/metrics.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /health | None | Liveness probe |
| GET | /ready | None | Readiness probe (DB + agent connectivity) |
| GET | /metrics | Network policy | Prometheus metrics (internal only) |
Authโ
Source: auth/auth.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /auth/register | None | Self-service: create org + first admin user |
| POST | /auth/login | None | Returns JWT with userId, email, platformRole, orgMemberships |
| POST | /auth/demo-login | None | Demo backdoor (DEMO_MODE=true only) |
| POST | /auth/orgs | SA | Create org with admin user |
| POST | /auth/accept-invite/:token | None | Accept invite + set password โ JWT |
| POST | /orgs/:orgId/invites | OrgAdmin | Invite user by email |
| DELETE | /orgs/:orgId/members/:userId | OrgAdmin | Remove user from org |
| GET | /orgs/:orgId | OrgMember | Org details |
| GET | /orgs/:orgId/members | OrgMember | List org members |
Password Resetโ
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /auth/request-password-reset | None | Send password-reset email |
| POST | /auth/reset-password | None | Complete password reset with token |
2FAโ
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /auth/2fa/setup | JWT | Generate TOTP secret + QR code URI |
| POST | /auth/2fa/verify | JWT | Verify TOTP code and enable 2FA |
Superadmin Auth Toolsโ
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /auth/bootstrap-superadmin | None (once) | Promote first user if no superadmin exists |
| GET | /admin/users/:id | SA | Fetch any user by id |
| PATCH | /admin/users/:id | SA | Update arbitrary user fields |
| PATCH | /admin/users/:id/role | SA | Update platformRole |
| PATCH | /admin/users/:id/password | SA | Reset password |
OTP & Invite Flowโ
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /invites/validate | None | Validate invite token |
| POST | /auth/send-invite-otp | None | Send email OTP |
| POST | /auth/verify-invite-otp | None | Verify OTP โ create/activate account |
| POST | /auth/request-otp | None | Generic OTP request |
| POST | /auth/verify-otp | None | Generic OTP verify |
Conversationsโ
Source: conversations/conversations.controller.ts. Rate limit: 100 req/min per PRD ยง14.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /conversations | JWT | Create conversation |
| GET | /conversations | JWT | List conversations (filter: orgId) |
| GET | /conversations/search | JWT | Full-text search (q, orgId, limit, offset) |
| GET | /conversations/:id | JWT | Fetch conversation + messages (paginated) |
| POST | /conversations/:id/messages | JWT | Send message |
| POST | /conversations/:id/messages/stream | JWT | Stream agent response as SSE |
| PATCH | /conversations/:id/status | Expert | Update conversation status |
| PATCH | /conversations/:id/assign | Expert | Reassign Specialist on a conversation |
| POST | /conversations/:id/assign-agent | JWT | Trigger agentic-mode re-assignment |
| GET | /conversations/:id/assignment-history | Expert | Append-only assignment audit (#363) |
Internal Agent Thread (HP staff only)โ
These power the Expert/AM "ask the agent" side panel and are guarded by PlatformRolesGuard.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /conversations/:id/agent-thread | Staff | Fetch internal agent-thread for conversation |
| POST | /conversations/:id/agent-thread/messages | Staff | Send message to internal agent thread |
| POST | /conversations/:id/agent-thread/messages/stream | Staff | SSE stream from internal agent thread |
Expert Queueโ
Source: expert-queue/expert-queue.controller.ts. All routes require PlatformRolesGuard (expert, account_manager, or superadmin unless noted).
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /expert-queue | Expert | List queue items (filter: status, orgId) |
| GET | /expert-queue/:id | Expert | Fetch single queue item |
| PATCH | /expert-queue/:id | Expert | Update queue item (generic patch) |
| PATCH | /expert-queue/:id/status | Expert | Update status (4-state: pending/awaiting_client/resolved/snoozed; widened by #1985) |
| POST | /expert-queue/:id/suggest | Expert | Get fresh AI suggestion for item |
| POST | /expert-queue/:id/respond | Expert | Send response (approve/edit/write own) |
| POST | /expert-queue/:id/resolve | Expert | Resolve with satisfaction score |
| POST | /expert-queue/:id/defer | Expert | Defer item by X hours |
| POST | /expert-queue/:id/add-note | Expert | Add internal note |
| POST | /expert-queue/:id/corrections | Expert | Submit correction for learning loop |
| POST | /expert-queue/:id/drafts/:draftId/release | Expert | Per-draft release (Expert hands a single draft off the queue) โ #1878 / PR #1966 |
| POST | /expert-queue/:id/drafts/:draftId/discard | Expert | Per-draft discard (Expert drops a single draft) โ #1878 / PR #1966 |
| POST | /expert-queue/admin/resurface-snoozed | SA | Force-resurface all snoozed items |
| GET | /expert/orgs | Expert | Get Expert's available orgs |
| GET | /expert/orgs/:orgId/assignable-experts | Expert | List experts assignable on this org |
Per-thread Slack queue items (#1877)โ
Slack channel queue items are keyed by (conversation_id, slack_thread_ts) so each Slack thread becomes its own queue item rather than collapsing onto the parent conversation. The standard /expert-queue/* endpoints above accept these items transparently; the additional thread key is exposed on the response payload as slackThreadTs.
Agent Statusโ
Source: agents/agent-status.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /agent/status | Staff | Liveness/health of agent service |
Onboardingโ
Source: onboarding/onboarding.controller.ts. All onboarding endpoints use a token (from the invitation email) instead of JWT auth.
Client-Facing (Phase 2 Wizard)โ
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /onboarding/:token/verify-email | Token | Send OTP to admin email |
| POST | /onboarding/:token/confirm-otp | Token | Verify OTP โ session JWT |
| POST | /onboarding/:token/profile | Token | Save name, title, phone |
| GET | /onboarding/:token/org | Token | Org details for wizard |
| GET | /onboarding/:token/specialist | Token | Assigned Specialist card |
| POST | /onboarding/:token/confirm-slug | Token | Finalize and reserve slug |
| POST | /onboarding/:token/invite-members | Token | Invite multiple Client Members |
| POST | /onboarding/:token/complete | Token | Finalize onboarding (Step 2.6) |
| POST | /onboarding/:token/business-context | Token | Submit business context |
| GET | /onboarding/:token/whitelist | Token | List email whitelist entries |
| POST | /onboarding/:token/whitelist | Token | Add entry to whitelist |
| DELETE | /onboarding/:token/whitelist/:id | Token | Remove whitelist entry |
Public Slug / Invite Endpointsโ
Sources: auth.controller.ts, organizations.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /orgs/slug-check | None | Real-time slug availability check |
| GET | /api/slugs/:slug/resolve | None | Resolve slug โ org info |
| GET | /invitations/:token/validate | None | Validate invite token, return org slug |
| GET | /client/trial-info | JWT | Trial countdown for client portal |
Organizations โ Account Manager / Superadminโ
Source: organizations/organizations.controller.ts.
API contract: the AM portal is still served from
/am/orgs/*on the API even though the frontend now lives at/ops/clients/*. See the banner at the top of this file (#247).
Core AM org routesโ
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /am/orgs | AM | List AM's assigned orgs |
| GET | /am/orgs/:orgId | AM | Org detail |
| PATCH | /am/orgs/:orgId | AM | Update company info |
| GET | /am/orgs/:orgId/phase0-status | AM | Phase 0 validation checklist |
| POST | /am/orgs/:orgId/invite | AM | Send client invitation (Phase 0 gate check) |
| POST | /am/orgs/:orgId/invite/resend | AM | Resend invitation (fresh 7-day token) |
| DELETE | /am/orgs/:orgId/invite | AM | Revoke invitation |
| POST | /am/orgs/:orgId/finish-setup | AM | Mark AM setup complete |
| POST | /am/orgs/:orgId/deactivate | AM | Deactivate org (AM-side) |
| GET | /orgs/:orgId/audit | AM/SA | Per-org audit log |
Specialists (AM catalog + per-org assignment)โ
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /am/specialists | AM | List available specialists |
| GET | /am/specialists/:id | AM | Specialist detail |
| GET | /am/orgs/:orgId/specialists | AM | Specialists assigned to org |
| POST | /am/orgs/:orgId/specialist | AM | Assign Specialist to org |
| PATCH | /am/orgs/:orgId/specialist-assignments/:assignmentId | AM | Update assignment (threshold, primary) |
| GET | /am/orgs/:orgId/specialist-assignments/:assignmentId/rate-history | AM | Hourly-rate history for assignment |
| DELETE | /am/orgs/:orgId/specialist | AM | Remove all Specialists from org |
| DELETE | /am/orgs/:orgId/specialist/:specialistId | AM | Remove one Specialist from org |
Expert โ Org Assignmentโ
/organizations/:orgId/experts is the canonical surface; /am/orgs/:orgId/experts is the legacy surface still served by the controller.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /organizations/:orgId/experts | OrgAdmin | List experts for org |
| POST | /organizations/:orgId/experts | OrgAdmin | Assign expert to org |
| DELETE | /organizations/:orgId/experts/:expertId | OrgAdmin | Remove expert from org |
| GET | /am/orgs/:orgId/experts | AM | List experts (legacy) |
| POST | /am/orgs/:orgId/experts | AM | Assign expert (legacy) |
| DELETE | /am/orgs/:orgId/experts/:expertId | AM | Remove expert (legacy) |
| GET | /am/experts | AM | Global expert directory |
Specialist Change Requestsโ
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /orgs/:orgId/specialist-change-requests | OrgAdmin | Client requests different Specialist |
| GET | /orgs/:orgId/specialist-change-requests | AM | AM views pending requests |
| PATCH | /orgs/:orgId/specialist-change-requests/:id | AM | AM fulfills or declines request |
Org Ownership / Trialโ
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /orgs/:orgId/transfer-ownership | OrgOwner | Transfer org ownership |
Superadmin Org Endpointsโ
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /organizations | SA | Create org |
| POST | /orgs | SA | Create org (legacy alias of /organizations) |
| GET | /superadmin/orgs | SA | List all orgs |
| GET | /superadmin/orgs/:orgId/invite-token | SA | Get current invite token |
| DELETE | /superadmin/orgs/:orgId | SA | Permanently delete org |
| GET | /experts | SA | List all experts |
| POST | /ops/orgs/:orgId/ragflow-provision | SA | Removed provisioning path; returns a compatibility tombstone because Haystack has no per-org provisioning step |
| POST | /admin/orgs/:orgId/rebrand | SA | Rebrand org (name/slug) |
| POST | /admin/orgs/:orgId/deactivate | SA | Deactivate org (SA-side) |
Note: /ops/orgs/:orgId/ragflow-provision retains the legacy ragflow-provision path during the P3-1 migration; it will be renamed in a follow-up.
Client Portal Helpersโ
Source: organizations/organizations.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /client/context | JWT | Full client portal context |
| GET | /client/specialists | JWT | Client's assigned Specialists |
| GET | /client/org-info | JWT | Org info for client portal |
Admin (per-org + platform ops)โ
Source: admin/admin.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /admin/members | SA / OrgAdmin / AM | List members |
| GET | /admin/internal-staff | SA | List HP internal staff |
| POST | /admin/members/invite | SA / OrgAdmin | Invite member |
| PATCH | /admin/members/:id/role | SA / OrgAdmin | Change member role |
| DELETE | /admin/members/:id | SA / OrgAdmin | Remove member |
| DELETE | /admin/invites/:id | SA / OrgAdmin | Revoke a pending invite |
| POST | /admin/invites/:id/resend | SA / OrgAdmin | Resend a pending invite |
| GET | /admin/billing | SA / OrgAdmin | Org billing status |
| GET | /admin/quota | SA / OrgAdmin | Org quota usage |
| GET | /admin/users | SA | Search users globally |
| POST | /admin/impersonate/:userId | SA | Start impersonation session |
| POST | /admin/impersonate/am/:userId | SA | Start silent AM impersonation |
| DELETE | /admin/impersonate | SA | End impersonation session |
| POST | /admin/orgs/:orgId/restore | SA | Restore archived stale org |
| GET | /admin/test/latest-otp | SA | Test-only: fetch most recent OTP |
| GET | /admin/orgs/:orgId/invite-token | SA / AM | Read current invite token |
| POST | /admin/backfill-subjects | SA | Backfill auth subjects (one-shot) |
Admin ยท Specialists Catalogโ
Source: admin/admin-specialists.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /admin/specialists | SA | List Specialist catalog |
| POST | /admin/specialists | SA | Create catalog Specialist |
| PATCH | /admin/specialists/:id | SA | Update catalog Specialist |
| DELETE | /admin/specialists/:id | SA | Delete catalog Specialist |
| GET | /admin/specialists/export | SA | Export catalog JSON |
| POST | /admin/specialists/push-to-r2 | SA | Publish live DB state to R2 manifest |
| POST | /admin/specialists/seed-catalog | SA | Seed catalog from manifest |
Admin ยท Experts (SuperAdmin fast-path)โ
Source: admin/admin-experts.controller.ts (#1221, closes #1208).
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /admin/experts | SA | Direct Expert creation (bypasses waitlist/lead flow) |
Admin ยท Marketing Leadsโ
Source: admin/admin-marketing-leads.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /admin/marketing/leads/companies | SA | List company leads |
| GET | /admin/marketing/leads/companies/:id | SA | Company lead detail |
| PATCH | /admin/marketing/leads/companies/:id/status | SA | Update company lead status |
| GET | /admin/marketing/leads/experts | SA | List expert applications |
| GET | /admin/marketing/leads/experts/:id | SA | Expert application detail |
| PATCH | /admin/marketing/leads/experts/:id/status | SA | Update expert app status |
| POST | /admin/marketing/leads/experts/:id/promote | SA | Promote waitlisted Expert to active (#1200, closes #1084) |
| POST | /admin/marketing/leads/experts/:id/decline | SA | Decline Expert application (#1200, closes #1084) |
Admin ยท DLQโ
Source: channels/dlq-admin.controller.ts. Prefix /admin/dlq. See DLQ Admin feature + DLQ Handling runbook.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /admin/dlq | SA | List dead-letter entries (filter status/channel/org) |
| GET | /admin/dlq/stats | SA | DLQ aggregate stats (count by status + pending) |
| POST | /admin/dlq/drain | SA | Drain entries (mark drained, no redelivery) |
| POST | /admin/dlq/replay | SA | Replay entries (reset dead/drained โ queued) |
Admin ยท WhatsApp Poolโ
Source: admin/whatsapp-admin.controller.ts. Prefix /admin/whatsapp/pool.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /admin/whatsapp/pool | SA | List pool numbers |
| GET | /admin/whatsapp/pool/health | SA | Pool health |
| POST | /admin/whatsapp/pool | SA | Add number to pool |
| PATCH | /admin/whatsapp/pool/:id | SA | Update pool number |
| POST | /admin/whatsapp/pool/:id/assign/:specialistId | SA | Assign number to a Specialist |
| POST | /admin/whatsapp/pool/:id/retire | SA | Retire number |
| POST | /admin/whatsapp/pool/:id/unassign | SA | Unassign number from Specialist |
Admin ยท Integrations Catalogโ
Source: admin/integrations-catalog/integrations-catalog.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /v1/admin/integrations/catalog | SA | List supported integrations |
Email Whitelistโ
Source: organizations/organizations.controller.ts. Same underlying data, two surfaces.
AM-sideโ
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /am/orgs/:orgId/email-whitelist | AM | List email whitelist |
| POST | /am/orgs/:orgId/email-whitelist | AM | Add to whitelist |
| DELETE | /am/orgs/:orgId/email-whitelist/:id | AM | Remove from whitelist |
Client-sideโ
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /client/orgs/:orgId/email-whitelist | OrgMember | List email whitelist |
| POST | /client/orgs/:orgId/email-whitelist | OrgAdmin | Add to whitelist |
| DELETE | /client/orgs/:orgId/email-whitelist/:id | OrgAdmin | Remove from whitelist |
Auto-Reply Configurationโ
Source: organizations/organizations.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /orgs/:orgId/auto-reply-config | SA/AM/Expert | Get auto-reply configuration |
| PATCH | /orgs/:orgId/auto-reply-config | SA/AM | Update auto-reply configuration |
Expert Access (ADR-007, canonical)โ
Source: expert-access/expert-access.controller.ts. Prefix /orgs/:orgId/expert-access. All routes require superadmin or account_manager.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /orgs/:orgId/expert-access | SA/AM | Create access grant (scope=org or specialist) |
| GET | /orgs/:orgId/expert-access | SA/AM | List access grants for org |
| DELETE | /orgs/:orgId/expert-access/:grantId | SA/AM | Revoke a single grant |
| DELETE | /orgs/:orgId/expert-access/expert/:expertId | SA/AM | Revoke all grants for an expert on this org |
Channelsโ
Inbound Webhooksโ
Sources: channels/slack/slack.controller.ts (Slack inbound, post-#1212 SlackModule refactor), channels/channels.controller.ts (Email, WhatsApp, Teams, WeChat), channels/telegram/telegram.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /channels/slack/events | Slack HMAC-SHA256ยน | Slack Events API webhook |
| POST | /channels/email/inbound | None (Cloudflare) | Cloudflare Email Routing inbound webhook |
| POST | /channels/whatsapp/inbound | Twilio HMAC-SHA1 | WhatsApp inbound |
| POST | /channels/whatsapp/status | Twilio HMAC-SHA1 | WhatsApp delivery status callback |
| POST | /channels/teams/webhook | Bot Framework | Teams inbound webhook |
| POST | /channels/teams/messages | Bot Framework | Teams proactive-message endpoint |
| GET | /channels/wechat/webhook | None | WeChat verification challenge |
| POST | /channels/wechat/webhook | WeChat signature | WeChat inbound |
| POST | /channels/telegram/webhook | HMAC-SHA256 | Telegram Bot API updates |
ยน Slack signing_secret is resolved per-org from integration_credentials (BLK-004 / #1219); the SLACK_SIGNING_SECRET env var is a dev-only fallback and disallowed in production.
Channel Adminโ
Source: channels/channel-admin.controller.ts. Prefix /orgs/:orgId/channels.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /orgs/:orgId/channels/status | OrgAdmin | Health status for all channels |
| GET | /orgs/:orgId/channels/webhook-urls | OrgAdmin | Webhook URLs to paste into dashboards |
| GET | /orgs/:orgId/channels/slack/manifest | OrgAdmin | Slack app manifest suggester (#1034) |
Channel Mediaโ
Source: channels/channel-media.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /messages/:id/attachments/:idx | Staff | Stream message attachment (signed) |
WhatsApp ยท per-orgโ
Source: channels/whatsapp/whatsapp-org.controller.ts. Prefix /orgs/:orgId/whatsapp/whitelist.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /orgs/:orgId/whatsapp/whitelist | OrgAdmin | List whitelist numbers |
| POST | /orgs/:orgId/whatsapp/whitelist | OrgAdmin | Add number to whitelist |
| DELETE | /orgs/:orgId/whatsapp/whitelist/:id | OrgAdmin | Remove from whitelist |
WhatsApp ยท pairing (user-side)โ
Source: channels/whatsapp/whatsapp-pairing.controller.ts. Prefix /whatsapp.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /whatsapp/pairing-code | JWT | Generate pairing code |
| GET | /whatsapp/linked-numbers | JWT | List linked numbers for current user |
| DELETE | /whatsapp/linked-numbers/:id | JWT | Unlink a number |
Integration Credentialsโ
Source: integrations/credentials/credentials.controller.ts. Two controllers in one file.
Per-org generic credentials (/orgs/:orgId/integrations)โ
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /orgs/:orgId/integrations | OrgAdmin | Create/upsert channel credentials |
| GET | /orgs/:orgId/integrations | OrgAdmin | List integrations (values masked) |
| DELETE | /orgs/:orgId/integrations/:id | OrgAdmin | Delete integration |
| POST | /orgs/:orgId/integrations/:id/test | OrgAdmin | Test connection |
Nango (/v1/integrations)โ
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /v1/integrations/nango/session | OrgAdmin | Create Nango connect session |
| POST | /v1/integrations/credentials/nango/confirm | OrgAdmin | Confirm Nango credentials |
Billingโ
Sources: billing/interface/client-billing.controller.ts, billing/interface/ops-billing.controller.ts, billing/interface/billing-webhook.controller.ts.
Status (2026-06-04): Lago is the active billing rail โ self-hosted Lago (Railway for dev; AWS for staging + prod โ AWS bring-up tracked in #1287). Legacy Stripe/RequestFinance plan-tier endpoints (
/billing/subscriptions,/billing/checkout-session,/billing/webhooks/stripe,/billing/webhooks/request-finance) were removed in #1016 (Phase 7, 2026-05-28). The Lago provider adapter shipped in #1069; dual-strategy pricing (plan_per_ratedefault for free-tier Lago,plan_overridesfor premium) shipped in #1105; client + ops surfaces via #1155 (#1165 was closed-unmerged and superseded by #1155); #1217 renamed the launch-checklist row from "Orb" โ "Lago". See docs/superpowers/specs/2026-05-26-billing-provider-leveraged-design.md.
Client billing (/client/billing)โ
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /client/billing/summary | OrgMember | Current subscription summary for the org |
| GET | /client/billing/portal-url | OrgAdmin | One-shot Lago portal URL for self-service |
Ops billing (/ops/billing)โ
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /ops/billing | SA/AM | List all orgs + subscription state |
| POST | /ops/billing/sync-customer/:orgId | SA | Reconcile Lago customer for an org |
| GET | /ops/billing/customer/:orgId | SA/AM | Lago customer detail for an org |
| POST | /ops/billing/subscriptions/:assignmentId/retry-sync | SA | Retry Lago subscription sync for a stuck OSA |
Lago webhooksโ
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /billing/webhooks/lago | Lago signature | Lago webhook intake |
LlmCostRollupService (#1151) rolls up messages.cost_cents pivoted on osa_id into the per-OSA billing record.
Agentic Tasksโ
Source: agentic/agentic.controller.ts. Prefix /agentic.
Status (2026-05-25): The HTTP surface below is unchanged, but execution has been superseded by the RIG runtime control plane (#696). The legacy Python
/v1/tasks*runtime was removed; backing for/agentic/tasks/*now flows through the RIG run authority (runs, events, approvals/input, tool/model/sandbox/artifact gateways). See docs/architecture/RIG_HARD_CUT_RUNTIME_PORT_PLAN.md.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /agentic/tasks | JWT | Create agentic task with step plan |
| GET | /agentic/tasks | JWT | List tasks by org |
| GET | /agentic/tasks/:id | JWT | Get task + full plan |
| POST | /agentic/tasks/:id/steps/:stepId/approve | JWT | Approve a step |
| POST | /agentic/tasks/:id/steps/:stepId/reject | JWT | Reject step with feedback |
Agents (per-org)โ
Source: agents/agents.controller.ts. Prefix /orgs/:orgId/agents.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /orgs/:orgId/agents | JWT | List org agents (filter: role) |
| POST | /orgs/:orgId/agents | JWT | Create agent for org |
| DELETE | /orgs/:orgId/agents/:id | JWT | Remove agent |
Toolsโ
Source: tools/tools.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
/tools/execute | โ | Removed 2026-05-25 (#696 โ RIG hard-cut). Returns HTTP 410. Tool execution flows through the runtime tool gateway / POST /v1/agent-api/tools/:toolName (Agent surface). | |
| GET | /orgs/:orgId/tool-permissions | JWT | List enabled tools |
| PUT | /orgs/:orgId/tool-permissions/:toolName | JWT | Enable/disable tool with optional config |
Analyticsโ
Source: analytics/analytics.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /analytics/summary | Staff | Aggregate analytics (superadmin: all orgs; org: scoped) |
Audit Logโ
Sources: audit/audit-log.controller.ts, organizations/organizations.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /audit-log | JWT | Paginated audit log (filter: from, to, entity_type, limit, cursor) |
| GET | /orgs/:orgId/audit | AM/SA | Per-org audit (see Organizations section) |
Learningโ
Source: learning/learning.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /expert-queue/:id/corrections | Expert | Submit correction (alias used by Expert UI) |
| POST | /corrections | None* | Agent service submits correction (* gated by agent-service auth header) |
| GET | /learning/corrections | Staff | List corrections (filter: role) |
| GET | /learning/corrections/stats | Staff | Aggregated correction stats by type |
| GET | /learning/corrections/export | SA | Export corrections CSV |
| GET | /learning/corrections/stats/by-org | SA | Stats grouped by org |
Usersโ
Source: users/users.controller.ts. Prefix /users.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /users/me | JWT | Current user profile |
| PATCH | /users/me | JWT | Update own profile |
| POST | /users/:id/hp-verify | JWT | Humanity Protocol credential verification (stub) |
Uploadโ
Source: upload/upload.controller.ts. Prefix /upload.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /upload | JWT | Upload file to R2 |
| GET | /upload/signed-url/*key | JWT | Get signed URL for file |
Knowledge Baseโ
Sources: kb/kb-documents.controller.ts (prefix /kb), kb/kb-retrieval.controller.ts (prefix /kb, Agent-only), kb/kb.controller.ts (prefix /api/kb). The /api/kb/* surface is the pre-#817 controller; document CRUD has migrated to /kb/*, but #1526 extended /api/kb/* with a new search endpoint used by the Expert workspace KB panel, so /api/kb/* is not wholesale retired.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /kb | JWT | Register a document (metadata) |
| GET | /kb | JWT | List KB documents for the org |
| GET | /kb/:id | JWT | Get document detail |
| POST | /kb/upload | JWT | Upload document file (multipart) โ #817 |
| GET | /kb/:id/access-url | JWT | Signed access URL for a stored document โ #823 |
| GET | /kb/retrieval | Agent | Vector retrieval for Agent runtime โ #819 |
| GET | /api/kb/search | JWT | KB search for Expert workspace KB panel โ #1526 |
Internal-only audit logging (used by Agent + runtime):
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /audit/log | Agent | Append agent-driven audit entry |
Notificationsโ
Source: notifications/notifications.controller.ts (#915). Prefix /notifications. Pipeline overview: features/notifications.md.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /notifications | JWT | Create an AppNotification (internal/system callers โ see note) |
| GET | /notifications?limit=&offset= | JWT | List the caller's notifications, newest first (limit default 50, clamped 1โ200; offset default 0) |
| PATCH | /notifications/:id/read | JWT | Mark notification as read (ownership-checked; idempotent) |
POSTbody (CreateNotificationDto):userId(uuid, recipient),type(string),message(string),title?,meta?(object). CurrentlyJwtAuthGuard-only; aPlatformRolesGuardtier is a tracked #170 follow-up, so treatPOSTas internal-caller-only.GETresolves the recipient from the JWT (never a query param); a request whose token has no user id 401s rather than returning an unfiltered list (#915).markReadreturns 403 if the notification belongs to another user, 404 if it doesn't exist. There is no unread-count endpoint โ the badge is derived client-side fromreadAt === null.- Response/Socket.io payload shape (
NotificationDto, identical on both surfaces):{ id, userId, type, message, title, meta, readAt, createdAt }.
Socket.io (/notifications namespace)โ
Real-time delivery runs alongside REST (#915). Namespace /notifications; JWT supplied via the Socket.io auth object, ?token=, or Authorization: Bearer. On connect the socket joins user:<userId> (always), org:<orgId> (non-client roles), and experts (expert/superadmin); conversation:<id> is joined on demand via the join_conversation event (ACL-checked, paired with leave_conversation). Redis-backed adapter fans events across pods when REDIS_URL is set.
| Event | Direction | Room | Notes |
|---|---|---|---|
notification:new | server โ client | user:<userId> | In-app AppNotification delivery (payload = NotificationDto) |
expert_queue_item_added | server โ client | experts | Queue surface |
queue_item_resolved | server โ client | experts, conversation:<id> | Queue surface |
queue_item_status_updated | server โ client | experts | Queue surface โ generic status change (defer/awaiting_client/โฆ) |
queue_item_updated | server โ client | experts (+ conversation:<id> conversation_status_changed) | Queue surface โ non-terminal transition (pending/awaiting_client/snoozed), row stays visible (#388) |
conversation_status_changed | server โ client | conversation:<id> | Conversation surface |
agent_message_sent | server โ client | org:<id>, conversation:<id>, experts | Conversation surface |
user_message_received | server โ client | org:<id>, conversation:<id>, experts | Conversation surface |
workspace_message_added | server โ client | experts | Conversation surface โ Expert-workspace internal note |
join_conversation / leave_conversation | client โ server | โ | Subscribe/unsubscribe a conversation:<id> room |
Schedulerโ
Source: scheduler/scheduler.controller.ts. Prefix /scheduler. All routes require superadmin.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /scheduler/jobs | SA | List scheduled jobs |
| POST | /scheduler/jobs/:jobName/trigger | SA | Trigger job immediately |
| DELETE | /scheduler/jobs/:jobKey | SA | Delete scheduled job |
| GET | /scheduler/health | SA | Scheduler health |
Marketing (public)โ
Source: marketing/marketing.controller.ts. Prefix /marketing. All routes are public.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /marketing/companies/lead | None | Submit company lead |
| POST | /marketing/experts/application | None | Submit expert application |
| GET | /marketing/specialists | None | List public Specialists |
| GET | /marketing/specialists/:slug | None | Public Specialist profile |
Public Widget (embeddable chat)โ
Source: public/widget-session.controller.ts. Prefix /public/widget. Unauthenticated entry point that mints a short-lived visitor JWT for the embeddable chat widget (@humanwork/chat-widget). See features/embeddable-chat-widget.md and integrations/embed.md.
| Method | Path | Auth | Description |
|---|---|---|---|
| OPTIONS | /public/widget/session | None | CORS preflight (Access-Control-Allow-Origin: *), 204 |
| POST | /public/widget/session | None, 30/min | Mint a 24h visitor JWT for { orgSlug, visitorId? } โ { token, expiresAt, visitorId } |
orgSlugis required; an unknown slug returns 404.visitorIdis optional โ when omitted (or not a UUID it can normalize) the server generates one; a malformedvisitorIdreturns 400.- The minted token carries
role: "client"/platformRole: "client",widgetVisitorId, and a single-orgorgMembershipsentry. TTL = 24h (#2925). - After holding the token the widget reuses the standard Conversations API above as a
client-role caller (GET/POST /conversations,GET /conversations/:id,POST /conversations/:id/messages); responses are masked byClientConversationViewInterceptor(Expert identity stripped,role: "expert"โ"agent"). Realtime arrives over the/notificationsSocket.IO namespace (agent_message_sent,agent_typing).
Environment Profilesโ
Source: environment-profiles/environment-profiles.controller.ts. Prefix /environment-profiles.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /environment-profiles/:id | JWT | Get environment profile |
| GET | /environment-profiles/by-assignment/:assignmentId | JWT | Get profile by specialist-assignment id |
| PATCH | /environment-profiles/:id | JWT | Update profile (draft fields) |
| POST | /environment-profiles/:id/approve | JWT | Approve profile |
Meetings (Onboarding videos / Tavus)โ
Source: meetings/meetings.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /assignments/:assignmentId/onboarding/start | JWT | Start onboarding video session |
| POST | /assignments/:assignmentId/meetings | JWT | Create a meeting for assignment |
| GET | /assignments/:assignmentId/meetings | JWT | List meetings for assignment |
| POST | /assignments/:assignmentId/meetings/:meetingId/start | JWT | Start a specific meeting |
| GET | /meetings/:id | JWT | Get meeting detail |
Tavus Replicas + Webhooksโ
Source: tavus/tavus.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /tavus/replicas | Staff | List Tavus replicas |
| POST | /tavus/webhooks/function-call | Tavus signature | Tavus function-call webhook |
| POST | /tavus/webhooks/transcript-ready | Tavus signature | Tavus transcript-ready webhook |
Tavus Function-Call Definitions (admin)โ
Source: tavus/tavus-function-definitions.controller.ts. Prefix /ops/tavus/function-calls since #1031 (renamed from /ops/personas/function-calls; legacy controller tavus-function-definitions-legacy.controller.ts serves 308 redirects for ~30 days). One of the rare real /ops/* API surfaces.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /ops/tavus/function-calls | Staff | List function-call definitions |
| GET | /ops/tavus/function-calls/:id | Staff | Get definition |
| POST | /ops/tavus/function-calls | Staff | Create definition |
| PATCH | /ops/tavus/function-calls/:id | Staff | Update definition |
| POST | /ops/tavus/function-calls/:name/versions | Staff | Create new version of named definition |
| DELETE | /ops/tavus/function-calls/:id | Staff | Delete definition |
Agent API (Agent Service โ Control Plane)โ
These routes are called by the Python agent service and are guarded by AgentTokenGuard (HMAC of AGENT_API_SHARED_SECRET). Not for human/UI clients.
Source: agent-api/agent-api.controller.ts, agent-events/agent-events.controller.ts, agent-runtime/internal-runtime-config.controller.ts.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /v1/agent-api/conversations/:conversationId/messages | Agent | Fetch conversation history |
| GET | /v1/agent-api/context | Agent | Fetch org/specialist context |
| GET | /v1/agent-api/tools | Agent | List available tools for org/specialist |
| POST | /v1/agent-api/tools/:toolName | Agent | Execute a tool |
| POST | /v1/agent-api/token/refresh | Agent | Refresh agent service token |
| POST | /v1/agent-api/events | Agent | Stream agent execution events |
| GET | /v1/internal/org/:slug/runtime-config | Agent | Per-org agent runtime config |
Recently Removed / Audit Notesโ
The following endpoints have been documented in past versions of this reference but do not exist in the current controllers (verified 2026-05-25 against api/src/**/*.controller.ts).
| Path | Status |
|---|---|
GET /orgs/:orgId/quota | Removed โ quota is exposed via /admin/quota. |
POST /expert-queue/:id/reassign | Removed 2026-05-03 โ expert-pool model deleted; replaced by expert_access (ADR-007). |
GET /expert/pools, POST /pools, GET /expert/pools/:id/members | Removed 2026-05-03 โ expert-pool model deleted. |
org_experts table writes | Deprecated 2026-05-22 (ADR-007); reads still served via /am/orgs/:orgId/experts for back-compat through #540. |
POST /tools/execute | Removed 2026-05-25 (#696, RIG hard-cut). Returns HTTP 410. Use the runtime tool gateway / POST /v1/agent-api/tools/:toolName. |
POST /v1/tasks and /v1/tasks/* (Agent surface) | Removed 2026-05-25 (#696). Agent endpoints return HTTP 410 with LEGACY_TASK_AUTHORITY_REMOVED. The Platform /agentic/tasks/* surface remains but is now RIG-backed. |
POST /billing/subscriptions, GET /billing/subscriptions[/:orgId], DELETE /billing/subscriptions/:orgId, POST /billing/checkout-session, POST /billing/webhooks, POST /billing/webhooks/stripe, POST /billing/webhooks/request-finance | Removed 2026-05-28 (#1016, Phase 7). Legacy fixed-plan Stripe + RequestFinance rail killed; Lago is canonical (#1069/#1105/#1155 โ #1165 was closed-unmerged, superseded by #1155). See Billing section above. |
Methodologyโ
This file was audited end-to-end against the controller decorators on 2026-05-25 (closes #247). The procedure was:
- Enumerate every
*.controller.tsunderapi/src/. - For each file, extract
@Controller(...)prefix and every@Get/@Post/@Put/@Patch/@Deletedecorator together with@PlatformRoles/@OrgRoles/@UseGuards. - Cross-check the resulting
(method, fully-qualified path, auth)triples against this document, in both directions. - Drop fictional entries, correct wrong methods/paths, add missing real endpoints, and note removed routes above.
@MessagePattern queue handlers and Socket.io gateway events are intentionally excluded โ this file documents HTTP only.
Last updated: 2026-06-01 โ Pass-2 docs audit sweep: KB/Notifications/Lago sections refreshed; /tools/execute + Stripe legacy + /v1/tasks* moved to Recently Removed; Slack source path updated for #1212; Slack signing_secret per-org footnote (#1219); SuperAdmin Expert fast-path and waitlist promote/decline endpoints added; Slack manifest endpoint added. Underlying full controller audit: 2026-05-25 (#247). If you add, rename, or remove a controller route, update this file in the same PR.