REST API
The Lane.Chat Open API is a small, stable REST surface for pulling conversations into your own tools, pushing agent replies programmatically, and managing your webhook subscription. It's the same API our n8n node is built on, and it's safe to build directly against for custom integrations.
Base URL
https://api.lane.chat/openapi/v1Every response is JSON with a real HTTP status code — 200 for success, 4xx for client errors, 5xx if something broke on our end. Successful bodies look like { "code": 0, "data": ... }; error bodies look like { "code": <status>, "message": "..." }.
Authentication
Every request needs an API key. Create one from the dashboard under Application Settings → API Keys — the plaintext key is shown once, at creation time, so save it somewhere safe. Keys look like lck_ followed by 48 hex characters. You can have up to 10 active keys per application; revoke old ones from the same screen. Treat a key like a password: store it server-side, never in client code or a mobile app.
Send the key in either header:
Authorization: Bearer lck_your_key_hereor
X-Api-Key: lck_your_key_hereIf the Authorization header is present and starts with Bearer , that value wins; X-Api-Key is the fallback for clients that can't set a custom Authorization scheme.
A key only ever sees data that belongs to its own application. There is no way to read or write another app's conversations with a valid key.
Rate limits
120 requests per minute, on a fixed one-minute window. The limit is keyed to your Authorization: Bearer header, so use Bearer as your canonical auth form — it gives you a predictable, per-key bucket. If you authenticate with X-Api-Key only, requests are rate-limited by source IP instead, which may be shared with other traffic behind the same NAT or proxy.
Every response carries the usual headers:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 113
X-RateLimit-Reset: 1754308860Going over the limit gets a 429 with a Retry-After header (seconds until the window resets). See Rate limits for backoff guidance.
Endpoints
Send a message
POST /messages — send a message into an existing conversation, as your agent/bot. This is the same delivery path as a human agent typing in the dashboard: it lands in the chat, gets broadcast to the visitor in real time, and shows up in the conversation history.
| Field | Type | Required | Notes |
|---|---|---|---|
chat_id | int | yes | Must belong to your application. |
content | string | yes | Non-empty after trimming. |
message_type | string | no | Defaults to text. |
Body may be JSON or application/x-www-form-urlencoded.
curl -X POST https://api.lane.chat/openapi/v1/messages \
-H "Authorization: Bearer lck_your_key_here" \
-d "chat_id=4821" \
-d "content=Thanks for reaching out — refund is on its way."{ "code": 0, "data": { "message_id": 918233 } }| Status | Message | When |
|---|---|---|
| 400 | chat_id and content are required | Missing chat_id, or content is empty. |
| 404 | Conversation not found | chat_id doesn't exist, or belongs to another app. |
| 500 | Failed to send | Delivery failed after validation passed. |
List conversations
GET /conversations — recent conversations for your application, newest activity first.
| Param | Type | Required | Notes |
|---|---|---|---|
status | string | no | Filter by status (e.g. open, closed). Omit for all. |
limit | int | no | Defaults to 20, clamped between 1 and 50. |
curl "https://api.lane.chat/openapi/v1/conversations?status=open&limit=10" \
-H "Authorization: Bearer lck_your_key_here"{
"code": 0,
"data": [
{
"id": 4821,
"client_id": 1290,
"status": "open",
"last_message_at": "2026-08-04T09:12:33.000000Z",
"created_at": "2026-08-01T14:02:11.000000Z"
}
]
}Get a conversation
GET /conversations/{id} — fetch a single conversation by ID.
curl https://api.lane.chat/openapi/v1/conversations/4821 \
-H "Authorization: Bearer lck_your_key_here"Returns the same shape as the list endpoint. Unknown IDs — including IDs that belong to another application — return a 404 with Conversation not found.
Read your webhook configuration
GET /webhook — your application's current webhook configuration.
curl https://api.lane.chat/openapi/v1/webhook \
-H "Authorization: Bearer lck_your_key_here"{
"code": 0,
"data": {
"url": "https://example.com/hooks/lane-chat",
"events": ["message.received", "chat.started"],
"enabled": true
}
}The webhook signing secret is intentionally not included in this response — it's only ever returned by PUT /webhook.
Update your webhook configuration
PUT /webhook — replace your application's webhook configuration.
Full replace, not a patch
Every field you omit is reset to its zero value — omitting url clears it and disables the webhook, and omitting events clears your subscriptions. There is no partial-update mode. If you only want to flip enabled off and back on, resend url and events on every call, or you will silently wipe your own configuration. Treat every PUT as "the whole config, from scratch."
| Field | Type | Required | Notes |
|---|---|---|---|
url | string | no* | Must be https:// and resolve to a public IP. Omitting or blanking it clears and disables the webhook. |
events | array | no | Event names to subscribe to (see Webhooks). Unknown names are silently dropped. Omitting it clears your subscriptions. |
enabled | boolean | no | Defaults to true. Forced to false if url is blank. |
* Not required by the request validator, but required in practice — this is how you set the webhook up in the first place.
curl -X PUT https://api.lane.chat/openapi/v1/webhook \
-H "Authorization: Bearer lck_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/lane-chat",
"events": ["message.received", "chat.started", "chat.ended"],
"enabled": true
}'{
"code": 0,
"data": {
"url": "https://example.com/hooks/lane-chat",
"events": ["message.received", "chat.started", "chat.ended"],
"enabled": true,
"secret": "whsec_66b5bec40c50f453df62655137e43788e21e48f6cd0fad30"
}
}secret is generated once, on first setup, and reused on every subsequent PUT — updating your URL or event list does not rotate it. Save it: it's how you verify the X-Webhook-Signature header on incoming deliveries. See Webhooks for the delivery format, signature verification code, and retry behavior.
url is validated against private, loopback, and link-local addresses (SSRF guard) both at configuration time and at delivery time.
Looking for in-app APIs?
- Controlling the web widget from your page — JavaScript SDK and the widget JavaScript API. No API key involved.
- Chat, identity, events, and push inside your mobile app — the native SDKs handle their own server communication; there is nothing to call directly.