Universal API Integration
Universal API Integration lets Diverge call your HTTP endpoints during a conversation — for example to look up order status, delivery times, or account details — and use the response in the assistant's reply.
This guide covers how the feature works, how to configure it in the dashboard, and the authentication patterns your API can use.
What this is (and what it is not)
| Direction | Feature | Auth | Guide |
|---|---|---|---|
| Diverge calls your API | Universal API Integration | Bearer, Basic, OAuth 1.0a, pre-request OAuth2, browser tokens | This guide |
| You receive events from Diverge | Outbound livechat webhooks | HMAC signature (x-di-signature) | Chatbot API Flow — webhooks |
| Attach context to a chat session | Session metadata (setMetadata) | Untrusted browser input; optional signed JWT | Chatbot Integration — metadata |
Universal API Integration is configured in the Diverge dashboard. It is not available through the public Chatbot API for self-service setup, and it is not yet exposed on the customer-facing MCP surface. Contact your Diverge representative if you need help configuring an integration.
Flow at a glance
- A visitor asks a question that needs live data from your systems (for example "Where is my order?").
- The chatbot widget sends the message to Diverge, optionally including runtime variables read from the visitor's browser (cookie, localStorage, and so on).
- Diverge's planner selects the right integration and collects any required fields (order number, email, and so on) from the conversation.
- Diverge's servers call your HTTP endpoint with the configured authentication.
- Your API returns data (typically JSON). Diverge uses it to compose the reply.
Request path: Visitor → chatbot widget → Diverge planner → your API → reply to visitor.
The widget may attach runtime variables read from the browser (cookie, localStorage, etc.)
when it sends each message.
Limits
| Limit | Value |
|---|---|
| Timeout per external HTTP request | 15 seconds |
| Total time for pre-request chain plus main request | 40 seconds |
| Maximum pre-request steps per integration | 5 |
Access tokens obtained in a pre-request step are fetched fresh on each invoke — there is no long-lived token cache shared across conversations. Token response bodies are not injected into the LLM context; only a compact per-step status log (label, HTTP status, ok) is recorded.
Before you start
You need:
- Access to the Diverge dashboard for the chatbot.
- One or more HTTP endpoints that return data your bot can use (JSON is typical). HTTPS is strongly recommended for production; HTTP may work but is not advised.
- An authentication method chosen from the sections below.
- A clear list of required fields the bot must collect before calling your API (for example
order_number,email). - For per-user auth: a stable place in the visitor's browser to read a session token (cookie,
localStorage, orsessionStorage).
Calls to your API originate from Diverge's servers, not from the visitor's browser. CORS on your endpoint does not apply to Universal API requests.
Configure in the dashboard
Enable the feature
Universal API Integration is disabled until you turn it on:
- Open the Diverge dashboard and edit the chatbot.
- Go to Extra Settings.
- Find Universal API Integration and turn on Enable Universal API Integration.
- Save Extra Settings.
Until this is enabled, the Universal API Integration and Universal API Planner tabs do not appear. After you enable the feature and save, those tabs show up in the chatbot editor. If the feature is turned off while you are already on that tab, the dashboard prompts you to go to Extra Settings first.
Create an integration
- Open the Universal API Integration tab.
- Create a new integration (or edit an existing one).
- Set the integration key and routing description.
- Configure Authentication (see Authentication).
- Configure the main request (method, URL, headers, body templates).
- Optionally add pre-request steps, runtime variables, required fields, and response shaping.
- Save.
| Area | Purpose |
|---|---|
| Integration key | Stable identifier the planner uses to invoke this integration |
| Routing description | Plain-language hint so the planner knows when to use this integration |
| Authentication | Server-stored credentials (see below) |
| Request config | HTTP method, URL, headers, query parameters, and body templates |
| Response config | Optional JSON path and transform that reshape the response before the planner uses it |
| Pre-request steps | Optional chained requests before the main call (for example OAuth2 token fetch) |
| Runtime variables | Values read from the visitor's browser before each message |
| Required fields | Fields the planner must collect from the conversation before invoking |
Security: Secrets stored in the Authentication credential panel (bearer tokens, passwords, OAuth 1.0a secrets, and so on) stay on Diverge's servers and are never sent to the visitor's browser.
Runtime variable configuration is different: the public widget config includes the variable definitions — keys, storage sources, and static values. Do not put API keys or other secrets in a static runtime variable. Prefer the Authentication panel for shared secrets.
Routing description is also included in the public widget runtime config when the integration exposes runtime variables. Treat it as customer-visible hint text, not a place for secrets or internal-only notes.
How the planner uses integrations
When a message may need live data, Diverge runs a Universal API planner. The planner returns one of these actions:
| Action | What happens |
|---|---|
invoke | Call the chosen integration with collected variables (for example order number, email) |
clarify | Ask the visitor for missing information before calling your API |
finish | Stop looking up data and continue with what is already known |
Required fields (configured per integration) must be present before an invoke runs. Values
bound from pre-request steps are supplied by the chain and are not treated as fields the planner
must collect from the visitor.
Routing descriptions and the planner catalog help the model choose among multiple enabled integrations.
Authentication
Diverge supports four common patterns when calling your endpoints. Pick the one that matches how your API gateway or platform expects credentials.
Integration-level vs per-step auth
There are two places auth can come from:
| Level | Where you configure it | Applies to |
|---|---|---|
| Integration Authentication panel | Credential panel on the integration | Every pre-request step and the main request (unless overridden) |
| Request-config Auth / Token Placement | Inline on a pre-request step (Auth / Token Placement UI) | That pre-request step only |
An explicit Authorization header (including one you add on the main request under
Headers) or enabled Auth / Token Placement on a pre-request step wins for that call —
credential-panel injection is skipped for that request. There is no separate Authentication panel
per pre-request step.
On the main request editor, Auth / Token Placement is not shown. Use the integration Authentication panel, or add headers, query parameters, and body fields directly on the main request.
1. Static API key or token
The simplest case: a shared secret attached to every request.
Option A — Credential panel (recommended for secrets)
In the dashboard Authentication panel, choose a type and enter the secret once. Diverge
automatically adds an Authorization header on every request (including pre-request steps unless
overridden):
| Auth type | Header sent |
|---|---|
| Bearer token | Authorization: Bearer <token> |
| Raw Authorization header value | Authorization: <value exactly as entered> — use for custom schemes such as ApiKey abc123 |
| Basic (username + password) | Authorization: Basic <base64(username:password)> |
This is usually enough for delivery-info or order-lookup endpoints protected by a static token.
Option B — Custom header, query parameter, or body field
When your API expects the secret somewhere other than a standard Authorization scheme from the
credential panel:
On the main request (Auth / Token Placement is not available here), add rows under Headers, Query Params, or body fields:
| Placement | Example |
|---|---|
| Authorization header | Header Authorization, value Bearer {{token}} |
| Custom header | Header name X-API-Key, value your key |
| Query parameter | Query name api_key, value your key |
| Body field | Field name token, value your key |
On a pre-request step, you can instead enable Auth / Token Placement on that step's request config for the same placements (Authorization header, custom header, query, or body).
Value templates support {{variableName}} substitution (see Template variables).
- Authentication type: Bearer token
- Enter the token in the dashboard (stored server-side).
- Request URL:
https://api.example.com/orders/{{order_number}}
Diverge sends Authorization: Bearer <your-token> automatically; no auth block needed on the
request config.
- Authentication type: No auth (credential panel).
- On the main request Headers list, add:
- Key:
X-API-Key - Value: your key (entered in the request editor on the server, not as a static runtime variable)
- Key:
2. OAuth2 client_credentials
If your API sits behind an OAuth token server, configure a pre-request step that fetches an access token before the main data request. There is no separate "OAuth2" auth type — the chain handles token exchange automatically on each invoke.
Setup:- Set Authentication (integration credential panel) to No auth so credential headers do not conflict with the token step on every call.
- Add a pre-request step:
- Method:
POST - URL: your token endpoint (for example
https://auth.example.com/oauth/token) - Body (JSON): include
grant_type: client_credentialsand any client id/secret your server requires (often as form fields or Basic auth on the token endpoint itself).
- Method:
- Add an output binding: map response field
access_token→ variableaccess_token. - On the main request, add header:
Authorization: Bearer {{access_token}}
{
"label": "Get access token",
"requestConfig": {
"method": "POST",
"url": "https://auth.example.com/oauth/token",
"bodyMode": "json",
"bodyTemplate": {
"grant_type": "client_credentials",
"client_id": "your-client-id",
"client_secret": "your-client-secret"
}
},
"outputBindings": [{ "variable": "access_token", "jsonPath": "access_token" }]
}Client secrets placed in pre-request JSON are stored server-side but remain visible in the dashboard to anyone who can edit the chatbot. Prefer Auth / Token Placement (or a header row) on the token pre-request step when the provider supports Basic auth on the token endpoint — do not set Basic on the integration Authentication panel just for the token step, because that panel applies to every request in the chain unless overridden.
Example main request headers:[{ "key": "Authorization", "value": "Bearer {{access_token}}" }]If the token endpoint itself requires Basic auth, add it on that pre-request step's request
config (Auth / Token Placement or a header row) — not a separate Authentication panel for the step.
An explicit header on that step wins over integration-level credential injection for that call only.
Keep the integration Authentication panel on No auth when the main request uses
Authorization: Bearer {{access_token}}.
Token refresh is automatic per invoke: each time the planner calls the integration, the chain runs from the beginning and obtains a fresh token.
3. OAuth 1.0a signed requests
For gateways that require OAuth 1.0a request signing (HMAC-SHA1 or HMAC-SHA256), use the OAuth 1.0a auth type in the credential panel:
| Field | Maps to |
|---|---|
| Consumer Key | OAuth consumer key |
| Consumer Secret | OAuth consumer secret |
| Access Token | OAuth access token |
| Token Secret | OAuth token secret |
| Signature method | HMAC-SHA1 or HMAC-SHA256 |
Diverge signs each request and sets a signed Authorization header. Magento 2.4.4 and later
typically require HMAC-SHA256; older integrations may use HMAC-SHA1.
Configure the main request URL and method as usual — signing is applied automatically.
4. Per-user session token (browser)
When the data is user-specific and your API should authorize the request as if the logged-in visitor called it themselves, configure Runtime variables to read a token from the browser.
Data path: Browser storage (cookie / localStorage / sessionStorage) → chatbot script on
your site → chatbot iframe → Diverge servers → your API (for example as
Authorization: Bearer {{customer_token}} or another header you configure).
Supported sources:
| Source | Use when |
|---|---|
| Cookie | Session token stored in a named cookie |
| localStorage | Token or JSON profile in localStorage |
| sessionStorage | Token scoped to the browser tab session |
| Static | Same value for every visitor (not for secrets — values are public to the widget) |
For JSON stored in cookie or storage, set an optional JSON path (for example customer.id) to
extract a nested field.
| Variable key | Source | Key / path |
|---|---|---|
customer_id | localStorage | Key profile, JSON path customer.id |
customer_token | cookie | Key session_token |
locale | static | Value da-DK |
Use {{customer_token}} (or your chosen key) in the request URL, headers, query parameters, body
fields, or (on a pre-request step) Auth / Token Placement.
The widget reads these values on each message and sends them to Diverge. Values the planner extracts from the current user message override browser runtime values for the same key.
Template variables
Request configs support {{variableName}} placeholders in:
- URL
- Headers
- Query parameters
- JSON or form body fields
- Auth value templates (pre-request Auth / Token Placement)
Rules:
- Variable names may contain letters, numbers,
_,., or-. - Missing variables become an empty string.
- Planner-collected fields (for example
order_number) and pre-request output bindings (for exampleaccess_token) are ordinary template variables once bound.
Pre-request chaining
Pre-request steps run in order before the main request. Each step is a full HTTP request config. After a step succeeds, output bindings copy fields from the JSON response into the shared variable map using a JSON path, so later steps and the main request can reference them.
Use chaining when:
- You need OAuth2
client_credentials(see above). - A lookup depends on an earlier call (for example token → account id → order list).
- Get access token —
POSTtoken URL → bindaccess_token - Resolve account —
GETaccount endpoint withAuthorization: Bearer {{access_token}}→ bindaccount_id - Main request —
GEThttps://api.example.com/accounts/{{account_id}}/orders/{{order_number}}with the same bearer header
Additional rules:
- Up to 5 pre-request steps per integration.
- Total wall-clock time for all steps plus the main request is capped at 40 seconds (each external request made by Universal API also times out after 15 seconds).
- If a step or the main request already sets an
Authorizationheader, that explicit header is used for that call; set credential auth to No auth when the chain provides tokens. - Variables produced by output bindings are not listed as planner "required fields" — the chain supplies them after the planner's field check.
Response shaping
On the main request, you can optionally configure:
| Option | Purpose |
|---|---|
| Response path | JSON path into the response body (for example data or orders.0) |
| Response transform | Short JavaScript that receives response, variables, and context and returns the value the planner should see |
Use transforms when your API returns a large or nested payload and you only want a compact shape passed into the conversation context. Leave them empty when the raw JSON is already suitable.
What your endpoint should implement
As the API owner, make sure your endpoint:
- Accepts the auth method you configured in Diverge.
- Returns structured data (JSON is typical) with stable field names. Non-JSON success responses are accepted as plain text, but JSON path selection and most planner usage work best with JSON.
- Handles read-style lookups idempotently where possible.
- Responds within the timeout limits above.
You do not need to allow browser CORS for these calls — they are server-to-server from Diverge.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Universal API tabs missing in the dashboard | Feature not enabled under Extra Settings → Enable Universal API Integration |
| Your API returns 401 | Wrong auth type; token in wrong header, query, or body; OAuth 1.0a signature method mismatch (try HMAC-SHA256) |
| Your API returns another non-2xx status | Diverge treats non-success HTTP statuses as a failed request and stops that invoke |
| Response is not JSON | Success responses without application/json are kept as plain text; JSON path / output bindings that expect objects will not work as expected — prefer JSON |
| Pre-request step fails | Token or lookup URL wrong; auth missing on that step's request config; non-2xx from the step endpoint |
{{variable}} is empty in the outgoing request | Runtime variable missing in browser storage; typo in cookie/storage key or JSON path |
| Token step succeeds but main request fails | Main request missing Authorization: Bearer {{access_token}} header |
| Unexpected double auth | Credential panel auth plus explicit Authorization on the same call — use No auth when the chain or request config supplies the header |
| Chain times out / chain budget exceeded | Too many slow steps; reduce steps or optimize your API; maximum 40 seconds total for all pre-steps plus the main request |
Related reading
- Chatbot Integration — opening the widget, session metadata, and signed metadata (session context — not Universal API auth)
- Chatbot API Flow — visitor auth, streaming messages, and outbound livechat webhooks