Skip to main content
When the Corti Assistant is embedded in a host application, all network traffic from the embedded app may be routed through a proxy controlled by the host application. The proxy sits between the client and the Corti backend services.
Host application
  └── Embedded Corti Assistant
       ├── HTTP requests  → Proxy → Corti web app
       └── WebSocket       → Proxy → Corti WebSocket backend
The Corti web app already proxies all third-party service traffic (analytics, feature flags) server-side through its own API routes. This means the proxy only needs to handle two types of traffic:
  1. HTTP requests to the Corti web app
  2. WebSocket connections to the Corti real-time backend

Upstream URLs

The proxy forwards traffic to two upstream services. The exact URLs depend on your region:
RegionCorti web appWebSocket backend
EUhttps://assistant.eu.corti.appwss://api.eu.corti.app
EU MDhttps://assistantmd.eu.corti.appwss://api.eu.corti.app
UShttps://assistant.us.corti.appwss://api.us.corti.app
Use the URLs that match the region your Corti tenant is provisioned in. Contact support if you are unsure which region applies.

HTTP Request Forwarding

All HTTP requests from the embedded app are forwarded to a single upstream — the Corti web app.
Client → https://proxy.example.com/* → https://assistant.eu.corti.app/*
No path rewriting is needed. The proxy passes through the full request path, query string, method, and body unchanged.

Required Headers

The proxy must set the following headers on every forwarded request so the upstream can identify the original client:
HeaderValueExample
X-Forwarded-ForThe original client IP. If already present, append the client IP to the chain.192.168.1.100
X-Forwarded-HostThe Host header as seen by the proxy (the proxy’s own hostname).proxy.example.com
X-Forwarded-ProtoThe protocol used between the client and the proxy.https
Example — forwarding a request:
# Original request from client
GET https://proxy.example.com/api/interactions HTTP/1.1
Host: proxy.example.com

# Forwarded to upstream
GET https://assistant.eu.corti.app/api/interactions HTTP/1.1
Host: assistant.eu.corti.app
X-Forwarded-For: 192.168.1.100
X-Forwarded-Host: proxy.example.com
X-Forwarded-Proto: https

Response Handling

The proxy returns the upstream response to the client as-is. No modification of status codes, headers, or body is required.

WebSocket Forwarding

The Corti Assistant uses WebSocket connections for real-time audio streaming and clinical sessions. The proxy must handle the HTTP Upgrade: websocket handshake and bidirectionally forward all WebSocket frames.

Routing

All WebSocket connections use the /audio-bridge/ path prefix and are forwarded to the Corti WebSocket backend:
wss://proxy.example.com/audio-bridge/* → wss://<websocket-backend>/audio-bridge/*
The path and query string are preserved when forwarding. For example:
wss://proxy.example.com/audio-bridge/v1/transcribe?token=Bearer%20abc123
  → wss://api.eu.corti.app/audio-bridge/v1/transcribe?token=Bearer%20abc123

Connection Lifecycle

  1. Upgrade — When the proxy receives a request with Upgrade: websocket, it establishes a WebSocket connection to the appropriate upstream based on the path.
  2. Message forwarding — All messages (text and binary) are forwarded bidirectionally between the client and upstream. Messages sent by the client before the upstream connection is established should be buffered and flushed once the upstream is ready.
  3. Close — When either side closes the connection, the proxy closes the other side.
  4. Idle timeout — WebSocket connections can be long-lived. Set the idle timeout high enough to avoid dropping active audio sessions (recommended: at least 4 minutes).

Client-Side Configuration

For the embedded app to route its WebSocket connections through the proxy instead of connecting directly to the backend, the host application must set websocketBaseUrl using the configure action. The host application sends the configure action with the network.websocketBaseUrl property. For implementation details, see the PostMessage API or Window API documentation.
// Using the PostMessage API
postMessage({
  type: "CORTI_EMBEDDED",
  version: "v1",
  action: "configure",
  requestId: "unique-id",
  payload: {
    network: {
      websocketBaseUrl: "wss://proxy.example.com",
    },
  },
});

// Using the Window API
await window.CortiEmbedded.v1.configure({
  network: {
    websocketBaseUrl: "wss://proxy.example.com",
  },
});
When websocketBaseUrl is set, the app rewrites the origin of all WebSocket URLs to use the proxy:
Original:  wss://api.eu.corti.app/audio-bridge/v1/transcribe?token=xyz
Rewritten: wss://proxy.example.com/audio-bridge/v1/transcribe?token=xyz
The path and query string are preserved — only the origin changes. This is what enables the proxy to route connections based on path.
The configure action should be called before the user starts an interaction. It can be called at any time after the embedded app has loaded and the ready event has been received. The configuration persists for the duration of the session.

NGINX Example

A complete NGINX configuration for proxying the embedded Corti Assistant. Replace the upstream URLs with the values for your region.
This example listens on port 80 for simplicity. For production, add TLS termination (listen 443 ssl) and certificate paths.
resolver 1.1.1.1 8.8.8.8 valid=30s;

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;

    # Large auth tokens / cookies can exceed the default 8k request header limit
    large_client_header_buffers 4 32k;

    # Replace with the upstream URLs for your region
    set $corti_web assistant.eu.corti.app;
    set $corti_ws  api.eu.corti.app;

    # ── WebSocket: /audio-bridge/* → Corti WebSocket backend ──

    location /audio-bridge/ {
        proxy_pass https://$corti_ws;
        proxy_ssl_server_name on;
        proxy_set_header Host $corti_ws;

        # WebSocket upgrade
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        # Forwarding headers
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Long-lived connections — at least 4 minutes
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }

    # ── Everything else → Corti web app ──

    location / {
        proxy_pass https://$corti_web;
        proxy_ssl_server_name on;
        proxy_set_header Host $corti_web;

        # Large auth tokens require bigger buffers than the default 4k
        proxy_buffer_size 16k;
        proxy_buffers 4 16k;

        # Forwarding headers
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Implementation Checklist

  • Forward all HTTP requests to the Corti web app upstream URL
  • Set X-Forwarded-For, X-Forwarded-Host, and X-Forwarded-Proto headers
  • Handle WebSocket Upgrade requests
  • Route /audio-bridge/* WebSocket connections to the Corti WebSocket backend
  • Buffer client WebSocket messages until the upstream connection is established
  • Send the configure action from the host application with network.websocketBaseUrl set to the proxy URL