Before you start
Open Dashboard → API keys to create a key for your business. Copy it once and confirm that Iris is launched from Home. Website-only businesses do not need a Meta account. Keep the key in your backend secret manager as FLOWLITH_API_KEY. Do not paste the real key into an LLM prompt. API endpoint: https://api.flowlith.com/v1/chat
Need a chat box on your site? Use the website embed example. There is no hosted Flowlith widget or public script tag: your site supplies the interface and a secure backend. To let Iris call your business systems instead, see Actions and external tools.
Check authentication
GET https://api.flowlith.com/v1/auth/check with Authorization: Bearer YOUR_API_KEY. A 200 {"ok":true} confirms the key only, not installation or agent readiness. No model runs.
# Run on your server. Read the key from its secret environment, not a pasted command.
curl --fail-with-body https://api.flowlith.com/v1/auth/check \
-H "Authorization: Bearer $FLOWLITH_API_KEY"
401 means invalid/revoked key; 429 means wait for Retry-After; 503 means temporarily unavailable. Rotate or revoke in Dashboard → API keys. The old key stops accepting new requests immediately.
Integration requirements
Implement website chat using the existing project stack. Reuse the site's authentication, backend and database. Do not call Flowlith directly from browser JavaScript.
Flow: customer browser -> your authenticated backend -> Flowlith -> your backend -> browser. Use the server-only FLOWLITH_API_KEY environment variable; never expose it through public build variables, client bundles, browser storage, HTML, logs or error messages. The key authorizes one business. Never accept an API key or business ID from customer input.
Customer identity
Derive user_id on the server from the authenticated customer account, consistently across visits. For anonymous customers, issue an unpredictable server-generated ID in a signed, HttpOnly, Secure, SameSite cookie. Do not let a visitor choose another customer's ID. Clearing a guest cookie creates a new identity. Do not match users by display name. IDs must contain only letters, digits and . _ : @ + -; maximum 128 characters. The same business key and user_id resume the same chat. Other channels are not automatically linked. The business key alone does not authenticate an individual customer: your backend must enforce this.
Message identity and ordering
Create one UUID message_id for each new customer message. Persist the ID and exact request body before sending, scoped to the authenticated customer. Reuse both on every reconnect, including after page reloads, timeouts or lost streams. Never generate a new ID to force a retry. Deduplicate duplicate browser submissions on your backend. Allow only one unresolved message per customer; queue later messages locally until the previous one finishes.
Request
POST https://api.flowlith.com/v1/chat
Authorization: Bearer YOUR_BUSINESS_API_KEY
Content-Type: application/json
Accept: text/event-stream
{
"user_id": "customer-42",
"message_id": "3b1d7d08-3956-4acd-8698-2f1df5a23af1",
"text": "Hello"
}
Omit page_id and session_id: Flowlith derives the business and session from the key and user_id. Limit text to 2,000 characters before submission; longer text is currently truncated. Optional image_urls is an array of up to 3 HTTPS image URLs that Flowlith can fetch. Optional audio_urls is an array containing 1 HTTPS voice-note URL, up to 2 MiB for website chat. Audio formats: OGG/Opus, MP3, M4A/MP4, WAV, WebM or FLAC. Photos: JPEG, PNG, WebP or GIF, up to 4 MiB each. Keep the combined image payload small; sending three maximum-size images does not guarantee all three can be included. Use direct download URLs with the correct Content-Type; redirects are rejected. URLs must remain usable during preparation. Do not include passwords or access tokens in public media examples. Flowlith does not forward your business API key to media hosts. PDF/document attachments and file uploads are not supported by the Website API. Send text, images, audio, or a combination. Keep the total JSON body below 100,000 bytes. Use a fresh message UUID for a genuinely new message; the UUID above is only an example.
Streaming response
A valid request returns HTTP 200 with Content-Type: text/event-stream and keeps that single connection open. Parse SSE frames incrementally. The stream sends accepted first, optional keepalive comments while Iris works, then exactly one terminal reply or error event and closes. There is no polling endpoint and no 202 polling loop. These are final-answer events, not token deltas.
id: YOUR_MESSAGE_UUID
event: accepted
data: {"ok":true,"status":"processing","message_id":"YOUR_MESSAGE_UUID"}
id: YOUR_MESSAGE_UUID
event: reply
data: {"ok":true,"status":"sent","message_id":"YOUR_MESSAGE_UUID","reply":"Hello! How can I help?"}
The examples above show the fields your interface needs; events may also contain user_id and an opaque session_id. Treat those as response metadata, not authority to select another customer.
Only reply with status sent or deduplicated and a matching message_id is success. Render reply as text or sanitized Markdown, never unsanitized HTML. An error event contains error, message_id and retryable. Do not treat an ended stream without a terminal event as success.
Errors and retry policy
400 or 413: fix validation/body size; do not blindly retry. 401: missing, wrong or revoked key. Check your backend API key; stop automatic retries. 403: wrong business identifier. Omit page_id and check server credentials; stop retries. After accepted, runtime failures arrive as an SSE error event. If retryable is true, reconnect with the exact same message ID and payload after capped backoff. Never start a replacement message. agent_not_ready or brand_not_configured means the business agent needs Flowlith setup. credits_exhausted: the business is out of credits; stop retries until the owner tops up in Billing. transcription_not_configured or transcription_rejected: stop retries and contact Flowlith with the message ID. transcription_unavailable: retry the same message after backoff, as indicated by retryable. 429: throttled. Respect Retry-After (currently 60 seconds). Network failures or a stream ending without reply/error have an unknown outcome. Reconnect the same POST with the same message ID and payload using capped exponential backoff plus jitter. The server keeps each stream open for up to five minutes. Never show fabricated success. Preserve the pending message ID and exact body across process restarts; never resubmit it as new. Closing the local stream does not cancel processing. Contact Flowlith about repeated failures with message_id and timestamp, without the API key. Do not replay historical messages older than 24 hours through normal integration retries. Completed-message deduplication is retained for seven days; that is not a promise that an unresolved request is safe to replay for seven days. Keep your own completed-message records and escalate an old unresolved request instead of assigning it a new ID.
API limits
60 requests/minute per ingress IP before key lookup (chat and auth checks combined), then 60 chat connections/minute per business and 20 per customer, including reconnects. Apply your own authenticated-customer and guest abuse limits before forwarding requests. These API limits are not a substitute for your website’s abuse protection. Respect Retry-After when you receive 429. Limiter outages return 503, not unlimited access.
Response times vary by request. Replies use one SSE stream per message. Build the chat interface in your website; this API does not include a hosted widget. History retrieval, session deletion and cross-channel identity linking are not available through this API. Store the customer-visible transcript in your own application if you need a chat-history UI. Key rotation invalidates the previous key immediately; update your backend secret. History remains associated with business and customer identity, not the literal key value.
Integration checklist
- No key appears in browser source, requests to the browser, or logs.
- Reloading or reconnecting preserves the pending message ID and body.
- The backend consumes SSE incrementally and never polls for completion.
- Error events, 429 and network failures do not submit a new logical message.
- Two customers cannot request each other's identity or receive each other's reply.
- Sequential messages with the same customer ID retain conversational context.
- Output is escaped; loading, error and delayed states are visible and accessible.
- Test API responses and complete an end-to-end conversation before enabling customer traffic.