Live Chat

Bring website and in-app conversations into one shared inbox. Server integrations mint visitor sessions with an API token so mobile and browser clients never hold the secret.

Generally availableOpenAPIMarkdown

Overview

Live Chat (`product_id: conversations_suite`) is the only Connect product with a generally available public REST API. Use a product-scoped API token so your server or agent can mint hosted chat sessions, read and write conversations, list visitors, and manage outbound webhooks—without embedding secrets in mobile or browser clients.

ItemValue
product_idconversations_suite
Suite token (in keys)live
StatusGenerally available
Base URL (production)https://umneyconnect.com/api
Base URL (staging)https://www.staging.umneyconnect.com/api
OpenAPI/developers/openapi-live-chat.json
Markdown (AI)/developers/live-chat.md
Same idea as a Cloudflare API token for an agent: enable the product, mint a least-privilege token, store it on the server, call only Live Chat resources.

Get started

  1. In Dashboard → Billing, enable Live Chat & Inbox (conversations_suite).
  2. In Dashboard → Developers, create an API token for product Live Chat. Environment: live (production traffic) or test. Scopes: at least chat:write to mint sessions; add chat:read, visitors:read, webhooks:manage as needed. Optional: expiry and IP allowlist.
  3. Copy the plaintext secret once. Store as UMNEY_CONNECT_API_KEY (or equivalent) on your server / Nest / agent runtime.
  4. Call https://umneyconnect.com/api/v1/chat/... with Authorization: Bearer <token> or X-API-Key: <token>.
  5. Return chatUrl (from POST /v1/chat/sessions) to end-user apps—never the API token.

Minimal session mint

curl -X POST "https://umneyconnect.com/api/v1/chat/sessions" \
  -H "Authorization: Bearer $UMNEY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "externalId": "TAXI:trip_123:user:usr_456",
    "displayName": "Maya Chen",
    "source": "umney-safety",
    "attributes": { "scopeType": "TAXI", "scopeId": "trip_123" }
  }'

Authentication & key formats

Live Chat live keys use the legacy form umk_live_<8>_<secret>. Test keys use umk_test_live_<8>_<secret>. Send either header style below. Responses include X-Request-ID.

Authorization: Bearer umk_live_<prefix>_<secret>
# or
X-API-Key: umk_live_<prefix>_<secret>
ScopeRequired for
chat:writePOST /v1/chat/sessions, create conversation, send message
chat:readList conversations and messages
visitors:readGET /v1/chat/visitors
webhooks:manageCRUD /tenants/{tenantId}/webhooks
403 usually means missing Billing entitlement, wrong product token, missing scope, IP allowlist miss, or expired key. Rotate from Dashboard → Developers without changing path contracts.

Concepts

ResourceMeaning
VisitorEnd user. Prefer stable externalId (e.g. Nest user or trip:user key) so repeats reopen the same person.
SessionServer-minted hosted chat link: chatUrl + visitorToken + conversationId.
ConversationInbox channel (status: open | pending | resolved | closed). Source often api, widget, or channel name.
MessageVisitor or agent/API content inside a conversation.
WidgetTenant siteKey (umw_…) used by /widget/chat. Auto-created on first session mint if missing.
Webhook subscriptionHTTPS endpoint receiving signed chat events.

Do not confuse Live Chat tables (chat_channels, chat_visitors, …) with Growth Suite “conversations” CRUD under /api/growth/conversations—they share billing product_id but are different APIs.

POST /v1/chat/sessions

Mint a hosted visitor chat URL for Nest Safety, CRM deep links, or any server integration. Requires chat:write. Upserts visitor by externalId, reuses an open/pending channel when present, otherwise opens a new conversation and may auto-assign an agent.

FieldRequiredNotes
externalIdyesStable id ≤200 chars
displayNamenoShown to agents
emailnoVisitor email
namenoConversation title; defaults from displayName/email/externalId
sourcenoDefaults to api
attributesnoJSON object merged into visitor attributes

200 response shape

{
  "conversationId": "8bb7f3b8-7e0f-4a86-bd84-b39d669f06c1",
  "chatUrl": "https://umneyconnect.com/widget/chat?siteKey=umw_…&token=…",
  "externalId": "TAXI:trip_123:user:usr_456",
  "visitorToken": "…",
  "expiresAt": "2026-09-14T21:00:00.000Z",
  "siteKey": "umw_…"
}

Conversations

List and create inbox conversations. List supports cursor pagination on last_message_at.

MethodPathScopeQuery / body
GET/v1/chat/conversationschat:readlimit (1–100, default 50), cursor, status, source
POST/v1/chat/conversationschat:writename (required), priority, optional visitor{externalId,displayName,email,attributes}
curl "https://umneyconnect.com/api/v1/chat/conversations?limit=50&status=open" \
  -H "Authorization: Bearer $UMNEY_API_KEY"

curl -X POST "https://umneyconnect.com/api/v1/chat/conversations" \
  -H "Authorization: Bearer $UMNEY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Website visitor", "source": "api", "priority": "normal" }'

List response: { data: Conversation[], meta: { limit, nextCursor } }. Conversation fields include id, name, source, status, priority, assignedUserId, visitorId, unreadCount, lastMessageAt, createdAt, updatedAt.

Messages

MethodPathScopeNotes
GET/v1/chat/conversations/{id}/messageschat:readlimit, optional after cursor
POST/v1/chat/conversations/{id}/messageschat:writebody { content } — sent as API/integration message
curl "https://umneyconnect.com/api/v1/chat/conversations/{id}/messages" \
  -H "Authorization: Bearer $UMNEY_API_KEY"

curl -X POST "https://umneyconnect.com/api/v1/chat/conversations/{id}/messages" \
  -H "Authorization: Bearer $UMNEY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "content": "Hello from Nest" }'

Visitors

GET /v1/chat/visitors requires visitors:read. Pass limit (1–100) to list, or externalId for an exact lookup. Prefer minting sessions with a stable externalId so the same person is reused across trips.

curl "https://umneyconnect.com/api/v1/chat/visitors?limit=50" \
  -H "Authorization: Bearer $UMNEY_API_KEY"

curl "https://umneyconnect.com/api/v1/chat/visitors?externalId=TAXI:trip_123:user:usr_456" \
  -H "Authorization: Bearer $UMNEY_API_KEY"

Response: { data: Visitor[] } (plus meta.limit when listing). Fields: id, display_name, email, phone, external_id, attributes, created_at, last_seen_at.

Outbound webhooks

Manage subscriptions from Dashboard → Developers or with scope webhooks:manage. Secret is returned once on create. Deliveries drain on cron and opportunistically after chat events.

MethodPathAuth
GET/tenants/{tenantId}/webhookswebhooks:manage or tenant admin JWT
POST/tenants/{tenantId}/webhookswebhooks:manage or tenant admin JWT
PATCH/tenants/{tenantId}/webhooks/{id}webhooks:manage or tenant admin JWT
DELETE/tenants/{tenantId}/webhooks/{id}webhooks:manage or tenant admin JWT
GET/tenants/{tenantId}/webhooks/{id}/deliverieswebhooks:manage or tenant admin JWT
POST/tenants/{tenantId}/webhooks/{id}/testwebhooks:manage or tenant admin JWT
EventEmitted today?
message.createdYes — widget, agent, omnichannel
conversation.createdYes — widget, support, omnichannel
conversation.closedYes — support/close flows
conversation.assignedYes — assignment flows
csat.submittedYes — CSAT submit
visitor.createdAllowlisted only — not emitted yet

Delivery JSON body: { event, eventId, payload, timestamp }. Signed with X-Umney-Signature (HMAC-SHA256 hex of `${unixTimestamp}.${rawBody}`) and X-Umney-Timestamp. Drain runs on prod every 15m / staging every 6h, plus opportunistic drain after emitWebhookEvent.

const crypto = require('node:crypto');

function verify(rawBody, signatureHeader, timestampHeader, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${timestampHeader}.${rawBody}`, 'utf8')
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signatureHeader, 'utf8'),
    Buffer.from(expected, 'utf8'),
  );
}

Errors and rate limits

Per-route IP limits apply, plus 600 requests/minute per API key on /api/v1/*. HTTP 429 includes Retry-After, X-Request-ID, and X-RateLimit-Limit / Remaining / Reset. Session mint may record chat_session_mint usage when billing_usage_events exists.

{
  "statusCode": 403,
  "error": "Forbidden",
  "message": "API key lacks required scope: chat:write",
  "requestId": "…"
}

API tokens for agents (Cloudflare-style)

Same ease-of-use model as Cloudflare: create an API token so an agent (Nest Safety, Agent Lee–style automation, CI) can access only Live Chat resources—not the whole workspace. Enable the product, mint a least-privilege token, store it server-side, call /v1/chat/*, return chatUrl to humans.

ENABLE_UMNEY_CONNECT=Yes
ENABLE_UMNEY_CONNECT_LIVE_CHAT=Yes
UMNEY_CONNECT_API_BASE_URL=https://umneyconnect.com/api
UMNEY_CONNECT_API_KEY=umk_live_…   # conversations_suite + chat:write

# Agent workflow
# 1. Read /llms.txt → open /developers/live-chat.md
# 2. Confirm entitlement + token scopes
# 3. POST /v1/chat/sessions with stable externalId
# 4. Return chatUrl only — never the API token

Dashboard APIs (JWT — not public tokens)

Richer inbox ops use tenant JWT (browser), not umk_* keys: /api/tenants/{tenantId}/chat/* and /api/public/chat/* for the widget. Prefer public /v1/chat/* for Nest and third parties.

  • Agent UI: /dashboard/chat, /dashboard/chat/reports
  • Keys & webhooks UI: /dashboard/developers
  • Hosted visitor UI: /widget/chat
  • Omnichannel (WhatsApp/Meta/Telegram) feeds the same inbox and can emit outbound webhook events

OpenAPI & AI index

  • OpenAPI 3: /developers/openapi-live-chat.json
  • Markdown for RAG/agents: /developers/live-chat.md
  • Global index: /llms.txt · /developers/catalog.json
  • Token guide: /developers/api-tokens