Trooply Chatbot Documentation
Everything you need to ship the Trooply AI shopping assistant on your store — from your first <script> tag to a fully customized, multilingual, multi-channel experience.
Quick start
Three steps. ~5 minutes.
- Create your account — pick a plan or start free.
- Walk through the onboarding wizard — connect your store, copy your embed snippet.
- Paste the snippet into your theme. The widget appears in the corner of every page.
Embed the widget
Paste this just before </body> on every page. Replace the placeholders from your dashboard.
<script async
src="https://chatbot.trooply.ai/widget.js"
data-store-id="YOUR_STORE_ID"
data-api-key="YOUR_API_KEY"></script>
That's the entire integration — two attributes, one script tag. The widget infers its API origin from the script's src, so data-api-url is only needed if you're self-hosting or proxying.
| data-* | What it does |
|---|---|
data-store-id | Your Trooply store UUID — visible on every dashboard page. |
data-api-key | Active widget API key. Manage at /dashboard/developer. |
data-api-url | Optional. The Trooply origin. Auto-inferred from the script src; only set this if you're proxying. |
data-user-token | Optional signed JWT identifying a logged-in shopper for personalized history and recommendations. |
data-product-id | Optional. When set on a PDP, surfaces product-specific FAQs above the input box. |
Per-page customization (overrides)
These optional attributes let you override the dashboard config on a per-page basis — useful for A/B tests, landing-page-specific greetings, or multi-language sites without re-saving from the dashboard.
| data-* | What it does |
|---|---|
data-primary-color | Hex color for the bubble + header. Example: "#10b981". |
data-bot-name | Display name shown in the chat header. |
data-welcome-message | First message the bot sends when the chat opens. |
data-placeholder | Placeholder text inside the message input box. |
data-position | bottom-right (default) or bottom-left. |
data-launcher-text | Optional teaser bubble shown above the launcher button. |
data-show-branding | true or false — overrides the plan default (Pro/Enterprise can hide branding). |
data-auto-open-after | Milliseconds to wait before auto-opening the chat. Set to 0 or omit to disable. |
<!-- Example: green widget on the cart page that auto-opens after 5s -->
<script async
src="https://chatbot.trooply.ai/widget.js"
data-store-id="YOUR_STORE_ID"
data-api-key="YOUR_API_KEY"
data-primary-color="#10b981"
data-welcome-message="Need help with your order? I'm here."
data-auto-open-after="5000"></script>
Match your brand
Brand the widget from /dashboard/widget: primary color, position, greeting text, bot name and avatar, and the placeholder text. Pro and Enterprise plans hide the Trooply branding.
Refinement chips
When a visitor types a broad term like shoe, Trooply doesn't dump 100 results — it asks one short question and shows tappable chips:
Bot: Pick what fits — or tap 🏆 Best for me and I'll choose.
[ Type · Running ] [ Type · Casual ] [ Type · Skate ]
[ Color · Black ] [ Color · White ] [ Color · Blue ] [ Color · Red ]
[ Color · Any ] [ 🏆 Best for me ]
Each chip is its own user message — the visitor never has to type. Chips compose intelligently: tapping Color · Black after Running returns black running shoes specifically, not random black products from other categories.
Best for me
Tapping 🏆 Best for me calls the LLM with the current refinement context (e.g. "running" + "black") plus a candidate pool of matching products, and returns the top 3 picks. If fewer than 4 products match, the system short-circuits and returns them all — no LLM call needed.
Widget events
The widget fires CustomEvents on window so you can hook into your own analytics (Google Analytics, Segment, Mixpanel, dataLayer) without backend integration.
| Event name | When it fires | detail payload |
|---|---|---|
trooply:chat_opened | Visitor opens the chat panel | {store_id, at} |
trooply:chat_closed | Visitor closes the chat panel | {store_id, at} |
// Pipe widget opens into GA4
window.addEventListener("trooply:chat_opened", (e) => {
gtag("event", "chat_opened", { store_id: e.detail.store_id });
});
Languages
Trooply auto-detects the visitor's language per message. Supported: English, Hindi (हिन्दी), Spanish (Español), Arabic (العربية). The detection runs on the message itself, not browser locale, so multilingual shoppers get correct replies even mid-session.
Chat API
Public chat endpoints accept an X-API-Key header. Use these to integrate Trooply into a native app, Slack bot, WhatsApp bridge, or any non-widget surface.
POST /api/v1/chat/message
Content-Type: application/json
X-API-Key: sk_live_…
{
"message": "show me running shoes",
"session_id": "any-unique-session-string",
"visitor_id": "optional-cross-session-id"
}
Response:
{
"text": "Pick what fits…",
"message_type": "quick_actions" | "product_card" | "text" | …,
"products": [{"id":"…","name":"…","price":89.99, "image_url":"…", …}],
"quick_actions": ["Type · Running", "Color · Black", "🏆 Best for me"],
"metadata": {"intent":"refinement", "source":"refinement", …}
}
Code samples
The exact same call, in the language you're already writing in:
curl
curl -X POST https://chatbot.trooply.ai/api/v1/chat/message \
-H "X-API-Key: sk_live_…" \
-H "Content-Type: application/json" \
-d '{"message":"show me running shoes","session_id":"sess-1234"}'
Python (requests)
import requests
r = requests.post(
"https://chatbot.trooply.ai/api/v1/chat/message",
headers={"X-API-Key": "sk_live_…"},
json={
"message": "show me running shoes",
"session_id": "sess-1234",
"visitor_id": "v-42",
},
timeout=30,
)
data = r.json()
print(data["text"])
for product in data.get("products") or []:
print(f" - {product['name']} (${product['price']})")
Node.js (fetch / Node 18+)
const res = await fetch("https://chatbot.trooply.ai/api/v1/chat/message", {
method: "POST",
headers: {
"X-API-Key": "sk_live_…",
"Content-Type": "application/json",
},
body: JSON.stringify({
message: "show me running shoes",
session_id: "sess-1234",
visitor_id: "v-42",
}),
});
const data = await res.json();
console.log(data.text);
(data.products || []).forEach(p => {
console.log(` - ${p.name} ($${p.price})`);
});
React hook
import { useState, useCallback } from "react";
export function useTrooplyChat(apiKey, sessionId) {
const [messages, setMessages] = useState([]);
const [loading, setLoading] = useState(false);
const send = useCallback(async (text) => {
setMessages(prev => [...prev, { role: "user", text }]);
setLoading(true);
try {
const r = await fetch("https://chatbot.trooply.ai/api/v1/chat/message", {
method: "POST",
headers: {
"X-API-Key": apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify({ message: text, session_id: sessionId }),
});
const data = await r.json();
setMessages(prev => [...prev, {
role: "bot",
text: data.text,
products: data.products || [],
chips: data.quick_actions || [],
}]);
} finally {
setLoading(false);
}
}, [apiKey, sessionId]);
return { messages, send, loading };
}
Streaming (Server-Sent Events)
// JS / Browser
const res = await fetch("https://chatbot.trooply.ai/api/v1/chat/stream", {
method: "POST",
headers: { "X-API-Key": "sk_live_…", "Content-Type": "application/json" },
body: JSON.stringify({ message: "show me shoes", session_id: "s-1" }),
});
const reader = res.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { value, done } = await reader.read();
if (done) break;
// each chunk is one or more "data: {...}\n\n" SSE events
for (const line of decoder.decode(value).split("\n\n")) {
if (!line.startsWith("data: ")) continue;
const event = JSON.parse(line.slice(6));
if (event.type === "token") process.stdout.write(event.text);
if (event.type === "done") {
console.log("\nproducts:", event.products);
console.log("chips:", event.quick_actions);
}
}
}
Billing API
| Endpoint | Method | Purpose |
|---|---|---|
/api/v1/billing/pricing | GET | Public pricing table (3 tiers). |
/api/v1/billing/checkout | POST | Create a Stripe Checkout session. Returns {url, session_id}. |
/api/v1/billing/portal | POST | Open the Stripe customer portal. |
/api/v1/billing/subscription | GET | Current plan + billing status for the authed store. |
/api/v1/billing/webhook | POST | Where Stripe POSTs events (signed by Stripe-Signature). |
Onboarding API
| Endpoint | Method | Purpose |
|---|---|---|
/api/v1/onboarding/status | GET | Checklist of remaining setup steps. |
/api/v1/onboarding/embed-snippet | POST | Mints an API key + returns the ready-to-paste snippet. |
/api/v1/onboarding/brand | PUT | Save brand color + greeting. |
/api/v1/onboarding/import-catalog | POST | Kicks off a crawl of the store URL. |
/api/v1/onboarding/complete | POST | Mark onboarding done. |
Stripe webhooks
Point Stripe at https://chatbot.trooply.in/api/v1/billing/webhook and subscribe to:
checkout.session.completedcustomer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.payment_failed
Trooply verifies the Stripe-Signature header against STRIPE_WEBHOOK_SECRET. Events update the store's billing_status, subscription_plan_id, and plan_expires_at in real time.