Skip to content
Noccela Developers Swagger UI SDK on GitHub Quickstart

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_in seconds. The decoded JWT also contains its issue and expiry times as Unix timestamps.
  • When a token has expired, the HTTP API answers 403 Forbidden and 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 refreshToken action 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