Authentication
Noccela APIs use OAuth 2.0 client credentials: create an app, request a JWT access token, send it as a Bearer header or WebSocket message, refresh it in time.
Every Noccela API call is authenticated with an access token from the Noccela authorisation server. The flow is the standard OAuth 2.0 client-credentials grant: your application exchanges its client ID and secret for a short-lived JSON Web Token (JWT), and sends that token with its requests. No user login and no redirect are involved.
Apps and credentials
An app is one set of credentials. Customers and partners create apps in the partner portal, under Apps; the app’s details page shows its client ID and client secret. For evaluation, request sandbox credentials.
- Create one app per use case. The number of apps is not limited, so give your WMS connector, your dashboard and your test scripts separate credentials. You can then revoke one without touching the others.
- Grant only what the app needs. Permissions are given per site, and an app can hold all or only some of the permissions its owner has. Account-wide permissions cannot be set in the portal; contact Noccela if you need them.
- Rotate secrets. An app can have several client secrets. Create a new one, deploy it, then delete the old one.
Request a token
Send a form-encoded POST to the token endpoint with three parameters. JSON bodies are not accepted, and grant_type is mandatory.
POST /connect/token HTTP/1.1
Host: auth.noccela.io
Content-Type: application/x-www-form-urlencoded
client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=client_credentials
curl -s https://auth.noccela.io/connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "grant_type=client_credentials"
async function getToken() {
const response = await fetch('https://auth.noccela.io/connect/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
client_id: process.env.NCC_CLIENT_ID, // YOUR_CLIENT_ID
client_secret: process.env.NCC_CLIENT_SECRET, // YOUR_CLIENT_SECRET
grant_type: 'client_credentials',
}),
});
const body = await response.json();
if (!response.ok || body.error) throw new Error(`Authentication failed: ${body.error ?? response.status}`);
return { token: body.access_token, expiresAt: Date.now() + body.expires_in * 1000 };
}
The response is always JSON. Example:
{
"access_token": "eyJhbGciOi...",
"expires_in": 86400,
"token_type": "Bearer",
"scope": "global"
}
| Field | Meaning |
|---|---|
access_token |
The JWT to send with API requests |
expires_in |
Lifetime in seconds, counted from the moment the request was processed |
token_type |
Always Bearer |
scope |
Always global |
Errors follow the OAuth 2.0 format, for example {"error": "invalid_client"} for a wrong ID or secret.
Use the token
HTTP API and Push API administration. Send the token in the Authorization header:
GET /info HTTP/1.1
Host: api.noccela.io
Authorization: Bearer YOUR_ACCESS_TOKEN
GET /info is a good first call: it returns your app’s client ID and the sites it may access, with the permissions it holds on each.
Real-time API. Many WebSocket implementations cannot add headers to the upgrade request, so the token is not sent as a header. Instead, send the raw token as the first message after the connection opens. See the real-time API.
Expiry and refresh
- A token is valid for
expires_inseconds. The decoded JWT also contains its issue and expiry times as Unix timestamps. - When a token has expired, the HTTP API answers
403 Forbiddenand the real-time API closes the connection. - Requesting a new token at any time returns a fresh one with a new expiry; the old token stays valid until it expires.
- Refresh when less than half of the lifetime is left. On an open WebSocket, send the new token with the
refreshTokenaction instead of reconnecting.
Tokens are self-contained: the permissions are written inside the token. If you change an app’s permissions, existing tokens keep the old permissions until they expire, so a change can take up to 24 hours to apply everywhere. Request a new token to see it at once.
Permission levels
Permissions are granted per site. An app needs the permission that matches each API it uses.
| Permission | Allows |
|---|---|
SiteInformation |
Reading site data such as the layout |
SiteModifications |
Changing site data such as the layout and alert areas |
DeviceInformation |
Reading device data: model, type, location and state |
DeviceModifications |
Changing devices: tag names, LEDs and buzzers |
HistoricalData |
Querying history |
Designer |
Using the site designer in the partner portal |
EventApi |
Creating Push API endpoints and subscriptions |
RealTimeApi |
Connecting to the real-time WebSocket API |
InstallationTool |
Planning and calibrating base station positions |
Creating or removing whole sites needs a separate “all sites” permission for the account.
Keep secrets safe
If a secret may have leaked, create a new secret for the app, switch your services to it and delete the old one. The partner portal and the HTTP API (/integrations/secret and /integrations/deletesecret) both let you do this.
Last updated 22 October 2026