The model
Conversations belong to a customer’s workspace. Scope them with a customer-scoped key orX-LazyApp-Customer:
GET /v1/conversations/{conversation}/messages. Free-form replies only work inside the 24-hour window; outside it, send a template.
Prefer shipping the embedded inbox if you do not need a fully custom UI. Mint a short-lived
inbox token per page load.Webhooks write your inbox, not polling
The list endpoints are for backfill — not for discovering new messages. Subscribe once on your platform workspace; events for every customer arrive with acustomer envelope. Your tenant UIs read your database:
Handle these events:
Routing an event to the right tenant
Platform deliveries include the customer:customer.external_id in your database. One endpoint serves every tenant:
Node
Sending replies
Send withPOST /v1/messages scoped to the tenant. Quote the inbound message with context.message_id when you want a threaded reply.
429, back off with the same Idempotency-Key.
Polling is for backfill only
Two moments justify calling list endpoints:- Onboarding a tenant — after
customer.connected, page through conversations (and messages per thread) into your DB. - Reconciliation — a periodic sweep to catch anything a missed webhook left behind.
Checklist
- One webhook endpoint writes your inbox DB; ack fast, process async, dedupe by event
id - Route via
customer.external_id - Send replies through the API; trust webhooks for status
- Per-tenant queues for bursty sends; honour rate limits
- Poll only for onboarding backfill and reconciliation
- Consider the embedded inbox before rebuilding UI
Related
- Build a platform — customer model and webhook fan-out
- Tenant messaging — send path and idempotency
- Embedded components — drop-in inbox
- Webhooks — delivery and signatures
- Event reference — message and connection events