Skip to content

AI Manager integration API

Status: Current | Last reviewed: 2026-10-12

The AI Manager integration API lets an external application list published agent pipelines and create a short-lived, dynamically customized WebRTC phone emulator. It is a server-to-server API: keep the tenant tsf_* token on your backend and send only the returned iframeUrl to browser code.

Quick reference

Human-controlled screens use the shared customer-components API. Trusted integrations link conversations with POST /api/conversations/{representativeId}/customer-components/link (agents:manage). Signed embed sessions use GET|POST /api/embed/conversations/{id}/customer-components; catalogue buttons reach it through the SDK and Surface's cookie-backed BFF. Patient share links use their existing capability and may respond only to the current screen.

Detail Value
Base URL https://ai-manager.vanguard.dev.trueserve.deloitte.com
Authentication Tenant-scoped Bearer tsf_* token
Live OpenAPI JSON /openapi.json
List scope agents:read
Emulator scope emulator:run
Accent runtime scope accent:runtime
Preview recording conversion scope agents:run

An existing agents:manage token implies both narrower scopes for backwards compatibility. New demo integrations should request only agents:read and emulator:run.

Director workspace routes

POST /api/director/scenes creates a Scene identity/project, duplicates with sourceAgentRef, or promotes a legacy recording with projectId (ManageAgents). Returns agentId, project id, and editor href.

Director's Studio routes use the signed-in user's active tenant. Read operations require RunAgents; writes and generation require ManageAgents. These internal workspace routes are separate from the external integration OpenAPI surface.

Route Operation
GET /api/director?agentRef=… Agent identity and saved demos
POST /api/director Create a demo with {agentRef, blank}
GET /api/director/{id} Saved {document, revision}
PUT /api/director/{id} Validate and save {document, revision}; stale revisions return 409
POST /api/director/{id}/audio Generate a stored take for {momentId, revision}
GET /api/director/{id}/assets/{assetId} Authorized WAV download
GET /api/director/catalogs Available native components; ?versionId=… resolves a pinned manifest
GET /api/director/{id}/exports Export history, state and progress
POST /api/director/{id}/exports Snapshot and begin an MP4 export from a Studio session; returns 202
GET /api/director/{id}/exports/{exportId} Download MP4; ?snapshot=1 reads the frozen document
DELETE /api/director/{id}/exports/{exportId} Cancel a queued/running export

The saved document includes callDirection (inbound or outbound, relative to the agent) and callOpeningDuration (0–30 seconds before the script begins). Omitted values default to inbound and zero for compatibility. These values are included in export snapshots and do not invalidate existing audio takes. personas optionally defines up to 12 additional speakers with {id, name, voice, showInActivity}. A moment with kind: "persona" references personaId; saves reject unknown speakers. Additional lines use the existing audio/export routes, and old documents default to no additional personas.

See Director for limits, persistence, assets and same-instance Chromium authorization.

Preview lifecycle activity

For Preview lifecycle activity, GET /api/preview/lifecycle?conversationId=… requires AIManager:RunAgents (agents:run for tokens) and existing phone conversation authorization. It returns { actions, truncated } from persisted Conversation Start/End workflow history, including step inputs/results. Reads are restricted to the active tenant and match canonical/transport IDs. An empty startup history returns 200. Invalid IDs return 400; denied sessions return 401/403/404; unavailable history returns 503. Responses are private and uncached. Limits are 100 linked execution/run rows and 1,000 node invocations. The Preview observer keeps polling after hangup so durable end-workflow results remain visible. See Thinking contracts.

Dynamic phone flow

  1. Your backend calls GET /api/v1/pipelines and presents the returned agents in its own UI. Only non-template agents with a published version are listed.
  2. After the user selects an agent, your backend calls POST /api/v1/emulator/sessions with the parent page origin and optional caller/session customization.
  3. Your backend sends iframeUrl to the browser.
  4. The browser passes it to <trueserve-phone> or a plain iframe.
const response = await fetch(
  'https://ai-manager.vanguard.dev.trueserve.deloitte.com/api/v1/emulator/sessions',
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.TRUESERVE_API_TOKEN}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      agentId: '3026',
      audienceOrigin: 'https://demo.example.com',
      direction: 'outbound',
      autoConnect: true,
      callerName: 'Demo Customer',
      sessionVariables: { customerName: 'Alex' },
      sttLanguage: 'en-US',
    }),
  },
);

const { iframeUrl } = await response.json();

For custom web apps, use the hosted phone element. It owns the iframe, responsive scaling, microphone delegation, origin checks, controls, and events:

<script src="https://ai-manager.vanguard.dev.trueserve.deloitte.com/embed/trueserve-phone.js"></script>
<trueserve-phone
  session-url="/api/trueserve/phone-session"
  session-request='{"agentId":"3026","callerName":"Demo Customer"}'
></trueserve-phone>

Your session-url endpoint calls the API shown above, strips the redundant embedToken, and returns { iframeUrl, expiresAt, sessionExpiresAt, emulator }. See Embed the demo phone for a backend route, dynamic JavaScript configuration, CSS, controls, and events.

The bootstrap URL is single-use. Mint a new session for every iframe load or reload. Caller and session-variable customization stays in short-lived server-side storage; the URL contains only an opaque id. Dynamic sessions are WebRTC-only and run published agents. SIP targets, arbitrary headers, and reusable presets remain administrator-managed emulator configuration.

The iframe coalesces React Strict Mode's duplicate development effect, and the exchange endpoint accepts an idempotent retry only from the browser holding the signed session cookie created from that exact bootstrap token. This does not make iframeUrl reusable across browsers or independent page loads.

For direction: "inbound", trigger the ringing UI after the element reports trueserve-ready:

phone.triggerIncomingCall({ caller_name: 'Alex Rivera', ani: '+15555550100' });

The element methods are startCall(), endCall(), and setMuted(boolean). It emits trueserve-call-started, trueserve-call-connected, trueserve-call-ended, trueserve-incoming-call, and trueserve-error. The plain iframe fallback keeps the dotted postMessage protocol documented in the phone embedding guide.

Accent normalization profile

GET/PUT /api/settings/accent-normalization reads or saves the non-secret tenant profile with configuration:manage. The JSON request is the profile itself; the response is {settings: profile}. Field bounds and defaults are generated from the same Zod schema as Studio's form.

GET /api/settings/accent-normalization/runtime requires an explicit accent:runtime tenant token and returns {tenantId, config, credentials}. Disabled profiles omit credentials. Browser sessions, personal tokens and configuration:manage alone are rejected. The tenant comes from the token, not a request parameter. This scope grants no general agent or settings access. The response is private, no-store; only the trusted SCV backend consumes it. Never forward it to the browser, log it, or use it in a URL.

The browser's separate call grant/ticket/WebSocket protocol is documented in the SCV runtime contract.

Preview recording downloads

Studio uses POST /api/preview/recordings/mp4 when a browser cannot record H.264/AAC MP4 directly. Send a raw video/webm or video/mp4 body, not multipart form data. A Studio session needs AIManager:RunAgents; an API token also needs agents:run. Success streams an attachment with Content-Type: video/mp4 and Cache-Control: private, no-store. Video uses H.264/yuv420p and audio uses AAC when present, with fast-start metadata for seeking.

Uploads are limited to 100 MiB. Conversion has two concurrent slots per process and a 180-second deadline within a 300-second request window. The per-user bucket allows five immediate requests and refills two per minute. Capacity/rate errors return 429 with Retry-After; oversized files return 413, invalid media 422, missing FFmpeg 503, and conversion timeout 504. Temporary input/output files are deleted after completion, failure, or cancellation. Studio retains the original browser blob so a failed download can be retried.

See preview capture and deployment requirements.

Studio phone event stream

The Studio BFF uses GET /api/phone/events/stream?conversationId=…&mode=follow to observe a conversation without activating it. Phone-session or authenticated tenant access is checked before forwarding to conversation-api. Resume an SSE stream with Last-Event-ID or the last_event_id query parameter; the header takes precedence and only Redis IDs (digits-digits) are forwarded. Disconnecting the request aborts its upstream stream. A new voice conversation can briefly return 404 before its server row exists; browser callers must recreate a closed EventSource with backoff rather than assuming it will retry that response.

Telephony Preview

Expanded Preview uses four tenant-scoped endpoints, each requiring AIManager:RunAgents or an API token with agents:run:

Request Response
GET /api/preview/telephony/integrations {integrations:[{id,name,provider,transport,defaultContactFlowId?}]}; no config or credentials
GET /api/preview/telephony/genesys-numbers?integrationId=… {numbers:[{number,routeId,routeName,flowNames}],truncated} from active routed IVRs
POST /api/preview/telephony/sip-target with {integrationId,destination,ani?} Normalized destination, outbound SIP headers, and a server-issued previewSessionId for Genesys; does not dial
GET /api/preview/telephony/conversation?sessionId=… {conversationId:string|null} from the Genesys SIP answer for that owned Preview session

Numbers require explicit + country codes. Inactive or inaccessible connections return 404; invalid inputs return 400. Genesys discovery failures return an actionable error while manual dialing remains available. Responses use Cache-Control: private, no-store. Discovery uses server-side credentials, blocks redirects, and caps work at 2,000 IVRs and 20 seconds.

Conversation correlation requires the same user and tenant that prepared the call. It returns null until the provider answers, 404 for unknown/expired or other-user/tenant sessions, and 503 when the internal correlation service is unavailable. The exact provider binding persists for six hours from preparation, including after hangup; it does not infer identity from ANI or call timing.

Connect reuses the authenticated /api/emulator/amazon-connect/contact-flows, …/webrtc-contact, and …/dtmf endpoints. See the telephony contract for ANI behavior, SIP versus browser entry, and transfer testing.

WebRTC start accepts optional preview: {smsDeliveryMode: "demo_notification" | "real_sms"}. Preview defaults to simulated delivery and real delivery requires an E.164 ANI. Its response adds previewSessionId for the correlation endpoint and notificationSessionId for the phone stream. The server owns the start token and contact binding. Correlation returns the persisted TrueServe ID, never the raw Connect ContactId.

For flows in the connection's administrator-owned preview_scv_routes, WebRTC start also requires ANI and checks the configured Salesforce destination before creating an AWS contact. DNIS may be omitted; an explicitly supplied DNIS must match the flow mapping. Invalid input/mapping returns 400, and an unavailable validation service returns 503. The public request shape is unchanged. The service-bearer-only /api/internal/preview/connect-routing endpoint reads the expiring routing binding and is not a browser API.

Live OpenAPI

The block below renders AI Manager's public /openapi.json. The generated copy is refreshed from the running service when the developer documentation builds.

See also