Quick start
- 1
Build and test your agent
- Create an agent in the builder and teach it with files or example chats in Studio.
- Try it in the playground until replies match what you want visitors to see.
- Optional: add conversation starters on the agent profile — they appear as quick-reply chips in the widget.
- 2
Open Agent Studio → Website
- From My Agents, open your agent and go to the Website section in Studio.
- This is where you create embed keys, pick a widget style, and copy install snippets.
- 3
Create an embed API key
- Click Create embed key. The raw nxa_… key is shown once — copy it into your snippet immediately.
- Optionally add allowed domains (one per line, e.g. https://example.com). When set, only those sites can use the key.
- Usage bills to your account. Disable or delete keys anytime from Dashboard → APIs.
- 4
Choose a widget style and copy the snippet
- Floating bubble — classic corner chat button (default).
- Sidebar — full-height panel that slides in from the left or right edge.
- Bottom bar — compact bar across the page that expands into a chat panel.
- Optional: turn on site actions so the agent can search, open pages, and drive a visible cursor on your site from the bubble.
- You can also embed an inline iframe on a support page, or call the REST API from your own app.
- 5
Paste on your site
- For the script widget, paste the snippet before </body> on every page where you want chat, or in your site template.
- For iframe embeds, drop the iframe HTML wherever you want a fixed chat box.
- For mobile apps or custom UIs, use the public agent API with your key in the Authorization header.
Widget options
Configure these with data-* attributes on the script tag. Agent Studio generates the right values for you.
| Attribute | Values | Default |
|---|---|---|
| data-agent-id | Your agent ID | required |
| data-key | nxa_… embed API key | required |
| data-name | Display name in the chat header | Assistant |
| data-mode | bubble · sidebar · bar | bubble |
| data-position | bottom-right · bottom-left · top-right · top-left | bottom-right |
| data-color | Hex accent color | #6366f1 |
| data-theme | light · dark · auto | light |
| data-logo | HTTPS URL for your logo | Nexpher icon |
| data-disclaimer | Footer line under the composer | — |
| data-open | true to open on load | false |
| data-starters | Pipe-separated starter prompts | — |
| data-external-user-id | Your logged-in visitor id (meters per-user credits) | — |
| data-base | Nexpher site URL if self-hosting | script origin |
Logo, colors & theme
Studio → Website includes a live preview of the bubble on a fake page. Change the logo URL, accent color, light/dark/match-page theme, and an optional disclaimer. The preview updates as you type; those values are saved on the agent and written into the snippet.
Site actions
In Studio → Website, turn on Let this agent interact with the website. The visitor stays in the chat bubble; the agent can search, open pages, and — after the visitor Allows — drive a visible cursor that clicks, types, and scrolls on that same site. Paths never leave the host origin.
- site_search opens your search path with ?q= and optional filters (sortBy, city, type, dates).
- site_open_page opens a path you already know, such as /feed or a story URL.
- site_ui_click / site_ui_type / site_ui_scroll move a visible ghost cursor on the page so visitors can watch. The visitor Allows page control once per chat.
- Optional allowed paths limit where the agent may navigate (e.g. /search and /feed).
- The widget sends the current page URL plus an interactive-controls snapshot so the agent knows what it can click.
- Your page can listen for a nexpher:navigate event if you want your own router to change the URL without a full reload.
- Optional: listen for nexpher:ui-act when the ghost cursor clicks, types, or scrolls.
document.addEventListener("nexpher:navigate", (event) => {
event.preventDefault();
router.push(event.detail.path); // Next.js, Vue, etc.
});End-user credit limits
By default every chat on a key burns against your plan. To stop one heavy visitor from using everyone's budget, pass their id from your site or app. Each identified visitor then gets a separate monthly allowance (platform default 10,000 credits / UTC calendar month). Configure defaults, view top users, and raise or pause individuals from Dashboard → APIs → End-user limits.
<script
src="https://nexpher.ai/embed.js"
data-agent-id="YOUR_AGENT_ID"
data-key="nxa_YOUR_KEY"
data-name="Support"
data-external-user-id="user_12345"
async
></script>- Use a stable id from your own auth (user id, email hash, account number) — not a random value each page load.
- Optional: turn on “Require external_user_id” on the key so anonymous calls are rejected.
- Your account plan quota still applies on top of per-visitor limits.
- Bonus credits and pauses apply to the current UTC calendar month.
Example snippets
Floating bubble (most common)
<script
src="https://nexpher.ai/embed.js"
data-agent-id="YOUR_AGENT_ID"
data-key="nxa_YOUR_KEY"
data-name="Support"
data-starters="Track my order|Return policy|Talk to a human"
async
></script>Sidebar panel
<script
src="https://nexpher.ai/embed.js"
data-agent-id="YOUR_AGENT_ID"
data-key="nxa_YOUR_KEY"
data-name="Help"
data-mode="sidebar"
data-position="bottom-right"
async
></script>Inline iframe (support page)
<iframe
src="https://nexpher.ai/embed/YOUR_AGENT_ID?key=nxa_YOUR_KEY&name=Support&parent_origin=https://yoursite.com"
title="Support chat"
style="width:100%;max-width:420px;height:560px;border:0;border-radius:16px;"
allow="clipboard-write"
></iframe>Domain allowlist
When you add allowed domains to an embed key, requests are rejected unless they come from one of those origins. This helps if someone copies your key from page source.
- Add full origins: https://example.com and https://www.example.com if you use both.
- Widget embeds pass the parent site origin automatically.
- Direct API calls must send a matching Origin header.
- Leave the allowlist empty during local testing, then lock it down before production.
Direct API (mobile & custom UI)
Build your own chat UI and call the same endpoint the widget uses. Full reference on the Developers page.
const res = await fetch("https://api.nexpher.ai/v1/agents/YOUR_AGENT_ID/chat", {
method: "POST",
headers: {
Authorization: "Bearer nxa_YOUR_KEY",
"Content-Type": "application/json",
Origin: "https://yoursite.com",
},
body: JSON.stringify({
message: "Where is my order?",
stream: true,
conversation_id: "optional-thread-id",
external_user_id: "user_12345",
}),
});Send back conversation_id from the response to keep a support thread on one topic. Enable chat retention on the agent if you want those threads saved for training. Pass external_user_id to meter each visitor under their own monthly credit limit.
JavaScript control
After the embed script loads, use the global NexpherEmbed object from your page:
// Open the chat panel
NexpherEmbed.open();
// Close it
NexpherEmbed.close();
// Toggle
NexpherEmbed.toggle();
// Open a same-site path (used by site actions)
NexpherEmbed.navigate("/search?q=New+York");
// Example: open when user clicks "Help"
document.getElementById("help-btn").addEventListener("click", () => {
NexpherEmbed.open();
});Security notes
- Embed keys appear in your page HTML — treat them as public widget keys, not server secrets.
- Use domain allowlisting in production to limit where the key works.
- Pass data-external-user-id (or external_user_id on the API) so one visitor cannot exhaust the shared budget.
- Rotate keys from Dashboard → APIs if a key is exposed or abused.
- Each key is rate-limited (30 requests/minute by default).
- For server-side integrations, keep keys on your backend and proxy requests instead of exposing them in the browser.
Was this page helpful?
