ProductConsole

APA docs

Your website’s own assistant, with the name you choose. One line on your site, or the chat API for apps, WhatsApp bots and call centres.

Quick start

  1. Sign in with your work email and add your website.
  2. Verify it, then create your assistant: her name, greeting, tone, colours and voice.
  3. She reads your site in minutes. Try her in the Test tab.
  4. Paste the widget on your site, or use the chat API.

Verify your website

APA only learns and answers on sites you have proven are yours. Add a TXT record cabana-site-verification=<token>, a meta tag <meta name="cabana-site-verification" content="<token>">, or a file /<token>.txt. We look again every day; if the site turns into something APA cannot be used with, she pauses until a person checks.

How she learns

She reads your sitemap and pages, following robots.txt, and keeps up: she re-reads your site every day, and when the widget notices a page has changed she re-reads that page from your server straight away. Pages that disappear are forgotten. What a visitor’s browser shows is never stored as knowledge, so no one can teach her false facts through the widget. You can add text and FAQs, and exclude pages, in the console or by API.

How she stays truthful

She answers only from your pages, your added knowledge and your custom actions. After she writes a reply, every price, number, phone number, email address and link in it is checked against those sources, and anything not found is removed. When the answer is not there she says so and offers to connect the visitor with your team. Typos, accents, Sheng and Pidgin are understood: questions are corrected against the words on your own site before searching.

The widget

Paste before </body> on every page. The key is publishable and only works on your verified site. The console’s Install tab gives you the exact line.

<script async src="https://cabana.africa/apa/w.js" data-key="apa_pk_live_…" data-bot="<assistant id>"></script>

It runs in its own shadow root, so your page’s styles cannot break it, and it reads the page the visitor is on so she knows what they are looking at.

JavaScript API

APA.open();                                  // open the chat
APA.close(); APA.toggle();
APA.ask('Do you have rooms this weekend?');  // open and ask
APA.setContext({ page: 'room', room: 'Deluxe Ocean View', price: 'KES 14,000' });
APA.on('lead', e => console.log(e));         // also: message, handoff, open, close

Context you set is used to understand the question; facts in her answer still have to come from your site.

Voice

Visitors can tap the microphone and talk, hands-free: she listens, answers aloud, and listens again until they stop. Speech is recognised by the visitor’s browser; her voice comes from our speech service, or the device’s own voice where that is unavailable. Pick her voice in Personality.

Page actions

She can move the visitor around your site: open a page, scroll to a section, highlight something, fill a form field for them to check, or press a button you allow. Actions only ever target your own site and are shown to the visitor as they happen. Turn each kind on or off in Actions.

Authentication

Base URL https://cabana.africa/api/apa/v1. From your server, send a secret key: Authorization: Bearer apa_sk_….

Chat

POST/chat
FieldMeaning
botThe assistant’s id (optional with one assistant)
messageWhat the person said, up to 2,000 characters
visitorYour ID for the person, so conversations are kept apart
conversation_idTo continue a conversation
client_idYour message ID; a retry with the same one returns the same reply
channele.g. whatsapp, app, call
tzThe person’s time zone, e.g. Africa/Nairobi
curl -X POST https://cabana.africa/api/apa/v1/chat \
  -H "Authorization: Bearer apa_sk_live_…" -H "Content-Type: application/json" \
  -d '{"message":"Bei ya safari ya Mara ni ngapi?","visitor":"wa-254700000000","channel":"whatsapp"}'
# → { "conversation_id": "…", "reply": "…", "sources": [ { "title", "url" } ], "actions": [], "handoff": false, "lang": "sw" }

Add knowledge

POST/knowledge
{ "bot": "…", "title": "Cancellation policy", "text": "Full refund up to 14 days before…",
  "faq": [ { "q": "Can I pay with M-Pesa?", "a": "Yes, Paybill 123456." } ] }

Send a url to replace an earlier entry with the same address.

Conversations

GET/conversations?bot=…&limit=50
GET/conversations/{id}

The messages, with the sources each answer used.

POST/conversations/{id}/delete

Deletes the conversation and its messages for good, for example when a visitor asks to be forgotten.

Custom actions

Let her ask your own systems: availability, prices, booking status. Add an action in the console with a name (like check_availability), a description of when to use it, an https address and its parameters as JSON Schema. When she needs it, we POST:

{ "tool": "check_availability", "arguments": { "date": "2026-12-24", "guests": 2 },
  "conversation_id": "…", "assistant": "…", "visitor": "…" }

signed with Cabana-Signature (see webhooks) under the action signing secret shown in the console. Answer within 8 seconds with JSON or text; she uses only what you return.

Webhooks

EventWhen
apa.leadA visitor left their name and a way to reach them
apa.handoffA visitor asked for a person, with the last messages
property.verified, property.updatedYour website was verified, or its standing changed
pingA test from the console

Check Cabana-Signature: t=…,v1=…: an HMAC-SHA256 of t + "." + raw body under your signing secret; reject anything older than five minutes. Failed deliveries retry after 1, 5 and 30 minutes, then 2, 6 and 24 hours.

import { createHmac, timingSafeEqual } from 'node:crypto';
export function verified(rawBody, header, secret) {
  const p = Object.fromEntries(String(header).split(',').map(x => x.split('=')));
  if (!p.t || Math.abs(Date.now() / 1000 - Number(p.t)) > 300) return false;
  const want = createHmac('sha256', secret).update(`${p.t}.${rawBody}`).digest('hex');
  return want.length === String(p.v1).length && timingSafeEqual(Buffer.from(want), Buffer.from(p.v1));
}

Errors and limits

Errors are JSON: { "error": "…", "code": "…" }: 400, 401 invalid_key, 402 trial_ended, 403 paused or origin_not_verified, 404, 429. The free trial includes one assistant on one website, 150 pages, 300 conversations and 3,000 messages a month, voice, and two custom actions.