API reference
The izipay livechat API lets you read conversations, reply as your team and receive events in real time. All requests use HTTPS and JSON. Timestamps are UTC in ISO 8601.
Base URL: https://chat.izipay.me/api/v1
Install the widget
Create a website in the dashboard and paste its snippet before the closing body tag. The widget loads asynchronously and only works on the domains you allow.
<script src="https://chat.izipay.me/w.js" data-key="YOUR_PUBLIC_KEY" async></script>
Authentication
The API and webhooks are available on the Pro plan; on Free, requests return 402 plan_required. Create a key in Dashboard, API and webhooks. Send it in the Authorization header. Keys give full access to your account data, so keep them on your server and never in browser code.
curl https://chat.izipay.me/api/v1/account \ -H "Authorization: Bearer lc_live_xxxxxxxx"
Errors and limits
Errors return a non 2xx status and a body like the one below. The limit is 300 requests per minute per account; above it you get 429.
{ "error": { "code": "not_found", "message": "Conversation not found." } }| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | Missing, invalid or revoked key |
| 404 | not_found | Object does not exist or belongs to another account |
| 422 | invalid_request | A field is missing or invalid |
| 429 | rate_limited | Too many requests, retry later |
Account
Returns your account and the AI credit balance.
{ "id": 12, "email": "you@company.com", "name": "Anna", "company": "Acme", "credits": 4870 }
Websites
{ "data": [ { "id": 3, "name": "Acme store", "public_key": "9f2c...", "allowed_domains": ["acme.com"], "ai_enabled": true, "ai_model": "claude-sonnet-5", "created_at": "2026-09-17T10:00:00Z" } ] }
Conversations
Newest first. Query parameters: site_id, status (ai, human, closed), limit (1 to 100, default 50), before_id for the next page.
{ "data": [ { "id": 881, "site_id": 3, "status": "human", "visitor_email": "client@mail.com", "country": "DE", "page_url": "https://acme.com/cart", "unread": 2, "created_at": "2026-09-17T10:04:11Z", "updated_at": "2026-09-17T10:06:52Z" } ], "has_more": true, "next_before_id": 881 }Status ai means the AI assistant is answering, human means your team handles it, closed means resolved. A new visitor message reopens a closed conversation.
Messages
Oldest first, up to 500. Pass after_id to get only new messages. Roles: visitor, agent (your team or API), ai, system.
Sends a reply to the visitor as your team. The AI assistant stops answering in this conversation once a team reply is sent.
curl -X POST https://chat.izipay.me/api/v1/conversations/881/messages \
-H "Authorization: Bearer lc_live_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"text": "Your parcel ships today.", "author": "Anna"}'{ "id": 10233, "role": "agent", "author": "Anna", "text": "Your parcel ships today.", "created_at": "2026-09-17T10:07:30Z" }
Close a conversation
Returns the updated conversation.
Webhooks
Add an https endpoint in the dashboard. We send a POST for each event and wait up to 4 seconds; answer with any 2xx status.
| Event | When |
|---|---|
| message.created | A visitor or a team member writes a message |
| conversation.handoff | The AI assistant transfers the conversation to your team |
{
"event": "message.created",
"created_at": "2026-09-17T10:06:52+00:00",
"data": { "conversation_id": 881, "site_id": 3, "message_id": 10231, "role": "visitor", "text": "Where is my order?" }
}
Verify signatures
Each request has the header X-Livechat-Signature: sha256=HEX, an HMAC SHA256 of the raw body with your webhook secret. Reject requests where it does not match.
<?php
$raw = file_get_contents("php://input");
$expected = "sha256=" . hash_hmac("sha256", $raw, getenv("LIVECHAT_WEBHOOK_SECRET"));
if (!hash_equals($expected, $_SERVER["HTTP_X_LIVECHAT_SIGNATURE"] ?? "")) {
http_response_code(401); exit;
}
$event = json_decode($raw, true);import hmac, hashlib
def verify(raw: bytes, header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, header)