Documentation
Add Belline to a website
Belline is an AI receptionist. One line of HTML puts it on any website: it answers questions about the business, and — once the business has an account — takes bookings against a real diary. No build step, no package to install, no framework required.
This page is public and has no signup wall. If you are an AI agent, read Installing from an AI coding agent first: there is a way to create a working receptionist with no account, and a claim link to hand to a person afterwards.
1. Paste one line
Put this immediately before the closing </body> tag, on every page the button
should appear on. Replace be_YOUR_KEY with the key from your Belline dashboard
under Channels → Website.
<script src="https://app.belline.ai/embed.js" data-belline="be_YOUR_KEY" data-mode="both" async></script>
That is the whole installation. A button appears in the bottom-right corner. Tapping it opens a panel in which the visitor reaches that business's own receptionist.
The key is public by design — it sits in your page source, and anybody can read it. Nothing about the safety of this depends on it staying secret: what does the work is the list of origins the widget is allowed to load on, and the per-day ceilings, both set on the venue and neither editable from the page.
2. Change what it shows
Every attribute is optional except data-belline.
| Attribute | Required | Default | Values | What it does |
|---|---|---|---|---|
data-belline |
Yes | — |
— | The venue's public embed key. Without it the script writes a warning to the page's console and does nothing else. It is public by design — it sits in the page source — and none of the safety depends on it staying secret: what does the work is the origin allowlist and the per-day ceilings, both set on the venue. |
data-mode |
No | voice |
voice · chat · both |
Which buttons appear: a bell to talk, a bubble to type, or both with the bubble above the bell. Anything unrecognised is read as `voice`. It cannot switch on a channel the venue has switched off. |
data-side |
No | right |
right · left · center |
Where along the bottom of the page the buttons float: a corner, or the middle. Useful when something else — a cookie bar, a live-chat widget, a back-to-top arrow — already occupies the right. Set here it wins over the corner chosen in the dashboard. With data-mount it says where in the element Belle sits instead (the middle when unset). |
data-offset-x |
No | 24 (18 on a phone) |
— | Pixels from the side the buttons float on, from 0 to 400. A larger number is clamped, and the widget never goes further than the screen allows. Ignored with data-side="center" and with data-mount. |
data-offset-y |
No | 24 (18 on a phone) |
— | Pixels from the bottom of the screen, from 0 to 600, to sit above a cookie bar or a sticky footer. Wins over the height chosen in the dashboard. Ignored with data-mount. |
data-size |
No | standard |
small · standard · large · a number of pixels |
The size of the round button (48, 58 or 68 pixels; a number is clamped to 40–96), or of Belle's face where the business has video (200, 260 or 320; a number is clamped to 120–360). Buttons with words on them keep their text size. Wins over the size chosen in the dashboard. |
data-mount |
No | — |
— | A CSS selector, such as #belle. Belle is drawn inside that element, in the page's own flow, instead of floating in a corner — the way belline.ai shows her in its first screen. If nothing on the page matches, she floats in the corner instead and the script writes one warning to the console. Chats and calls still open in their own window over the page. |
data-label |
No | Talk to us |
— | The words on the voice button. Set here it wins over the venue's own choice in the dashboard, so one page can say something different from the rest of the site. |
data-chat-label |
No | Chat with us |
— | The words on the chat button. As with data-label, an attribute on the tag wins over the dashboard, and the dashboard's words arrive a moment after the page loads for everyone else. |
data-whatsapp-label |
No | WhatsApp us |
— | The words on the WhatsApp button. That button appears only when the venue has a WhatsApp number connected, so on most sites this attribute does nothing at all. |
data-video-label |
No | Video call |
— | The words on the video button. The button appears only when the venue's own configuration turns video on; nothing on the tag can turn it on, and a preview venue can never have it. |
A chat-only button on the left, labelled in your own words:
<script src="https://app.belline.ai/embed.js" data-belline="be_YOUR_KEY" data-mode="chat" data-side="left" data-chat-label="Ask us anything" async></script>
An attribute chooses what to show. It cannot switch on something the business has switched
off. Setting data-mode="both" on a venue with the voice channel disabled shows
the chat button and nothing else. Entitlement lives on the venue, not in HTML anybody can edit.
3. Allow your domain
The widget refuses to load on an origin that is not on the venue's allowlist, so add the live domain before launch — in the dashboard under Channels → Website, or over the API:
curl -X PATCH https://app.belline.ai/api/install/v1/venue \
-H 'authorization: Bearer bk_your_key' \
-H 'content-type: application/json' \
-d '{"allowed_origins": ["https://example.com"]}'
Scheme and host only. A path or a query in an allowlist entry never matches anything, because a
browser sends an origin and an origin has neither. https://example.com and
https://www.example.com are treated as the same site.
4. Check it before you ship
Ask the receptionist a question and read the answer, exactly as a visitor would get it:
curl -X POST https://app.belline.ai/api/install/v1/venue/preview \
-H 'authorization: Bearer bk_your_key' \
-H 'content-type: application/json' \
-d '{"message": "are you open on Sunday?"}'
Ask the awkward ones — a price, a Sunday, a booking for Friday at seven. This is the only way to find out that the hours you entered say the shop opens on a day it is actually shut. Each call is a real model call and counts against the venue's allowance.
Installing from an AI coding agent
Signing up for Belline normally needs a six-digit code from an email inbox, which an agent cannot read. So there is a second door: a preview venue, created by one call with no account, no card and no code.
curl -X POST https://app.belline.ai/api/install/v1/venues \
-H 'content-type: application/json' \
-d '{"business_name": "Rose & Thorn", "website": "https://roseandthorn.example"}'
The response carries an API key (shown once), the embed snippet, and a claim link. Paste the snippet, set the details, check the answers, then give the claim link to a person at the business.
A Belline referral partner building this for a client adds
"partner": "your-code" to that body, and the business that claims the preview is
credited to them. A code Belline does not know is refused with a 422 rather than ignored.
What a preview can and cannot do
- 20 conversations in total, for the life of the preview — not per day — and 12 visitor messages in each.
- Chat only. No phone number, no WhatsApp, no video, no web voice.
- It cannot take a booking, take a message, or fetch a person. Those tools are not given to it, so it cannot do it by mistake or be talked into it.
- It says so. Belle opens every conversation by saying she is a preview, is not switched on, and cannot pass anything to the team. The button carries a “Preview — not live” badge.
- It is deleted after 14 days unless a person claims it. The line left in the page then does nothing at all — no button, no error, nothing broken.
- One preview per network per day.
Tell whoever you are building for all of that. A receptionist that disappears in a fortnight is not a pleasant surprise.
The MCP server
We have built a Model Context Protocol server that
wraps these calls as tools — create_preview_venue, set_business_details,
get_embed_snippet, ask_belle, get_claim_link and the rest — but it
is not published yet: it is not on npm and its source is not public, so it cannot be
installed from outside Belline today. Everything it does is one of the HTTP calls on this page, which
you can make directly. Write to hello@belline.ai if you would
like to know when it is out.
Machine-readable summary of this site: /llms.txt.
Every endpoint
| Call | Key? | What it does |
|---|---|---|
POST /api/install/v1/venues | No | Create a preview venue. Returns the API key, the snippet and the claim link. |
GET /api/install/v1/venue | Yes | Everything Belline knows about the venue, including its snippet and a preview's remaining allowance. |
PATCH /api/install/v1/venue | Yes | Set the name, hours, services, staff, languages, FAQs, house rules and allowed origins. Only the fields you send change. |
GET /api/install/v1/venue/snippet | Yes | The line to paste and what each attribute does. |
POST /api/install/v1/venue/preview | Yes | Ask the receptionist a question and read the reply. Spends one conversation. |
GET /api/install/v1/venue/conversations | Yes | Recent conversations. Claimed venues only. |
GET /api/install/v1/venue/bookings | Yes | Recent bookings. Claimed venues only. |
GET /api/install/v1/venue/claim-link | Yes | The URL a person follows to make the preview real. |
POST /api/install/v1/venue/widget | Yes | Switch the widget on or off. Off needs "confirm": true. |
Send the key as Authorization: Bearer bk_…. A refusal comes back as
{"error": "…", "code": "…", "fix": "…"} — code is the stable string to branch
on, and fix says what to do instead of retrying.
Claiming a preview
A person at the business opens the claim link, creates an account with the ordinary email confirmation, and everything carries over — the hours, the services, the languages, and the embed key, so the line already on the site keeps working and nobody has to edit the site again. The API key keeps working too. Belle stops calling herself a preview, and the phone, WhatsApp, video and bookings become available on a plan.
Removing it
Delete the <script> line. That is all — nothing else is left behind on the page,
and there is no second file to clean up. To switch the button off without editing the site, use the
dashboard or POST /api/install/v1/venue/widget with
{"enabled": false, "confirm": true}.