The REST API has one credential: a user access token from POST /auth/login. There is no refresh endpoint and no general-purpose API key, so a script signs in as a user and signs in again when the token stops working.
Sign in
curl -s https://api.cx.na6iq.com/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"integration@example.com","password":"your-password"}'{
"accessToken": "eyJhbGciOiJIUzI1NiJ9…",
"orgId": 12,
"userId": 34,
"email": "integration@example.com",
"tokenType": "Bearer",
"expiresInHours": 24
}| Field | Notes |
|---|---|
accessToken | A signed JWT. Send it on every call. |
orgId, userId | The organisation and user the token belongs to. Every call is scoped to that organisation. |
email | The signed-in address. |
tokenType | Always present. Always Bearer. |
expiresInHours | Always present. How long the token lives; the default is 24 hours. |
/auth/login needs no token. A failed sign-in answers 401 INVALID_CREDENTIALS (wrong email or password), 401 USER_INACTIVE (the user is deactivated), 403 ORG_SUSPENDED (the organisation is suspended), or 400 VALIDATION_FAILED (malformed body).
Send the token
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9…What a call may do depends on the roles of the user the token belongs to. A missing permission answers 403; see Roles and permissions.
Expiry and sign-in again
There is no refresh endpoint. When a call answers 401, the token has expired or was revoked: sign in again and retry once. A signed-out token answers SESSION_REVOKED; an expired one may come with no JSON body, so key on the status. Do not loop; a repeated 401 means the credentials, or the user, is no longer valid (a deactivated user's 401 carries the code USER_INACTIVE).
let token = null
async function natiq(path, init = {}) {
if (!token) token = await login()
let res = await send(path, init)
if (res.status === 401) {
token = await login() // sign in again, once
res = await send(path, init)
}
return res
}
const send = (path, init) =>
fetch(`https://api.cx.na6iq.com/api/v1${path}`, {
...init,
headers: { ...init.headers, Authorization: `Bearer ${token}` },
})import requests
class Natiq:
def __init__(self, base, email, password):
self.base, self.email, self.password, self.token = base, email, password, None
def login(self):
r = requests.post(f"{self.base}/auth/login",
json={"email": self.email, "password": self.password}, timeout=30)
r.raise_for_status()
self.token = r.json()["accessToken"]
def request(self, method, path, **kw):
if not self.token:
self.login()
for attempt in (1, 2):
r = requests.request(method, f"{self.base}{path}", timeout=30,
headers={"Authorization": f"Bearer {self.token}"}, **kw)
if r.status_code != 401 or attempt == 2:
return r
self.login()Sessions you create
Every sign-in is a session. The user can see their sessions and end them with GET /auth/sessions, DELETE /auth/sessions/{id} and DELETE /auth/sessions?others=true, and POST /auth/logout ends the one the token belongs to. Sign-ins also appear in the organisation's audit log. A script that signs in on every request will fill both, so keep one token until it returns 401.
Use a dedicated user
Create a user for each integration, give it a role holding only the permissions the integration needs, and keep its password in your secret store. Then you can deactivate it, or change its role, without touching anyone's own account.
Other credentials you may meet
These are not REST credentials. They are listed so you can tell them apart.
| Credential | Where you get it | What it is for |
|---|---|---|
| Webhook URL token and signing secret | A flow's webhook trigger | Starting a flow from your system. See Inbound triggers. |
| Widget key | Share tab of an agent; Accessibility page | Identifies a widget on your website. It is public. See Web Chat install. |
External bot Bearer token and Key | Connect → External bots | Your bot calling Natiq. See External agents. |
Organisation API key (X-Natiq-Api-Key) | POST /admin/api-keys | Accepted only by the bot webhook route /webhooks/channels/{type}/bots/{botId}, not by /api/v1. There is no dashboard screen for it today. |
The Integration token does not authenticate API calls
Organisation settings shows an Integration token (rotated with POST /org/integration-token/rotate, shown once). Its description calls it a server-to-server token, but the Natiq backend does not accept it on any REST route we could find. Do not build on it; sign in with a user instead. If you were told otherwise, check with support before relying on it.
Realtime
The WebSocket feed uses the same token. See Realtime overview.