> ## Documentation Index
> Fetch the complete documentation index at: https://www.bolna.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Web Call SDK starter templates

> Copy-paste starter templates for the Bolna Web Call SDK: a Next.js App Router route and a plain HTML page with a small Node backend.

Two complete, copy-pasteable starting points. Pick whichever matches your stack.

## Next.js (App Router)

Works out of the box on Vercel. Set `BOLNA_API_KEY` and `BOLNA_AGENT_ID` as environment variables and deploy.

```javascript app/api/bolna-session/route.js theme={"system"}
export async function POST(req) {
  const { user_data } = await req.json().catch(() => ({}));
  const r = await fetch("https://api.bolna.ai/web-call/session", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.BOLNA_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ agent_id: process.env.BOLNA_AGENT_ID, user_data }),
  });
  return new Response(await r.text(), {
    status: r.status,
    headers: { "Content-Type": "application/json" },
  });
}
```

```jsx app/components/BolnaCallButton.jsx theme={"system"}
"use client";
import { useState } from "react";
import { BolnaWebCall } from "@bolna/web-call";

// pass userData to fill {{name}}/{{order_id}}-style variables in the agent's prompt
export default function BolnaCallButton({ userData }) {
  const [state, setState] = useState("idle");

  const startCall = () => {
    const call = new BolnaWebCall({ sessionUrl: "/api/bolna-session", userData });
    call.on("state-change", setState);
    call.on("call-end", () => setState("idle"));
    call.on("error", (e) => console.error(e.code, e.message));
    call.start();
  };

  return (
    <button onClick={startCall} disabled={state !== "idle" && state !== "ended"}>
      {state === "active" ? "On call" : "Start call"}
    </button>
  );
}
```

```jsx usage theme={"system"}
<BolnaCallButton userData={{ name: "Asha", order_id: "ORD-4521" }} />
```

## Plain HTML + Node

No build step, no framework. Two files, no `package.json` needed. Run `BOLNA_API_KEY=bn-… BOLNA_AGENT_ID=… node server.mjs`, then open `index.html`.

```javascript server.mjs theme={"system"}
// the .mjs extension runs as ESM with zero setup, even with no package.json
import http from "node:http";

http.createServer(async (req, res) => {
  if (req.method !== "POST" || req.url !== "/bolna-session") return res.writeHead(404).end();
  const chunks = [];
  for await (const chunk of req) chunks.push(chunk);
  const { user_data } = JSON.parse(Buffer.concat(chunks).toString() || "{}");
  const r = await fetch("https://api.bolna.ai/web-call/session", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.BOLNA_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ agent_id: process.env.BOLNA_AGENT_ID, user_data }),
  });
  res.writeHead(r.status, { "Content-Type": "application/json" }).end(await r.text());
}).listen(8787, () => console.log("session endpoint on http://localhost:8787/bolna-session"));
```

```html index.html theme={"system"}
<script src="https://cdn.jsdelivr.net/gh/bolna-ai/web-call@v3.0.0/dist/bolna-web-call.min.js"></script>
<button id="call">Start call</button>
<script>
  const call = new BolnaWebCall({
    sessionUrl: "http://localhost:8787/bolna-session",
    userData: { name: "Asha", order_id: "ORD-4521" },
  });
  call.on("error", (e) => alert(e.message));
  document.getElementById("call").onclick = () => call.start();
</script>
```

## Next steps

<CardGroup cols={2}>
  <Card title="SDK API reference" href="/docs/developer-resources/sdks/web-call-api" />

  <Card title="Take calls in the browser" href="/docs/developer-resources/sdks/web-call" />
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.