Skip to content

Embed Widget API Reference

REST API Endpoints

Create Embed Token

Create a new embed token for your widget.

POST /embed/create

Authentication: Required (Bearer token)

Request Body:

FieldTypeRequiredDescription
agentIdstringAt least oneText chat agent ID
voiceAgentIdstringAt least oneVoice/bidi agent ID
allowedDomainsstring[]NoDomain allowlist (default: ["localhost"])
modestringNo"text", "voice", or "both" (auto-detected from agents)
greetingstringNoGreeting message
colorstringNoBrand color hex (default: "#6366f1")
positionstringNo"bottom-right" or "bottom-left"
agentNamestringNoDisplay name in widget header
titlestringNoHeader title (overrides agentName display)
subtitlestringNoSecondary text under the title (e.g., "Powered by AI")
logoUrlstringNoURL of circular avatar image in header
initialPromptstringNoAuto-sent to agent on first load — agent's reply becomes the opening message
placeholderstringNoInput box placeholder text (default: "Ask me anything...")
sizestringNoWidget size: "compact" (340×480), "standard" (400×580), "large" (440×640)
rateLimitPerDaynumberNoMax requests per day (default: 1000)
rateLimitPerIpnumberNoMax requests per IP (default: 10)
minutesLimitnumberNoVoice minutes limit (null = unlimited)
creditLimitnumberNoCredit usage limit (null = unlimited)

TIP

You must provide at least one of agentId or voiceAgentId. Providing both enables the dual-mode widget with text/voice toggle tabs.

Response:

json
{
  "data": {
    "embedTokenId": "emb-a1b2c3d4-...",
    "embedToken": "emb_pk_live_...",
    "agentId": "text-agent-uuid",
    "voiceAgentId": "voice-agent-uuid",
    "allowedDomains": ["yourdomain.com", "localhost"],
    "config": {
      "greeting": "Hi! How can I help?",
      "color": "#6366f1",
      "position": "bottom-right",
      "mode": "both",
      "agentName": "AI Assistant"
    },
    "snippet": "<script src=\"https://cdn.universalapi.co/embed/widget.js\"\n  data-text-agent=\"text-agent-uuid\"\n  data-voice-agent=\"voice-agent-uuid\"\n  data-token=\"emb_pk_live_...\"\n  async></script>",
    "status": "active"
  }
}

Get Widget Config

Fetch widget configuration for a given embed token. This is a public endpoint — no user auth required. Validates the token and Origin header.

GET /embed/config?token=emb_pk_live_...

Response:

json
{
  "data": {
    "agentId": "text-agent-uuid",
    "voiceAgentId": "voice-agent-uuid",
    "agentName": "AI Assistant",
    "greeting": "Hi! How can I help?",
    "color": "#6366f1",
    "position": "bottom-right",
    "mode": "both"
  }
}

List Embed Tokens

List all embed tokens for the authenticated user.

GET /embed/list

Authentication: Required

Response:

json
{
  "data": {
    "tokens": [
      {
        "embedTokenId": "emb-a1b2c3d4-...",
        "tokenPrefix": "emb_pk_live_",
        "agentId": "text-agent-uuid",
        "voiceAgentId": "voice-agent-uuid",
        "allowedDomains": ["yourdomain.com"],
        "config": { ... },
        "minutesUsed": 12.5,
        "minutesLimit": null,
        "status": "active",
        "createdAt": 1714000000
      }
    ],
    "count": 1
  }
}

Update Embed Token

Update settings for an existing embed token.

PUT /embed/{embedTokenId}

Authentication: Required

Request Body (all fields optional):

FieldTypeDescription
allowedDomainsstring[]New domain allowlist
rateLimitPerDaynumberNew daily rate limit
rateLimitPerIpnumberNew per-IP rate limit
configobjectUpdated widget config (greeting, color, mode, etc.)
statusstring"active" or "revoked"

Delete (Revoke) Embed Token

Soft-delete an embed token. The widget stops working immediately.

DELETE /embed/{embedTokenId}

Authentication: Required


Embed Chat (Streaming Credentials)

Get streaming credentials for text chat. The widget calls this internally.

POST /embed/chat

Request Body:

json
{
  "token": "emb_pk_live_..."
}

Response:

json
{
  "data": {
    "agentId": "text-agent-uuid",
    "bearerToken": "uapi_ut_...",
    "streamUrl": "https://stream.api.universalapi.co/agent/{agentId}/chat"
  }
}

The widget uses these credentials to stream directly from the agent API.


Script Tag Attributes

AttributeTypeRequiredDescription
data-text-agentstringAt least oneText chat agent ID
data-voice-agentstringAt least oneVoice/bidi agent ID
data-tokenstringYesEmbed token (emb_pk_live_...)
data-modestringNoOverride mode: "text", "voice", "both"
data-positionstringNo"bottom-right" (default) or "bottom-left"
data-colorstringNoBrand color hex
data-greetingstringNoGreeting text (shown as static first bubble in text mode)
data-titlestringNoHeader title (overrides agent name)
data-subtitlestringNoSecondary text under the title
data-logostringNoURL of circular avatar image in header
data-initial-promptstringNoAuto-sent to agent on load — response is opening message
data-placeholderstringNoInput box placeholder text
data-sizestringNo"compact", "standard" (default), "large"
data-default-tabstringNoWhich tab to show first in "both" mode: "text" (default) or "voice"

JavaScript API (window.UniversalAPIWidget)

Methods

MethodArgumentsDescription
open()Open the widget panel
close()Close the widget panel
switchTo(tab)"text" or "voice"Switch active tab (only in "both" mode)
on(event, callback)event name, functionRegister event listener
getMode()Returns "text", "voice", or "both"
getActiveTab()Returns "text" or "voice"
isReady()Returns true after widget has initialized

Properties

PropertyTypeDescription
versionstringWidget version (e.g., "3.0.0")

Events

EventDataDescription
readyWidget has loaded and is ready
openPanel was opened
closePanel was closed
voiceStartVoice WebSocket connected, mic active
voiceEndVoice session ended
transcript{ text, role, is_final }Voice transcript received

Universal API - The agentic entry point to the universe of APIs