Connect Loonext to whatever else you run.
A small REST API and signed outbound webhooks, so your scheduling tool, your books, or a Zap can work with the same conversations your crew does. Keys are scoped, revocable, and can never do more than the person who created them.
Base path /public/v1. Create a key in Settings → API keys.
Authentication, and what a key can reach.
Send the key as Authorization: Bearer lnx_…. It is shown once, when it is created; we keep a hash and the first twelve characters, and there is no way to look it up afterwards.
A key acts as the person who created it, narrowed by the scopes they chose. That has two consequences worth designing around: a key never outlives its creator's access — if they leave the workspace, it stops working on the next request — and a key created by someone who cannot see a particular phone number cannot see its conversations either.
The whole surface.
Deliberately short. This is the set an integration actually needs, not our internal API with a second door.
GET /me
—
Which workspace this key reaches, and what it may do. Start here.
GET /contacts
contacts:read
The customer list, newest first.
POST /contacts
contacts:write
Add a customer. Re-sending one you already sent updates it rather than duplicating.
GET /conversations
conversations:read
The thread list.
GET /conversations/:id/messages
messages:read
One thread's messages.
POST /messages
messages:send
Send a text into an existing thread. Requires an Idempotency-Key header.
GET /tasks
tasks:read
The job list.
POST /tasks
tasks:write
Turn a message into a job.
POST /webhooks
webhooks:manage
Subscribe to events. This is the REST-hook endpoint Zapier and Make use.
DELETE /webhooks/:id
webhooks:manage
Unsubscribe. A key can only remove a subscription it created.
Webhooks, so you are not polling.
Point an https address at us and we post the moment something happens. Every delivery is signed with HMAC-SHA256 over timestamp.body, sent as Loonext-Signature: t=…,v1=…, and carries the delivery id so a retry is recognisably the same event. A failing address is retried 6 times with growing gaps, and one that keeps refusing is switched off so it stops costing you deliveries you are not receiving.
What v1 promises.
An API is a promise. Here is ours, so you can decide how much to build on it.
While v1 exists
- A field we publish will not be removed or change meaning. New fields may be added, so parse permissively — an unknown field is not an error.
- A route will not be removed, and its method and path will not change.
- An event name will not be removed or repurposed. New ones may be added; ignore names you do not know.
- The webhook signature scheme will not change under v1=. A v2= may appear beside it, and a receiver checking v1= keeps working.
- Error codes and their HTTP statuses will not change.
What we do not promise
- Ordering beyond what a route documents. Lists are newest-first; nothing else about order is stable.
- Rate limits. Today a key is allowed 60 requests a minute. Handle 429.
- Timing. Webhook delivery is best-effort with retries; nothing is synchronous with the event that caused it.
- Our first-party API. The app's own endpoints are not this API and change whenever the product does.
If we ever have to break something
A breaking change means a new version path — /public/v2 — served beside v1, never replacing it under a running integration. Every response already carries Loonext-Api-Version, so a client that pins nothing is still told what answered.
If v1 is ever retired, we announce it and then wait at least twelve months, emailing the workspaces whose keys are still calling it at six months and again at one. We know exactly who they are, because we record when each key was last used. Twelve months is chosen to be longer than the gap between an integrator finishing a job and being asked back — a policy measured in weeks is one that breaks somebody's business on a Tuesday.