Skip to content

Legacy approach. For new integrations, use the Widget SDK with Access Key Embed.

Server-Side Proxy

The most secure integration method. Your server fetches the widget HTML from Returning.AI, injects the JWT token server-side, and serves it to the browser. The API key never touches the client.

Integration method, not authentication method

Server-Side Proxy is one of three ways to integrate Returning.AI widgets (alongside the Widget SDK and Embed Script). It uses Token Authentication under the hood. If you haven't read about Token Auth yet, start there first.

Architecture

Every request flows through your backend. The browser never communicates directly with the Returning.AI API.

Browser  ->  Your Server  ->  Returning.AI API
                  |
           1. POST /widget/{id}/signin   (get JWT)
           2. GET /{widget-type}/{widgetId}  (get HTML)
           3. Inject token into HTML
                  |
Browser  <-  Modified HTML with embedded token

Security model

A clear separation between server-side secrets and browser-visible data.

Stays on your serverGoes to the browser
WIDGET_API_KEYJWT (short-lived, user-scoped)
WIDGET_COMMUNITY_IDWidget ID
Returning.AI API requestsRendered widget HTML (with token embedded)

When to use

  • Maximum security requirements - API key never leaves the server.
  • Full control over the widget lifecycle (caching, error pages, fallbacks).
  • Domain whitelisting is insufficient for your security model.

Getting started

Five steps from zero to a working server-side proxy.

1Store credentials server-side

Keep your API key and community ID in environment variables. They must never be included in client-side code or HTML responses.

.env
WIDGET_BASE_URL=https://prod-widgets.returning.ai
WIDGET_API_KEY=your-api-key
WIDGET_COMMUNITY_ID=your-community-id
WIDGET_ID=your-widget-id
WIDGET_TYPE=store

2Accept user email from an authenticated request

The email must come from your verified session or auth middleware - never from a query parameter or request body that the client controls directly.

3Fetch a JWT from Returning.AI

POST the user's email along with your API key to the signin endpoint.

POST /widget/{communityId}/signin
Headers:
  Content-Type: application/json
  returningai-api-key: YOUR_API_KEY
  email: user@example.com

Response:
  { "token": "eyJhbGciOiJIUzI1NiIs..." }

4Fetch widget HTML

GET the widget page. The HTML comes with an empty token placeholder in the __WIDGET_INIT__ config.

GET /{widget-type}/{widgetId}?color=light

Response:
  <!DOCTYPE html>
  <html>
    <head>...</head>
    <body>
      <script>
        window.__WIDGET_INIT__ = { token: "", ... };
      </script>
      ...
    </body>
  </html>

5Inject token into HTML and serve

Replace the empty token placeholder with the JWT, then send the modified HTML to the browser.

// Replace the empty token placeholder with the real JWT
html = html.replace(/token:\s*""/, `token: "${safeToken}"`);

How this differs from Widget SDK and Embed Script

Unlike the Widget SDK or Embed Script methods, the server-side proxy gives you complete control over the authentication flow but requires more backend work. The tradeoff is maximum security for additional implementation effort.

Guides