Developers

Public REST API (/v1/public/*) + outbound webhooks. Lihat docs di /api-docs.

Live Chat Widget

Add a floating chat button to any website in under a minute. Bundle size is under 30KB gzipped, loads asynchronously, and never blocks your page render.

  1. Create a Live Chat channel at Channels → New → Live Chat Widget. Copy the channel ID from the resulting card.
  2. Paste the embed snippet below into the <head> or before </body>.
  3. Publish. The widget picks up your agent config, brand color, and locale.

Standard embed (any site)

Vanilla HTML tag. Works with WordPress, Shopify, Webflow.

<!-- Danum AI Live Chat Widget -->
<script
  async
  src="https://ai.numintek.com/widget/widget.js"
  data-channel-id="YOUR_CHANNEL_ID"
  data-primary-color="#6366F1"
  data-position="bottom-right"
  data-locale="en"
></script>
Available data-* attributes
  • data-channel-id - required. From your Live Chat channel.
  • data-primary-color - hex or rgb. Overrides channel default.
  • data-position - bottom-right | bottom-left | top-right | top-left.
  • data-locale - en | id. Defaults to browser lang, then en.
  • data-open - auto | closed. Default closed.
  • data-hide-launcher - true to hide floating button (control via JS API).

React / Next.js

Client-only mount to skip SSR flash.

import { useEffect } from 'react';

export function DanumWidget({ channelId }: { channelId: string }) {
  useEffect(() => {
    const s = document.createElement('script');
    s.async = true;
    s.src = 'https://ai.numintek.com/widget/widget.js';
    s.dataset.channelId = channelId;
    s.dataset.primaryColor = '#6366F1';
    s.dataset.position = 'bottom-right';
    document.body.appendChild(s);
    return () => { s.remove(); };
  }, [channelId]);
  return null;
}

Identify known users

Skip the anonymous handshake. Passing identify auto-links the conversation to a customer record.

// Programmatic identify - pass known-user context before the widget loads a session.
window.DanumWidget = window.DanumWidget || {};
window.DanumWidget.identify = {
  externalId: 'user_123',
  name: 'Budi Santoso',
  email: '[email protected]',
  phone: '+628123456789',
  metadata: { plan: 'PROFESSIONAL' },
};

Call this before the widget script loads, or after with window.DanumWidget.identify(...) . externalId must be your internal user ID; it is never displayed to agents.

JS API

Programmatic control after the widget loads.

window.DanumWidget.open();
window.DanumWidget.close();
window.DanumWidget.toggle();
window.DanumWidget.setLocale('id');
window.DanumWidget.on('conversation.started', (id) => { /* analytics */ });
window.DanumWidget.on('message.sent', (msg) => { /* track */ });
window.DanumWidget.reset(); // clears local session

Content Security Policy

If your site sends a CSP header, allow these origins.

Content-Security-Policy:
  script-src 'self' https://ai.numintek.com;
  connect-src 'self' https://ai.numintek.com wss://ai.numintek.com;
  frame-src https://ai.numintek.com;
  img-src 'self' data: https://ai.numintek.com;

Troubleshooting

Common gotchas and how to solve them.

Widget doesn't appear

  • Open DevTools → Network → look for danum-widget.js. Should be 200.
  • Check data-channel-id matches your channel exactly.
  • Confirm the channel is Active on the Channels page.

Widget loads but chat fails

  • WebSocket blocked - check CSP and any proxy rewriting Upgrade headers.
  • Tenant quota exhausted - see Usage page.
  • Agent published? Draft-only agents don't serve production traffic.

Styling clashes

  • Widget runs inside a Shadow DOM - your CSS won't leak in or out.
  • Custom fonts → contact support to whitelist your font URL.

Privacy & PDP compliance

  • Widget stores only a session ID in localStorage.
  • Full transcript lives in your tenant DB, encrypted at rest.
  • Use widget.reset() when a user signs out to clear the session.