# Vixcell visitor chat API v1

Works with Flutter/Dart, React Native, Android, iOS and other HTTP clients. No OpenRouter key, account bearer token or Supabase key belongs in the customer app.

Base URL: `https://www.vixcell.com/cloud-engine/api/widget/public`

Configure the public installation key and enable mobile chat in Web App → Integrations → In-app chat. Set an application identifier. The key and app identifier are public installation values, not proof of a user's identity. Do not send private customer records or personal account data through visitor chat. Web origins are limited; native clients send no browser Origin header. For browser embedding use the hosted WebView/iframe URL or the website script.

All requests use `Content-Type: application/json`, no dashboard Authorization header and no cookies.

## 1. Open a visitor session

`POST /session`

```json
{"key":"YOUR_PUBLIC_WIDGET_KEY","mode":"mobile","app_id":"com.company.app"}
```

Successful response (200):

```json
{"token":"SHORT_LIVED_VISITOR_TOKEN","name":"Business name","greeting":"أهلًا بك، كيف أقدر أساعدك؟"}
```

The token expires after one hour. Keep it in memory; never put it into a URL. Each visitor gets their own session. Visitor tokens cannot access authenticated dashboard endpoints.

For a website visitor, the session payload is `{"key":"...","mode":"website","origin":"https://example.com"}`. Exact configured hostnames apply; www is separate. Origin restrictions reduce unwanted browser embedding; they do not turn a public installation key into a secret or authenticate non-browser clients.

## 2. Send a message

`POST /chat`

```json
{"key":"YOUR_PUBLIC_WIDGET_KEY","token":"SHORT_LIVED_VISITOR_TOKEN","message":"ما هي مواعيد العمل؟"}
```

Response: `{"reply":"..."}`. Render the reply as text, never unescaped HTML. A successful reply is stored atomically with the user's message. Requests are bounded to 2,000 characters; client timeout should be 55 seconds. Disable duplicate sends while one request is in progress. The server serializes requests for the same session.

## Limits and errors

Website and mobile share the widget subscription's monthly allowance (currently 1,500 reply attempts). Failed upstream attempts count toward this bound to prevent free-provider abuse. Creating sessions has a separate finite monthly budget. Both creation and replies are limited to 20 per IP per hour. Only OpenRouter free models are allowed; free-provider availability is not guaranteed.

Errors: 401 session expired, 403 integration/subscription unavailable, 404 invalid or disabled widget, 422 invalid payload, 429 quota/rate limit or busy session, 502/503 provider/database unavailable. Responses include `detail`, `code` and `request_id`. On 401 create a new session; on 429 do not retry automatically. On other failures keep the draft and let the visitor retry.

Replacing the public key invalidates old installations and visitor sessions. Disabling the widget or expiring its subscription stops new replies. There are no order creation, payments, external channel sends or background agent actions in this API.
