ArtyChat Developers
Webhooks
Receive signed, near real-time notifications when important activity happens in an ArtyChat business. Use webhooks to confirm API or MCP actions, synchronize CRMs, trigger automations, and keep external systems up to date.
Quick start
- Create an External API token with
webhooks:writeandwebhooks:read. - Register an HTTPS endpoint and choose the events you want.
- Copy the signing secret returned at creation. It is shown only once.
- Verify
X-ArtyChat-Signaturebefore processing each request. - Return any
2xxresponse within 15 seconds to acknowledge delivery.
curl -X POST https://artychat.com/api/v1/webhooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Production CRM",
"url": "https://example.com/webhooks/artychat",
"events": ["booking.created","booking.status_changed","customer.updated"]
}'
Supported events
Subscribe to individual events or use * to receive every supported event.
| Event | When it fires |
|---|---|
| booking.created | A booking is created from web, mobile, API, MCP, or another ArtyChat flow. |
| booking.updated | A booking record changes. |
| booking.status_changed | Booking status changes. |
| customer.created | A customer/contact is created. |
| customer.updated | A customer/contact changes. |
| order.created | A store order is created. |
| order.updated | A store order changes. |
| order.status_changed | Store order status changes. |
| pos.sale.created | A POS sale/order is created. |
| pos.sale.updated | A POS sale/order changes. |
| pos.sale.status_changed | POS status changes. |
| message.received / message.sent | Customer or business-side chat message activity. |
| conversation.created / conversation.updated | Conversation lifecycle and assignment/state changes. |
| invoice.created / invoice.updated / invoice.paid | Invoice and quote lifecycle, including payment completion. |
| payment.created / payment.completed / payment.failed | Payment lifecycle. |
| lead.created / lead.updated | CRM lead lifecycle. |
| form.submitted | A new public form submission is received. |
| task.created / task.completed | Task lifecycle. |
| campaign.started / campaign.completed | WhatsApp campaign lifecycle. |
| product.created / product.updated / product.low_stock | Catalog changes and low-stock notification (threshold 5). |
| webhook.test | Generated by the test-delivery endpoint. |
| expense.created | Expense lifecycle. |
| expense.updated | Expense lifecycle. |
| expense.deleted | Expense lifecycle. |
| delivery.created | Delivery creation, assignment, or lifecycle transition. |
| delivery.updated | Delivery creation, assignment, or lifecycle transition. |
| delivery.assigned | Delivery creation, assignment, or lifecycle transition. |
| delivery.accepted | Delivery creation, assignment, or lifecycle transition. |
| delivery.picked_up | Delivery creation, assignment, or lifecycle transition. |
| delivery.delivered / delivery.canceled | Delivery creation, assignment, or lifecycle transition. |
| delivery.status_changed | Delivery creation, assignment, or lifecycle transition. |
| dispatch.status_changed | Dispatch preparation status changes. |
Payload format
Expense events contain data.expense. Delivery events contain data.delivery and data.metadata; status_changed also includes previous_status and status. Delivery payloads omit internal proof storage paths. Delivery events are queued after the database transaction commits and also cover automatic handoff when a POS order becomes ready.
Each delivery has a stable event envelope. The resource-specific object is inside data.
{
"id": "4a1a2a92-0b3b-4df5-9cb4-b70934af52a1",
"type": "booking.status_changed",
"created_at": "2026-10-05T05:10:00.000000Z",
"business_id": 29,
"data": {
"booking": {
"id": 1234,
"status": "confirmed"
},
"previous_status": "pending",
"status": "confirmed"
}
}
X-ArtyChat-Event— event name.X-ArtyChat-Delivery— unique delivery UUID.X-ArtyChat-Timestamp— Unix timestamp used for signing.X-ArtyChat-Signature— HMAC-SHA256 signature inv1=...format.
Verify webhook signatures
Compute HMAC-SHA256 over timestamp + "." + raw_request_body with your endpoint signing secret. Compare the result using a constant-time comparison.
PHP
$body = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_ARTYCHAT_TIMESTAMP'] ?? '';
$received = $_SERVER['HTTP_X_ARTYCHAT_SIGNATURE'] ?? '';
$expected = 'v1=' . hash_hmac(
'sha256',
$timestamp . '.' . $body,
getenv('ARTYCHAT_WEBHOOK_SECRET')
);
if (!hash_equals($expected, $received)) {
http_response_code(401);
exit('Invalid signature');
}
http_response_code(200);
Node.js
const crypto = require("crypto");
const expected = "v1=" + crypto
.createHmac("sha256", process.env.ARTYCHAT_WEBHOOK_SECRET)
.update(timestamp + "." + rawBody)
.digest("hex");
if (!crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
)) {
return res.status(401).send("Invalid signature");
}
res.sendStatus(200);
Webhook management API
All paths are relative to https://artychat.com/api/v1.
| Method | Path | Scope | Purpose |
|---|---|---|---|
| GET | /webhooks/events | webhooks:read | List supported events |
| GET | /webhooks | webhooks:read | List endpoints |
| POST | /webhooks | webhooks:write | Create endpoint |
| PATCH | /webhooks/{id} | webhooks:write | Update endpoint/events |
| DELETE | /webhooks/{id} | webhooks:write | Delete endpoint |
| POST | /webhooks/{id}/rotate-secret | webhooks:write | Rotate signing secret |
| GET | /webhooks/{id}/deliveries | webhooks:read | Delivery history |
| POST | /webhooks/{id}/test | webhooks:write | Send test delivery |
| POST | /webhooks/{id}/deliveries/{delivery}/retry | webhooks:write | Retry a delivery |
Each business can create up to 20 webhook endpoints. Endpoint URLs must use HTTPS.
Acknowledgements and retries
- Any HTTP
2xxresponse acknowledges a delivery. - The endpoint has 15 seconds to respond.
- Failed deliveries are retried automatically up to 5 attempts.
- Retry delays increase progressively: approximately 1 minute, 5 minutes, 15 minutes, and 1 hour.
- Use
X-ArtyChat-Deliveryas an idempotency key. Your receiver should safely ignore duplicate delivery IDs.
Test an endpoint
curl -X POST https://artychat.com/api/v1/webhooks/1/test \
-H "Authorization: Bearer YOUR_API_KEY"
Test deliveries use event type webhook.test and the same signing mechanism as production events.
Security recommendations
- Always verify the HMAC signature against the raw request body before parsing or acting on the payload.
- Reject stale timestamps to reduce replay risk. A 5-minute tolerance is a common choice.
- Store signing secrets in a secret manager or environment variable.
- Rotate a signing secret immediately if you suspect it was exposed.
- Return quickly, then perform slow processing asynchronously in your own queue.
- Do not assume delivery order. Use event timestamps and resource IDs when sequencing matters.