Skip to main content

External API

Integrate WizChat chatbots into your applications using our REST API.

Overview​

The External API allows you to:

  • Send messages to your chatbot
  • Retrieve responses programmatically
  • Integrate chatbot functionality into your apps
  • Build custom interfaces

Getting API Keys​

  1. Go to "Settings" > "API"
  2. Click "Generate API Key"
  3. Copy and securely store the key
  4. Note: Keys are shown only once

Authentication​

Every request is authenticated with your chatbot's API key in the x-api-key header:

curl -H "x-api-key: YOUR_API_KEY" \
https://your-chatbot-domain/api/external/chat

An Authorization: Bearer YOUR_API_KEY header is also accepted.

Base URL​

The External API is served from your chatbot's own domain as a single endpoint:

https://your-chatbot-domain/api/external/chat

Use your chatbot's deployment URL (shown under Settings > API) in place of your-chatbot-domain.

Sending a Message​

Request​

POST https://your-chatbot-domain/api/external/chat
Content-Type: application/json
x-api-key: YOUR_API_KEY

{
"question": "What is your return policy?",
"sessionId": "optional-session-id"
}

Request Body Parameters​

FieldTypeRequiredDescription
questionstringYesThe message to send to the chatbot
sessionIdstringNoSession id for conversation continuity — reuse it to keep a caller's turns linked. Omit it and one is generated and returned.
historyarrayNoPrior turns to seed context, if you manage conversation history yourself
imagesarrayNoImages for multimodal queries (max 5) — each { "url": "https://…" } or { "base64": "…", "mimeType": "image/png" }
scopestringNoKnowledge scope ID to query a specific namespace (Business/Enterprise only)

Response​

{
"success": true,
"answer": "Our return policy allows returns within 30 days of purchase...",
"sessionId": "sess_abc123",
"sources": [
{
"documentId": "doc_xyz",
"title": "Return Policy",
"relevance": 0.95
}
],
"metadata": {
"model": "gpt-4o",
"responseTimeMs": 1234
}
}

Conversation Management​

Continue a Conversation​

Reuse the sessionId returned by the previous response:

{
"question": "What if the item is damaged?",
"sessionId": "sess_abc123"
}

Start New Conversation​

Omit sessionId — a fresh one is generated and returned:

{
"question": "Hello!"
}

On-behalf-of (OBO): act for your own users​

By default, every External API request is authenticated only by your chatbot's API key, so all traffic shares a single anonymous identity. On-behalf-of (OBO) lets your own backend tell WizChat which of your end users a request is for, by attaching a short-lived signed token that identifies that user. Each verified end-user identity then gets its own isolated conversation history, conversation memory, and in-chat uploads — one user can never read or write another user's conversation, even by reusing a conversation id.

Advanced, server-to-server pattern

Most integrations don't need OBO — use your API key, or end-user sign-in for interactive chatbots. Reach for OBO when your application already authenticates its users and you want WizChat to keep per-user context without those users signing in to WizChat separately.

How it works​

  1. Your backend authenticates your user (however you already do).
  2. Your backend mints a short-lived JSON Web Token (JWT) identifying that user and signs it with your private key.
  3. Your backend calls the External API with the token in the X-Wizchat-OBO header, alongside your API key.
  4. WizChat verifies the token's signature against the public key you registered and scopes the request to that user.

WizChat only ever holds your public key — it never sees your signing key or your users' credentials.

Step 1 — Register your token issuer​

  1. Open your chatbot in the WizChat dashboard.
  2. Go to the API tab and make sure the External API is enabled.
  3. Under On-behalf-of (OBO) issuers, click Add issuer and fill in:
FieldDescription
LabelOptional name to recognize this issuer (e.g. Production backend).
IssuerThe value your backend puts in the token's iss claim (e.g. https://auth.example.com).
AlgorithmThe signing algorithm: RS256 (RSA, ≥ 2048-bit) or ES256 (EC P-256).
Key sourceEither a JWKS URL — an HTTPS endpoint serving your public keys, e.g. https://auth.example.com/.well-known/jwks.json — or a public key (PEM) you paste directly.
  1. Click Add issuer.

You can register up to 10 issuers per chatbot. Toggle an issuer to Disabled (or delete it) to revoke it — tokens from that issuer stop working within about a minute. OBO stays completely off until at least one active issuer is registered.

JWKS URL vs. pasted key

Use a JWKS URL if you rotate signing keys — WizChat refetches your key set automatically, including on key rotation. Paste a public key (PEM) if you have a single static key.

Step 2 — Mint a token per request​

For each API call, mint a JWT signed with your private key and these claims:

ClaimRequiredDescription
issYesMust match the Issuer you registered.
subYesA stable, unique id for the end user in your system. This is what WizChat uses to keep that user's context separate.
audYesMust be your chatbot's ID.
expYesExpiry (Unix seconds), in the future.
iatYesIssued-at (Unix seconds).
nbfNoNot-before (Unix seconds), if you use it.

Tokens must be short-lived: the span between iat and exp may be at most 10 minutes. Mint a fresh token per request (or per short burst) rather than reusing a long-lived one.

import jwt from 'jsonwebtoken';

const token = jwt.sign(
{
iss: 'https://auth.example.com', // must match the registered issuer
sub: user.id, // your stable id for this end user
aud: 'YOUR_CHATBOT_ID',
},
privateKeyPem, // your RS256 or ES256 private key
{ algorithm: 'RS256', expiresIn: '5m' } // iat + exp set for you; keep ≤ 10m
);

Step 3 — Call the API with the header​

Send the signed token in the X-Wizchat-OBO header. Pass a stable sessionId for each end user's conversation so their turns stay linked and their private history and memory persist across requests. sessionId is optional — omit it and the API generates one and returns it in the response — but reuse the same value on that user's later turns to keep their context.

curl -X POST https://your-chatbot-domain/api/external/chat \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Wizchat-OBO: YOUR_SIGNED_JWT" \
-H "Content-Type: application/json" \
-d '{"question": "What did we discuss last time?", "sessionId": "user-42-thread-1"}'

Per-user isolation​

Once a request carries a verified OBO token:

  • The end user identified by the token gets their own conversation history and conversation memory, separate from every other user and from anonymous API-key traffic.
  • Files that user uploads into a conversation are visible only on that user's turns.
  • A user can't reach another user's conversation by reusing a conversation id — isolation is enforced on the server.
  • For streaming or agentic chatbots, the same token lets a user resume their own in-progress run and approve their own tool-approval prompts; a user can only act on runs they started.

Without an OBO token, plain API-key traffic shares a single anonymous context: cross-session memory and stored history are disabled for those requests (a caller-supplied email can't be trusted), so answers are ephemeral. Registering an issuer and sending OBO tokens is what gives each of your users durable, private per-user context over the API.

OBO errors​

HTTP StatusWhen
401The token is missing a required claim, is expired, exceeds the 10-minute lifetime, or fails signature verification.
403A user tries to resume a run or approve a tool call that belongs to a different user.
503WizChat temporarily can't load the issuer configuration to verify the token — retry.

Security notes​

  • WizChat stores only your public key; your signing key never leaves your systems.
  • Keep tokens short-lived (≤ 10 minutes) and mint one per request.
  • Disabling or removing an issuer revokes its tokens within about a minute.

Knowledge Scopes​

Business & Enterprise Only

Knowledge scopes are available on Business and Enterprise plans.

If your chatbot has Knowledge Scopes configured, you can target a specific scope by passing the scope parameter. Each scope queries its own dedicated namespace with optional behavior overrides (system prompt, persona, response length).

Discovering Available Scopes​

Send a GET request to see which scopes are available:

GET /api/external/chat

The response includes an availableScopes array when scopes are configured:

{
"name": "External Chat API",
"version": "1.2.0",
"enabled": true,
"availableScopes": [
{ "id": "product-a", "label": "Product A" },
{ "id": "product-b", "label": "Product B" }
],
"documentation": { ... }
}

Querying a Scope​

Pass the scope ID in the request body:

{
"question": "What features does Product A have?",
"scope": "product-a"
}

The response metadata will include the scope that was used:

{
"success": true,
"answer": "Product A includes...",
"metadata": {
"model": "gpt-4o",
"responseTimeMs": 1234,
"scope": "product-a"
}
}

Scope Errors​

Error CodeHTTP StatusDescription
SCOPE_NOT_AVAILABLE403Scope requested but plan is not Business or Enterprise
INVALID_SCOPE400Scope ID does not exist on this chatbot

Code Examples​

JavaScript/Node.js​

const response = await fetch(
'https://your-chatbot-domain/api/external/chat',
{
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
question: 'What are your business hours?',
}),
}
);

const data = await response.json();
console.log(data.answer);

Python​

import requests

response = requests.post(
'https://your-chatbot-domain/api/external/chat',
headers={
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
json={
'question': 'What are your business hours?',
},
)

data = response.json()
print(data['answer'])

cURL​

curl -X POST https://your-chatbot-domain/api/external/chat \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"question": "What are your business hours?"}'

Rate Limits​

PlanRequests/MinuteRequests/Day
Starter301,000
Pro6010,000
Business120Unlimited

Rate Limit Headers​

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1640000000

Error Handling​

Error Response Format​

{
"success": false,
"error": "Too many requests. Please try again later.",
"errorCode": "RATE_LIMITED"
}

Common Error Codes​

HTTP StatuserrorCode (examples)Description
400MISSING_QUESTION, INVALID_JSON, TOO_MANY_IMAGESMissing or empty question, malformed JSON body, or more than 5 images
401—API key is missing or invalid
403—The External API is disabled for this chatbot
429RATE_LIMITEDRate limit exceeded
500—Internal server error

Knowledge-scope and OBO requests can return additional codes — see Scope Errors and OBO errors above.

API Key Management​

Viewing Keys​

  1. Go to "Settings" > "API"
  2. See all active keys
  3. View usage statistics

Revoking Keys​

  1. Go to "Settings" > "API"
  2. Find the key
  3. Click "Revoke"
  4. Confirm revocation
warning

Revoked keys stop working immediately.

Best Practices​

  • Store API keys securely (environment variables)
  • Rotate keys periodically
  • Use separate keys for different environments
  • Implement proper error handling
  • Respect rate limits