# LaysanX Chat Widget API

This document covers the public widget runtime endpoints used by the LaysanX chat widget.

Base path:

```text
/widget
```

These endpoints are separate from `/api/v1`:
- they do not use the API access public/secret key pair
- they validate `clientId`, `widgetKey`, and allowed domain rules
- they are meant for embedded website chat experiences

## Endpoints

### Bootstrap Widget

```http
GET /widget/bootstrap?clientId=1001&widgetKey=widget_xxx&domain=www.example.com
```

Returns:
- widget title
- agent name
- greeting message
- input placeholder
- primary color
- position
- logo URL
- lead capture availability
- `poweredBy`

### Ask a Question

```http
POST /widget/ask
Content-Type: application/json
```

Request body:

```json
{
  "clientId": 1001,
  "widgetKey": "widget_xxx",
  "message": "What services do you offer?",
  "sessionId": "optional-session-id",
  "visitorId": "optional-visitor-id",
  "domain": "www.example.com"
}
```

Response includes:
- `sessionId`
- `answer`
- `usedAi`
- `leadCapture.required`
- `leadCapture.prompt`
- `sources`
- `branding.siteName`

The widget is conversational by default. A normal greeting such as `hi` should be answered from the knowledge base or general assistant behavior, not treated as an order/ticket lookup.

Internal status lookups are available when the message clearly asks for them:

- order status by order number, for example `ORD-1001-20260522224715159`
- support ticket status by ticket number, for example `LX-TKT-20260516-00002`

Example order status request:

```json
{
  "clientId": 1001,
  "widgetKey": "widget_xxx",
  "message": "Check order status ORD-1001-20260522224715159",
  "sessionId": "session-demo-001",
  "domain": "www.example.com"
}
```

Example ticket status request:

```json
{
  "clientId": 1001,
  "widgetKey": "widget_xxx",
  "message": "Share ticket status LX-TKT-20260516-00002",
  "sessionId": "session-demo-001",
  "domain": "www.example.com"
}
```

### Submit Lead from Widget

```http
POST /widget/lead
Content-Type: application/json
```

Request body:

```json
{
  "clientId": 1001,
  "widgetKey": "widget_xxx",
  "name": "John Doe",
  "email": "john@example.com",
  "mobile": "9999999999",
  "originalQuestion": "I need pricing details",
  "sessionId": "optional-session-id",
  "domain": "www.example.com"
}
```

Success response:

```json
{
  "success": true,
  "message": "Thanks. We have your details and our agent will reach out soon."
}
```

## Validation Notes

- the widget must exist for the supplied `clientId` and `widgetKey`
- the request domain must match the widget's configured `AllowedDomains`
- `/widget/lead` also requires an assigned form on the widget
- `/widget/ask` consumes AI allowance or wallet tokens when needed

## Related Admin Surfaces

- Client Admin > Chat Widget
- Client Admin > Chat Logs
- Client Admin > API Access
- Client Admin > Orders
- Client Admin > Helpdesk

## Recent Runtime Coverage

- Chat Widget admin saves API integrations, voice/settings fields, assigned forms, and agent configuration.
- Widget ask can answer from knowledge base, company profile fallback, configured external API integrations, internal order status lookup, and internal support ticket lookup.
- Ticket and order status lookups are intent-gated so ordinary conversation is not hijacked by status messages.
- Support tickets created by the hosted helpdesk can be queried by ticket number from the widget when the customer asks for ticket status.

## Related Documents

- [Frontend delivery API](./frontend-delivery-api.md)
- [Knowledge base + chat widget foundation](./knowledge-base-chat-widget-foundation.md)
