What you’ll build

By the end of this guide your website will have a floating voice button that:
  • Opens a live AI voice call when clicked
  • Uses your branding (colors, logo, name)
  • Passes your logged-in user’s details to the agent
  • Lets the agent open forms mid-call and submit them to your backend

Step 1 — Create your agent in the dashboard

  1. Sign in at app.oshara.ai
  2. Go to Characters → New Character
  3. Fill in:
    • Slug — a URL-safe ID, e.g. support-bot (you’ll use this in the script tag)
    • System prompt — what the agent should do and how it should behave
    • Greeting — the first thing it says when a call starts
  4. Under Allowed Origins, add your website domain:
    https://yoursite.com
    
  5. Save the character.

Step 2 — Embed the script tag

Paste this before the closing </body> tag on every page where you want the widget:
<script
  src="https://api.oshara.ai/widget.js"
  data-agent="support-bot"
  data-api-url="https://api.oshara.ai">
</script>
Replace support-bot with your character’s slug. A floating button will appear in the bottom-right corner. Test it: Open the page, click the button, allow mic access, and click Start Call. You should hear the greeting within a few seconds.

Step 3 — Customise the appearance

Go to Characters → [your character] → Widget Appearance in the dashboard and set your brand colors, logo, and panel size. Or configure it via the API:
PATCH /api/ai-characters/support-bot/
{
  "widget_appearance": {
    "name": "Acme Assistant",
    "logo_url": "https://cdn.yoursite.com/logo.png",
    "fab_label": "Talk to us",
    "theme": {
      "primary_color": "#FF6B35",
      "background_color": "#FFFFFF",
      "text_color": "#1A1A1A"
    },
    "layout": {
      "position": "bottom-right",
      "font_family": "Inter, sans-serif"
    }
  }
}
See the full Appearance reference for every option.

Step 4 — Pass your user’s context to the agent

When your user is logged in, you want the agent to know who they are. Do this by calling the session endpoint from your backend instead of letting the widget call it directly. Your backend calls Oshara to get a LiveKit token, then passes it to the widget. This keeps your API key server-side and lets you inject user context. Your backend (Node.js example):
// POST /your-api/start-voice-session
app.post("/your-api/start-voice-session", requireAuth, async (req, res) => {
  const user = req.user; // your authenticated user

  const response = await fetch("https://api.oshara.ai/api/agents/agent-session/", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Origin": "https://yoursite.com"
    },
    body: JSON.stringify({
      agent: "support-bot",
      metadata: {
        user_id:    user.id,
        user_name:  user.name,
        user_email: user.email,
        account_tier: user.plan,   // any extra context the agent should know
      }
    })
  });

  const session = await response.json();
  res.json(session); // { token, livekit_url, room_name, session_id, ... }
});
Your frontend — connect the widget with a pre-minted token:
<script>
  window.VOICE_AGENT_SLUG = "support-bot";
  window.VOICE_API_URL    = "https://api.oshara.ai";
</script>
<script src="https://api.oshara.ai/widget.js"></script>

<script>
  // Override the widget's session-start with your own endpoint
  // (advanced: intercept via the widget's session hook if supported,
  //  or load the token before the widget boots)
  document.addEventListener("DOMContentLoaded", () => {
    window.__OsharaSessionOverride = async () => {
      const res = await fetch("/your-api/start-voice-session", { method: "POST" });
      return res.json(); // must return { token, livekit_url }
    };
  });
</script>
The metadata object is available to the agent worker and can be referenced in tool calls.

Step 5 — Handle post-call form submissions

If you’ve defined forms on your character, the widget will POST submissions to your submit_url. Set up an endpoint on your backend to receive them:
// Express example
app.post("/api/demo-requests", express.json(), (req, res) => {
  const { name, email, company, date } = req.body;

  // Save to your database, trigger a Zapier hook, send a Slack notification...
  await db.demoRequests.create({ name, email, company, date });
  await slack.notify(`New demo request from ${name} <${email}>`);

  res.status(200).json({ ok: true });
});
In the form definition, point submit_url at this endpoint:
{
  "id": "book-demo",
  "title": "Book a demo",
  "submit_url": "https://yoursite.com/api/demo-requests",
  "fields": [
    { "name": "name",    "label": "Your name",    "type": "text",  "required": true },
    { "name": "email",   "label": "Work email",   "type": "email", "required": true },
    { "name": "company", "label": "Company",      "type": "text" },
    { "name": "date",    "label": "Preferred date","type": "date" }
  ]
}
The widget sends a JSON POST with the field values as the body. Return any 2xx to confirm. See Form Handling for the full form configuration reference.

Step 6 — Auto-open for dedicated landing pages

For a page whose entire purpose is the voice agent (e.g. a demo page):
<script
  src="https://api.oshara.ai/widget.js"
  data-agent="support-bot"
  data-open-chat="true">
</script>
The panel opens immediately on page load — no button click needed.

Checklist

  • Character created with a slug
  • Your domain added to Allowed Origins
  • Script tag added to your site
  • Call works end-to-end in the browser
  • Branding configured (colors, logo, FAB label)
  • User context passed via metadata (if your site has login)
  • Form submit_url pointing at your backend (if using forms)