Qubit API v1

Authentication

API keys, OAuth2 client credentials, scopes and rotation.

Two ways in, both server-to-server. Neither is meant for a browser or a mobile app: a credential in front-end code is a credential everyone has.

API keys

The simplest option. An administrator issues a key from the developer portal; it is shown once. Send it as a bearer token on every request:

Authorization: Bearer omni_live_<32 characters>

Keys look like omni_{live|test}_{32 characters}. Only the prefix and the last four characters are kept in the portal for display; the key itself is stored hashed, so if it is lost it is re-issued, not recovered.

A key carries every scope its application has. If your integration only ever sends messages, give the application only messages.send - a leaked key can then do only that.

OAuth2 client credentials

For systems that already manage tokens, or when you want short-lived credentials on the wire. Exchange a client id and secret for an access token that lasts an hour; request only the scopes this token needs.

Request
Try it - send it and see the response

This is a real request. A test key still acts on its workspace: a send goes out on the connection named in the body. Point it at your own number.

Response 200
{
    "access_token": "omni_at_...",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "messages.send messages.read"
}

Send the token as Authorization: Bearer <access_token>. When it expires you get 401 unauthenticated; request a new one - there is no refresh token, because client credentials are the refresh token. The secret is shown once, like a key.

The token endpoint is rate limited per IP (30 a minute). A legitimate client asks once an hour; cache the token.

Scopes

Every endpoint declares the scopes it accepts. A request without one of them is refused with 403 forbidden before anything is read - it costs nothing and reveals nothing.

ScopeAllows
messages.sendSend free-form messages inside the service window.
messages.readRead conversations and messages.
messages.statusRead the delivery status of messages you sent.
templates.readList message templates and their approval status.
templates.sendSend approved templates, including outside the service window.
contacts.readSearch and read contacts.
contacts.writeCreate and update contacts.
leads.createCreate leads for contacts.
leads.readRead leads.
webhooks.receiveRegister endpoints and receive signed deliveries.
events.sendSend business events that start automations.

Channel allow-list

Beside scopes, an application has a channel allow-list: the connections it may send through. GET /channels returns exactly those, and a send naming any other connection_id is refused with 403 forbidden. A message-only integration for the sales number cannot post from the support number.

Rotation and revocation

Every issue, rotation and revocation is in the workspace's audit log with who did it and from where.

Environments

omni_test_ credentials belong to a test application and can only use the channels the business marked as test. The API, the envelope and the webhooks are identical; only the key changes when you go live.

Base URL https://communication-api.artofluminaire.com Every response carries X-Request-ID; quote it when you write to support.