Resources

Integrations

Connect chatbots to WhatsApp, REST API, web widget channels, and external MCP tool servers.

Overview

Integrations connect a chatbot to an external messaging channel or tool server. Supported types:

ChannelType valueDescription
WhatsAppwhatsappWhatsApp Business API via Meta
REST APIrest-apiGeneric REST webhook for custom integrations
Web WidgetwebEmbeddable chat widget for websites
MCP ServermcpRemote tool servers for LLM agents (Model Context Protocol)

List Integrations

Returns all integrations attached to a chatbot.

http
GET /api/dev/v1/chatbots/{chatbot_id}/integrations
Authorization: Bearer <api-key>
bash
curl -X GET https://developers.sarufi.io/api/dev/v1/chatbots/<chatbot-id>/integrations \
  -H "Authorization: Bearer <your-api-key>"

Response - 200 OK

json
{
  "items": [
    {
      "id": "01JST...",
      "chatbot_id": "01JMXYZ...",
      "type": "whatsapp",
      "is_active": true,
      "created_at": "2026-01-25T11:00:00Z"
    }
  ],
  "total": 1
}

Get Integration

http
GET /api/dev/v1/chatbots/{chatbot_id}/integrations/{integration_id}
Authorization: Bearer <api-key>
bash
curl -X GET https://developers.sarufi.io/api/dev/v1/chatbots/<chatbot-id>/integrations/<integration-id> \
  -H "Authorization: Bearer <your-api-key>"

Delete Integration

Permanently removes an integration. Users on this channel will no longer be able to reach the chatbot.

http
DELETE /api/dev/v1/chatbots/{chatbot_id}/integrations/{integration_id}
Authorization: Bearer <api-key>
bash
curl -X DELETE https://developers.sarufi.io/api/dev/v1/chatbots/<chatbot-id>/integrations/<integration-id> \
  -H "Authorization: Bearer <your-api-key>"

Response - 204 No Content


WhatsApp Integration

Create WhatsApp Integration

http
POST /api/dev/v1/chatbots/{chatbot_id}/integrations/whatsapp
Authorization: Bearer <api-key>
Content-Type: application/json

Body

phone_number_idstringrequired

Meta WhatsApp Business phone number ID.

access_tokenstringrequired

Permanent access token from Meta for Business.

verify_tokenstringrequired

Token you set when configuring the Meta webhook.

bash
curl -X POST https://developers.sarufi.io/api/dev/v1/chatbots/<chatbot-id>/integrations/whatsapp \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number_id": "1234567890",
    "access_token": "EAABwzLixnjYBO...",
    "verify_token": "my-webhook-verify-token"
  }'

Get WhatsApp Integration

http
GET /api/dev/v1/chatbots/{chatbot_id}/integrations/whatsapp
Authorization: Bearer <api-key>

Update WhatsApp Integration

http
PATCH /api/dev/v1/chatbots/{chatbot_id}/integrations/whatsapp
Authorization: Bearer <api-key>
Content-Type: application/json

REST API Integration

Use this integration to connect the chatbot to any custom channel via a webhook.

Create REST API Integration

http
POST /api/dev/v1/chatbots/{chatbot_id}/integrations/rest-api
Authorization: Bearer <api-key>
Content-Type: application/json

Body

webhook_urlstringrequired

The URL Sarufi will POST outbound messages to.

namestringoptional

Friendly name for this REST integration.

bash
curl -X POST https://developers.sarufi.io/api/dev/v1/chatbots/<chatbot-id>/integrations/rest-api \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook_url": "https://yourserver.com/chatbot-webhook",
    "name": "My REST Integration"
  }'

Get / Update REST API Integration

http
GET  /api/dev/v1/chatbots/{chatbot_id}/integrations/rest-api
PATCH /api/dev/v1/chatbots/{chatbot_id}/integrations/rest-api
Authorization: Bearer <api-key>

Web Widget Integration

Embed a real-time chat widget on any website. The widget loads asynchronously, connects over Socket.IO, and supports full conversation history, buttons, lists, and media messages.

Create Web Integration

http
POST /api/dev/v1/chatbots/{chatbot_id}/integrations/web
Authorization: Bearer <api-key>
Content-Type: application/json

Body

namestringrequired

A friendly name for this web integration.

allowed_domainsarrayoptional

List of domains allowed to load the widget (e.g. ["yoursite.com", "app.yoursite.com"]). Leave empty to allow all domains.

greeting_messagestringoptional

The first message shown when a visitor opens the widget.

widget_configobjectoptional

Appearance and behaviour overrides - see the Widget Config reference below.

widget_config fields

bot_display_namestringoptional

Name shown in the widget header and on bot messages. Defaults to "Assistant".

primary_colorstringoptional

Hex color for the bubble, header, and user messages. Defaults to "#0066ff".

secondary_colorstringoptional

Hex color for bot message bubbles. Defaults to "#f0f4ff".

background_colorstringoptional

Hex color for the chat message area background.

bubble_textstringoptional

Text shown on the floating bubble button. Defaults to "Need Help?".

bot_avatar_iconstringoptional

Icon key for the bot avatar. One of: "" (Sarufi default), "robot", "headset", "sparkle", "heart", "store", "graduation", "chat".

font_sizenumberoptional

Base font size in pixels (12–24). Defaults to 13.5.

positionstringoptional

Widget placement. One of "bottom-right" (default) or "bottom-left".

widthnumberoptional

Chat window width in pixels (280–600). Defaults to 380.

heightnumberoptional

Chat window height in pixels (400–800). Defaults to 600.

allowed_pathsarrayoptional

URL path patterns where the widget should appear. Supports exact paths ("/contact") and wildcard prefix matching ("/shop/*"). When null or empty the widget appears on every page.

bash
curl -X POST https://developers.sarufi.io/api/dev/v1/chatbots/<chatbot-id>/integrations/web \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Main Site Widget",
    "allowed_domains": ["yoursite.com"],
    "greeting_message": "Hi! How can I help you today?",
    "widget_config": {
      "bot_display_name": "Aria",
      "primary_color": "#0066ff",
      "bubble_text": "Need Help?",
      "position": "bottom-right",
      "allowed_paths": ["/contact", "/support/*"]
    }
  }'

Response - 201 Created

json
{
  "id": "01JUV...",
  "type": "web",
  "name": "Main Site Widget",
  "config": {
    "widget_key": "wk_AbCdEf...",
    "allowed_domains": ["yoursite.com"],
    "widget_config": {
      "bot_display_name": "Aria",
      "primary_color": "#0066ff",
      "position": "bottom-right",
      "allowed_paths": ["/contact", "/support/*"]
    }
  },
  "is_active": true
}

Get / Update Web Integration

http
GET   /api/dev/v1/chatbots/{chatbot_id}/integrations/web
PATCH /api/dev/v1/chatbots/{chatbot_id}/integrations/web
Authorization: Bearer <api-key>

Embedding the Widget

Once your web integration is created you get a widget_key (format: wk_...). Use it to embed the widget on your site with a single <script> tag.

Script Attributes Reference

AttributeRequiredDescription
srcyesWidget script URL - https://sarufi.io/widget.js
data-widget-keyyesYour wk_... key from the integration
data-server-urlnoOverride the backend origin (useful for self-hosted deployments)
asyncrecommendedLoads the script without blocking page rendering
html
<!DOCTYPE html>
<html lang="en">
  <body>
    <!-- your page content -->
    <script
      src="https://sarufi.io/widget.js"
      data-widget-key="wk_YOUR_WIDGET_KEY"
      async
    ></script>
  </body>
</html>

Next.js: lazyOnload strategy

lazyOnload loads the widget after all critical page resources finish. Use it in app/layout.tsx for site-wide embeds, or scope it to a nested layout for specific route groups only.

Angular SSR (Universal)

Wrap the script injection in an isPlatformBrowser(this.platformId) check to prevent it running during server-side rendering.

Shopify Online Store 2.0

On OS2.0 themes you can add a custom snippet under snippets/sarufi-widget.liquid and render it with {%- render 'sarufi-widget' -%} to keep theme.liquid tidy.


JavaScript API

The widget exposes window.SarufiWidget with methods you can call from your page's JavaScript. Both methods can be called before or after the widget script loads — they take effect immediately or queue until the widget connects.

Identify the visitor

Attach a visitor identity so the same person resumes their conversation across devices, sessions, and reconnects.

html
<script>
  // Call after your login logic — pass the user's email or phone number
  SarufiWidget.identify("alice@acme.com");
</script>

Rules:

  • Accepts an email or phone number
  • Phone numbers are normalized to E.164 server-side (0712..., +255712..., 255 712 ... all map to the same visitor)
  • Invalid or synthetic emails are rejected (connection refused) — only pass real addresses
  • Sanitized to [A-Za-z0-9@._-], max 100 characters
  • When the same user_id connects again, the backend resumes their latest conversation
  • Omit the call entirely for anonymous visitors — behavior is unchanged

Send contact details

Pass extra visitor metadata that agents see in the conversation context panel. Useful for surfacing account info, plan tier, or any business-specific context.

html
<script>
  SarufiWidget.setContactDetails({
    "Name": "Alice Mongi",
    "Email": "alice@acme.com",
    "Merchant account name": "Acme Ltd",
    "Plan": "Pro"
  });
</script>

Rules:

  • Plain { key: value } object — labels are up to you
  • Keys are normalized to snake_case server-side ("Merchant account name"merchant_account_name)
  • Values must be scalars (string, number, boolean) — nested objects are dropped
  • Max 13 fields, each value max 300 characters
  • Details are merged on each reconnect: new keys are added, existing keys are updated, old keys are retained
  • Stored once the visitor sends their first message

Full example

html
<script
  src="https://sarufi.io/widget.js"
  data-widget-key="wk_YOUR_WIDGET_KEY"
  async
></script>

<script>
  // After your app authenticates the user:
  SarufiWidget.identify("alice@acme.com");

  SarufiWidget.setContactDetails({
    "Name": "Alice Mongi",
    "Merchant account name": "Acme Ltd",
    "Plan": "Pro"
  });
</script>

Independent features

identify() and setContactDetails() are fully independent. You can use one without the other, or both together. Identity drives session continuity; contact details provide extra context visible to agents.


Path-Based Visibility

By default the widget appears on every page. Use allowed_paths inside widget_config to restrict it to specific pages.

How matching works

PatternMatches
"/contact"Exactly /contact
"/shop/*"/shop, /shop/, /shop/shoes, /shop/shoes/nike
"/docs/*"/docs, /docs/getting-started, /docs/api/auth

When a visitor navigates to a page not in allowed_paths:

  • The widget is hidden (display: none)
  • The Socket.IO connection is disconnected - no idle connections on restricted pages

When they navigate back to an allowed page:

  • The widget reappears
  • The socket reconnects automatically, resuming the conversation from session history

SPA route changes

The widget listens for both popstate (browser back/forward) and intercepts history.pushState / history.replaceState to handle client-side navigation in React, Vue, Angular, and Next.js apps - no extra configuration needed.

Example - show only on support pages

json
{
  "widget_config": {
    "allowed_paths": ["/support", "/support/*", "/contact", "/help/*"]
  }
}

Example - show on all pages except checkout

There is no "deny list" - define the pages where the widget should appear:

json
{
  "widget_config": {
    "allowed_paths": ["/", "/products/*", "/about", "/contact"]
  }
}

MCP Server Integration

MCP (Model Context Protocol) integrations give LLM agents access to tools hosted on external servers — order lookups, CRM queries, ticketing systems, internal APIs — without writing custom executor code.

Unlike channel integrations (WhatsApp, REST API, web widget), MCP integrations are many-per-chatbot: each chatbot can have multiple MCP servers registered simultaneously.

Knowledge Base or MCP?

Knowledge Base — ground answers in your own documents via RAG. Best for static content: FAQs, policies, product docs.

MCP Server — let agents call external tools and live APIs. Best for real-time actions: order lookups, CRM queries, booking systems.

You can attach both to the same chatbot. See the Knowledge Bases guide for KB setup.

For the full API reference — including all CRUD endpoints, auth types, connection testing, tool allowlists, and how to wire MCP tools into LLM_AGENT flow actions — see the dedicated guide:

MCP Server Integration →

Calling your own backend from a flow?

Use the API_CALL flow action to make outbound HTTP requests to your systems from within any conversation state. See the dedicated guide for full examples, variable substitution, response access, and backend setup.

API_CALL Action Guide →