Loops AI Docs

The chat URL

Every query parameter the chat runtime accepts — required container flags, session continuity, and flow entry points you can open straight from the URL.

The runtime is addressed entirely by URL. Your agentId is a path segment; everything else is a query parameter.

https://chat.loopsai.com/<agentId>?embedded=true&mode=sdk&platform=ios&isMobile=true

Encode your values

Build the URL with your platform's URL builder (URLComponents, Uri.Builder, URL/URLSearchParams), not string concatenation. A raw &, space, or non-ASCII character in a product code or search query silently truncates the rest of the query string.

Required for a mobile container

ParameterValueWhy
embeddedtrueLoads the embedded chat surface (the panel), not the standalone marketing page.
modesdkSwitches the runtime to host-driven mode: it attaches its message listener, emits ready, and routes product taps to you instead of navigating itself.
platformios | androidTags the session and its analytics with the real platform. Match the device.
isMobiletrueMobile layout (sizing, sheets, keyboard handling). Send it on every phone-sized container.

`mode=sdk` is the switch that makes a WebView integration possible

Leave it out and the chat still renders — but the runtime treats a top-level page as standalone: it never attaches its inbound message listener, never emits ready, and opens product links inside its own WebView. You would have a chat you cannot control, close, or route out of. Always send it.

Optional

ParameterValueEffect
_lsuidAnonymous user idRestores a known anonymous user — see Session continuity.
_lscidConversation idResumes that conversation. Ignored when fresh=true.
freshtrueStarts a brand-new conversation and ignores any stored one. Use for a "new chat" entry point.
parentOriginYour page origin, URL-encodedIframe transport only. Adds your page to the runtime's trusted-sender list. Without it your inbound messages are dropped.
localeen | trPins the chat language, outranking the device language and any previously stored preference. Regional tags are accepted (tr-TR → tr). Omit it to follow the device.

Do not copy web-embed parameters

widgetMode, loopsai_open, and rt belong to the website embed script and its bubble / bottom-bar / sidebar layouts. They have no meaning in a mobile container — the WebView is the panel.

Language

The chat resolves its language in this order:

  1. ?locale= — your explicit override. Use it when your app has its own language setting that may differ from the device.
  2. The visitor's stored preference from an earlier session.
  3. The WebView's own language (Accept-Language / navigator.language).
  4. English.

English and Turkish are supported today; an unsupported value falls through to the next step rather than failing. ?locale= applies to the whole session — interface strings, agent copy, and the language the assistant answers in — so pass it whenever your app knows better than the device.

It only applies on load

Language is resolved when the runtime boots. To switch language in a warm WebView, reload it with the new ?locale= value.

Flow entry points on the URL

These open a flow at load time, with no bridge message. Ideal when a native button should land the user straight in a flow, because there is nothing to wait for — no ready, no timing.

ParameterOpens
suggestSize=trueThe size-suggestion form (height + weight) as soon as the chat is usable.
sizeGuide=trueThe body-type size guide inside the conversation. Combine with productCode and gender.
productCode=<code>The product the size guide should size. Must match your Loops AI catalog code.
gender=women | menSkips the gender question in the size guide.
searchQuery=<text>Starts a fresh conversation and runs that query as an AI search escalation.
# "Find my size" button
https://chat.loopsai.com/AGENT?embedded=true&mode=sdk&platform=ios&isMobile=true&suggestSize=true

# "Size guide" button on a product screen
https://chat.loopsai.com/AGENT?embedded=true&mode=sdk&platform=android&isMobile=true
  &sizeGuide=true&productCode=1010600-88244&gender=women

# Your own search bar escalating into the assistant
https://chat.loopsai.com/AGENT?embedded=true&mode=sdk&platform=ios&isMobile=true
  &searchQuery=linen%20shirts%20under%2050

URL for a cold open, bridge for a warm one

If you keep one WebView alive and reuse it (recommended — it reopens instantly), a URL parameter only applies on the load that carried it. Use the bridge actions in Flow modes to open a flow in a WebView that is already loaded.

The standalone size guide

The body-type size guide also has its own route. Open it in its own WebView/sheet when you want the guide without the conversation around it:

https://chat.loopsai.com/<agentId>/size?productCode=1010600-88244&gender=women&mode=sdk&platform=ios
ParameterNotes
productCodeOptional. Resolved from the catalog when omitted.
genderwomen or men. Skips the gender step.
mode, platformSame as the chat — required for the page to talk to your bridge.

It speaks the same bridge and sends three actions: closeChat when the user dismisses it, openExternalUrl for a product link, and startSizeGuideInline when the user chooses to continue in chat. See Links & navigation for that hand-off.

Session continuity

The runtime keeps its anonymous user id and conversation id in the WebView's localStorage. As long as your WebView uses a persistent data store and you don't clear it, the conversation resumes on its own — nothing to implement.

Two ids matter:

IdMeaning
anonUserIdThe pseudonymous shopper. Stable across conversations.
conversationIdThe conversation to resume, per agent.

For a fully robust setup, mirror them natively. The runtime hands them to you whenever they change:

// web → host
{ "name": "persistSession",
  "payload": { "agentId": "AGENT", "anonUserId": "…", "conversationId": "…" } }

Store both, then pass them back as _lsuid and _lscid on the next load. They are only used to seed storage when it is empty, so replaying them is safe.

https://chat.loopsai.com/AGENT?embedded=true&mode=sdk&platform=ios&isMobile=true
  &_lsuid=<anonUserId>&_lscid=<conversationId>

Why the SDKs bother

iOS WebKit can clear WebView storage under storage pressure or on app termination, which would drop the conversation. Mirroring persistSession natively (Keychain, UserDefaults, SharedPreferences, secure storage) and replaying the two ids is what makes a session survive that. Skip it and you get a good-enough session that occasionally restarts.

To start a new conversation deliberately, drop _lscid and add fresh=true — keep _lsuid so the new conversation still belongs to the same shopper.

Environments

EnvironmentBase URL
Productionhttps://chat.loopsai.com
Staging / self-hostedProvided by your Loops AI contact

There is no API key or client secret in the URL. Access is resolved server-side from the agentId, so treat the URL as public — and keep any personal data out of it (use initContext over the bridge instead).

Availability check

Your Loops AI channel has an Active / Inactive status in the dashboard. Ask for it before you show your chat entry point, and you can turn the assistant on or off — for a launch, or for maintenance — without shipping an app update:

GET https://chat.loopsai.com/api/embed/<agentId>/style
{
  "embedEnabled": true,   // web channel status
  "iosEnabled": true,     // present when an iOS channel exists
  "androidEnabled": true  // present when an Android channel exists
}

Read the platform field first and fall back to embedEnabled. Fail open — treat a network error or unparseable response as available, so a transient blip never hides a working assistant.

val available = json.optBoolean("androidEnabled", json.optBoolean("embedEnabled", true))
chatButton.isVisible = available

The response is the agent's published configuration, so the same call tells you which native entry points are worth showing — virtualTryOnEnabled, sizeSuggestionEnabled, voiceModeEnabled, and friends. Gate your buttons on them: a flow that is disabled for the agent is ignored by the runtime, so a button for it would do nothing.

Next: The message bridge.

On this page