Authentication
The Xibo CMS API is protected by OAuth 2.0.
Every request must carry a valid access_token in an Authorization header:
Authorization: Bearer <<access token>>This page covers how to register an application, obtain a token, refresh it, and scope it.
Quick start
If you're building a server-side integration and just want a token, this is the whole flow:
curl -X POST https://cms.example.org/api/authorize/access_token \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"Response:
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."
}Use it:
curl https://cms.example.org/api/display \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."The rest of this page explains where the credentials come from and what to do when the token expires.
Step 1: Register an Application
Before you can request a token, an Application must exist in the CMS.
Sign in to the CMS and go to Administration → Applications.
Select Add Application and give it a name. This name is shown to users on the authorisation screen, so make it recognisable.
Save, then edit the new Application to configure it.
The Application edit form controls everything about how your integration authenticates:
Client ID
Public identifier for your application. Safe to include in configuration files.
Client Secret
Password for your application. Treat it like a password — see Keeping credentials safe.
Confidential
Whether the application can keep a secret. Leave enabled for server-side integrations.
Authorisation Code / Client Credentials
Which grant types this application may use. Enable only what you need.
Redirect URIs
Required for the authorisation code grant. The CMS will only redirect to a URI listed here.
Scopes
Which parts of the API this application may reach. Defaults to all.
The Client Secret is generated when the Application is created and cannot be retrieved later in plain text. If you lose it, reset it from the Application edit form — this immediately invalidates any integration using the old value.
Step 2: Choose a grant type
Two grant types are supported. Pick based on whose data you're acting on.
grant_type value
client_credentials
authorization_code
Acts as
The user who owns the Application
The user who signs in and approves
Use for
Server-to-server integrations, scheduled jobs, middleware
Applications used by multiple CMS users, or where you must not hold user credentials
User interaction
None
Sign-in and consent in a browser
Refresh tokens
Not issued
Issued
Needs a redirect URI
No
Yes
The Applications page labels the authorisation code grant Authorisation Code, and older documentation referred to it as access_code. Neither is the value you send. The grant_type parameter must be exactly authorization_code, per the OAuth 2.0 specification.
Step 3: Obtain an access token
All token requests are POST to /api/authorize/access_token, with parameters in a form-encoded request body (application/x-www-form-urlencoded). They are not query string parameters.
Client credentials grant
A single request. There is no user to redirect and no consent screen.
The token acts as the CMS user who owns the Application. It can do everything that user can do, and nothing they cannot — API permissions are still subject to normal CMS user permissions and features.
Authorisation code grant
Three steps: send the user to the CMS, receive a code, exchange the code for a token.
1. Redirect the user to the authorisation endpoint
client_id
Yes
From the Application page.
response_type
Yes
Always code.
redirect_uri
Yes
Must exactly match one of the URIs registered against the Application.
scope
No
Space-delimited. Omit to receive all scopes configured for the Application.
state
Strongly recommended
Random per-request value. Verify it on return to protect against CSRF.
The user signs in if they aren't already, then sees an authorisation screen naming your application. If they approve, the CMS redirects to your redirect_uri.
2. Receive the authorisation code
Check that state matches the value you sent before going any further. If the user declines, you receive an error parameter instead of code.
3. Exchange the code for a token
Authorisation codes are valid for 10 minutes and may be used once.
Response:
Store the refresh_token securely alongside the user's record.
Refreshing a token
Access tokens last one hour. Rather than sending the user through the authorisation screen again, exchange the refresh token:
The response contains a new access token and a new refresh token. Replace the stored refresh token each time — the previous one is invalidated.
Client credentials integrations do not receive refresh tokens. Simply request a new token when the old one expires.
Step 4: Call the API
The API is served from /api on your CMS. Send the token as a Bearer credential on every request:
See OpenAPI for the full route reference, or Getting Started with Postman to explore interactively.
Token lifetimes
Access token
1 hour
Request a new one, or use a refresh token
Authorisation code
10 minutes, single use
Restart the authorisation flow
Refresh token
1 month
Rotated on every use
Cache your access token for its lifetime rather than requesting a new one per API call. Requesting a token on every call is wasteful and will trip rate limiting on busy systems.
Scopes
Scopes limit which API routes a token can reach. Each scope defines a set of route and method combinations; a request is allowed if any scope on the token permits that route and method.
The
allscope grants access to every route and is the default.Request specific scopes with a space-delimited
scopeparameter on the token request.If you request no scopes, the token receives every scope configured against the Application.
A token that reaches a route none of its scopes permit receives
403 Access to this route is denied for this scope.
Scopes are configured per Application under Administration → Applications. Grant the narrowest set your integration needs — a data-feed integration that only writes to a DataSet has no reason to be able to delete Displays.
Error responses
Token endpoint errors follow the OAuth 2.0 error format:
400
unsupported_grant_type
grant_type missing, misspelled, or sent as a query parameter instead of a form field
400
invalid_request
A required parameter is missing
400
invalid_grant
Authorisation code expired, already used, or redirect_uri doesn't match the one used to obtain it
400
invalid_scope
A requested scope isn't configured against the Application
401
invalid_client
Wrong client_id/client_secret, or the grant type isn't enabled for this Application
401
access_denied
Access token expired or malformed
403
—
Token is valid but its scopes don't permit this route
Keeping credentials safe
Always use HTTPS. A Bearer token in a request over plain HTTP is a credential in the clear. The CMS should not be exposed over HTTP in production.
Never embed a client secret in a browser or mobile application. Anything shipped to a device is public. Client credentials belong on a server you control.
A client credentials token inherits the Application owner's permissions. Create a dedicated CMS user for each integration, with only the permissions and features that integration needs, and own the Application from that user. Don't run integrations as a Super Admin out of convenience.
Store secrets outside your codebase — environment variables or a secrets manager, never source control.
Reset the secret if it may have leaked. Resetting takes effect immediately.
Review Applications periodically and delete ones no longer in use.
Troubleshooting
Last updated
Was this helpful?

