private beta · three providers · one key

The chat bubble
grew a face.

One API key and five lines of code put a live video person on your site — it answers with your data by calling tools you define on your own server, every request signed. And when video isn't possible, it steps down to text chat instead of going dark.

$npm i @bubblio/server @bubblio/widgetor one script tag ↓
sess_b8e4f2a01cexample · replay

how it works

A route, a tag, and your tools get called.

That is the entire integration. Bubblio owns the provider WebSockets, the media pipeline, and the session metering; you own two small files and the answers.

01your server

One route holds the key

It never reaches the browser. The route declares what the character may do — each tool is just a callback URL on your side.

app/api/bubblio/session/route.ts
import { createBubblioSession } from '@bubblio/server'export async function POST() {return Response.json(await createBubblioSession({bubblioApiKey: process.env.BUBBLIO_API_KEY!,personality: 'Help the customer.',tools: [{  name: 'get_orders',  description: 'Orders for the current user',  callbackUrl: 'https://you.com/api/tools',}],}))}
02your page

One tag mounts the bubble

The widget calls your route, gets a session, and opens the video stream. No provider SDK, no WebSocket code, no keys in the client.

index.html
<!-- plain HTML, Webflow, Wix — no build step --><script defersrc="https://cdn.jsdelivr.net/npm/@bubblio/widget@0.10/dist/embed.global.js"data-server-url="/api/bubblio/session"></script><!-- in React instead: --><!-- <BubblioWidget config={{ serverUrl }} /> -->
03every question

Your tools get called

When a visitor asks, Bubblio POSTs to your callback URL — HMAC-signed, with the user identity in a signed JWT. Answer with JSON.

what your server receivessigned
POST /api/tools?ctx=<signed user jwt>X-Bubblio-Signature: sha256=8a1f…{"sessionId": "sess_b8e4f2a01c","tool": "get_orders","args": { "orderId": "ORD-4291" }}// you return JSON — Aria says it out loud

Embedding on Webflow, Wix, or hand-written HTML? Read the embed guide

the ladder

Fails down a rung,
never off a cliff.

Most support widgets have two states: working and gone. Bubblio has a ladder. When video isn't possible — an avatar provider is down, or your prepaid minutes run out — the bubble steps down and keeps answering. A visitor never meets a dead bubble or a paywall mid-question.

video

A live person, on video

The visitor talks to a real-time avatar over WebRTC. It answers with your data by calling the tools you registered — every call signed, every call logged.

provider unhealthy at connect
video

Same character, different provider

Three avatar providers stand behind every session. If the preferred line is down or cooling off, the session opens on the next one — the switch happens before the call starts.

prepaid minutes hit zero
text

Text chat, same brain

Same personality, same tools, same signed callbacks — in text. Chat doesn’t draw down your minutes, and video comes back the moment you top up.

Three avatar providers.
One line: yours.

1Runwayserves first2Tavussecond line3Anamthird line

Bubblio holds the provider keys and picks a healthy line the moment a visitor connects. Your five lines never change — an avatar outage pages us, not you.

pricing

Prepaid minutes. That's the whole model.

Buy a pack, the bubble draws it down by the second. Because it's prepaid, a surprise bill is structurally impossible — and because of the ladder, an empty balance never hangs up on a customer.

pack_100
100minutes
$49 one-time · 49¢ / min
Request access
pack_2000
2,000minutes
$599 one-time · ≈ 30¢ / min
Request access
20 free minutes to start
Granted once, when your team is approved into the beta.
One-time packs
No subscription, no seats. Only avatar minutes meter — tool calls don’t.
At zero: chat, not a cutoff
The bubble degrades to text — same character, same tools. Video resumes when you top up.

Put a face on it.

Bubblio is in private beta. Request access — approved teams start with 20 free minutes.

Request accessRead the docs