Command Centre REST API (2.0)

This document describes how you can use the Command Centre REST API to view and manage its configuration, user directory, events, and alarms.

Forward compatibility (HATEOAS)

This is a self-referencing REST API that follows the principles of HATEOAS. Other than the initial GET /api when it first connects, your source code should not contain any URLs, as they are subject to change. You should append the query parameters this document describes for operations such as filtering and searching, but everything in the path should come from the results of GET /api or pages linked from it.

GET /api only shows the API calls the server is licensed for.

Be prepared to append query parameters to URLs that already have their own: do not assume that you can simply add a question mark and your parameters.

Forward compatibility part two: undocumented features

Any behaviour that is not referenced in this documentation is subject to change. This includes routes, default values, field names, field values, request parameters, and HTTP verbs. Which is everything in a REST API so please take note:

  • If you discover a route or query parameter that is not documented here, a future version may change it.

  • Take all 2xx responses as success and all 4xx responses as failure. Example: a success could be 200 or 204 depending on whether it has something to tell you, and a negative result will change between the various 400s depending on the environment.

  • Treat item IDs as strings even though they currently look like small integers. We intend to change them.

  • Treat string identifiers as strings even if they look like GUIDs. If the documentation does not say they will always be a GUID, they may not.

  • Some routes work with a PATCH even though they should only accept a POST. One day, PATCHes to routes that do not have a PATCH in this document will start to fail.

  • Format all the timestamps you send as specified in the documentation. The parser we currently use is quite flexible so you may find that other formats such as "1/12/2025" and "12/1/2025" work today, but they may not tomorrow.

Versions

The body of this document clearly indicates when recent features arrived in the API so that readers with older versions of Command Centre know not to expect them. There is also a changelog.

API authentication

Clients authenticate by including a pre-shared API key in the Authorization header of each request. Command Centre generates a random API key when you create an endpoint for your clients to connect to. Search the Configuration Client online help for 'REST API' for how to do that.

In current versions of Command Centre, the API key will be in the format XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX with each X an uppercase hexadecimal digit. Future versions of Command Centre may use other formats of API key, so treat it as an opaque string. Tempting as it may be, do not interpret it as a GUID.

There are two ways you can pass the API key to the server in the Authorization header: following an authorisation method of GGL-API-KEY, or (in 9.0 and later) in the style of HTTP Basic authentication: prefixed with a colon, Base64-encoded, and following an authorisation method of Basic.

Examples:

Authorization: GGL-API-KEY C774-B01F-D695-AA4B-215F-A158-AC22-ADEB

Authorization: Basic OkM3NzQtQjAxRi1ENjk1LUFBNEItMjE1Ri1BMTU4LUFDMjItQURFQg==

Early versions of Command Centre allowed you to omit the 'GGL-API-KEY' from the first form. Future versions of Command Centre and all versions of the API gateway will reject you with a 401 if you do that. The API gateway is especially fussy about case and punctuation.

HTTP Basic authentication

The two example headers above are equivalent: prepending a colon to the API key beginning with C774 then encoding it into Base64 produces the 56 characters beginning with OkM3.

According to the HTTP Basic specification, the colon is a separator between a username and a password. In our case, the API key is the password and the username is unnecessary. If you place a username before the colon, before Base64-encoding it, Command Centre will ignore it and authenticate the connection based on the API key alone.

Pinning a client TLS certificate

Depending on Command Centre's site configuration, its REST API may also require a client certificate with each request. In versions up to and including 8.40 this was controlled by a flag labelled 'Do not require pinned client certificates' on the 'Web Services' tab of the server properties. In 8.50 that flag's label changed to 'Enable REST Clients with no client certificate', and its behaviour changed slightly when turned on.

If off, for all versions of CC, an incoming request's certificate has to match the thumbprint on its API key's REST Client item, and REST Client items with a blank thumbprint field do not work at all. This is how it ships, and it is the recommended way to run a production server.

If 'Do not require pinned client certificates' was turned on in versions up to and including 8.40, the server did not check any client certificates. If that flag is turned on in 8.50, now relabelled 'Enable REST Clients with no client certificate', it still does not check the client certificate if the thumbprint field of the matching REST Client item is blank, but if the Client item's thumbprint is not blank the server will reject connections with the wrong certificate.

Recent versions of CC automatically upgrade thumbprints to SHA384 when their clients next connect, if they are not there already.

See the Configuration Client help for instructions on where to enter REST Client thumbprints.

Source IP filtering

Also note that if IP filtering is enabled on the REST Client item in Command Centre, the API will only accept connections from the IP address ranges configured into that client item.

Symptoms of authentication failures

If a connection attempt fails, the server will return a 401 and raise an event containing its reason for refusing the request. If that happens too often, the server will stop reporting each offence and will instead create a summary alarm at a higher priority and lower rate. The details of the alarm tell you how many failed attempts there have been since the start of the flood. The server will stay in this mode of reduced reporting until several minutes pass without a failed connection attempt.

The current failure limit is ten errors inside one minute. After that you will receive one "a large volume of requests has been denied" alarm every minute while the failures continue. If five minutes pass without a failure, the server reverts to normal reporting.

The most common queries we receive from our integrators relate to their certificate handling. If your client's HTTP client library complains about certificates the first thing to check is Command Centre's alarm list. If there are 'invalid client certificate' alarms there, your client is not sending the certificate CC is expecting. If there are no alarms then the client is most likely rejecting the server's certificate.

Operator privileges

Some background on operators, operator groups, and divisions.

To determine your REST client's privileges, the server starts by searching the list of REST Client items in its configuration for the one with the API key in the Authorization header of your request. Assuming it finds one, it takes the cardholder from that REST Client item.

To be any use at all that cardholder must be a member of at least one operator group. Being in an operator group makes a cardholder an operator.

After the server has your operator, it needs to check whether that operator has access to the items or events in the request. To explain that, it is necessary to cover divisions.

Aside from some special items such as day categories, every item in Command Centre is in a division. Divisions are hierarchical, with all divisions (but the root) being a child of another. Multi-server installations have one division tree per server.

Every event and alarm has a division. It is usually the division of the source item, taken when the event arrives at the server. Card events or 'forced door' alarms, for example, typically use a door as a source item; when an operator modifies an item, the event recording that change uses that operator's workstation as the source item; the alarm that the server generates when you send a bad API key uses the server item as the source.

An event's division is not always its source's division. For example, 'Card activated' events have the server as a source item, but take on the cardholder's division so that operators who can see the cardholder can also see when the server activates their cards.

To link privileges to items and events, an operator group contains a list of privileges and a list of divisions. Its operators enjoy those privileges on all the items, events, and alarms that are in those divisions.

Having a privilege on a division also grants an operator that privilege on that division's descendants. Therefore an operator with a privilege on the root division has that privilege on all that server's items and events.

A common misconception is that the division an operator is in, or the division an operator group is in, have a bearing on the operator's privileges. They do not. It is all about the divisions in the operator group's 'Operator privileges' list.

If your privileges do not seem to be working

First, to protect Command Centre from accident and malice, you should strive to grant your REST clients the fewest and lowest-level privileges you can. Do not give them 'advanced user'. Reaching a point where you do not receive the results you want is a good thing: it means you have screwed things down a little too tightly.

If changing privileges in Command Centre does not seem to make any difference, remember to push the 'Refresh operator privileges' button in the properties window of your REST Client item.

Here are some general rules that may help if you are still not receiving the results you expect.

  • Receiving a 403 from a GET means the server may not have a licence for the retrieval you are attempting or your operator does not have the privilege to view that object. If it is a licensing problem, the body of the response will describe it.

  • Receiving a 403 from a PATCH, POST, or DELETE means your operator does not have the necessary privilege to perform that operation. You need one of the privileges beginning with 'Edit', 'Modify', or 'Create'.

  • Receiving a 404 when trying to get one item or event means it either does not exist or your operator does not have the privilege to view it.

  • Receiving a 200 and an empty result set from a search means you are licensed for that search but your operator could not see any items or events that matched. One possible cause is that your operator is not licensed to see any items or events of that kind. Make sure that one of the operator groups that your operator is in has a 'View' privilege such as 'View events' or 'View cardholders' - whatever is appropriate. If it does, and you have hit the button mentioned above, then check that the divisions on the operator group contain the items you expect. If it is events you are searching for, check the source item on those events either by using a REST operator with 'View events' on the root division or by looking at them in one of the thick clients.

Text encoding

Command Centre's REST API encodes all payloads using UTF-8, and expects clients to do the same. It does not escape special characters in response bodies except where required to embed them in JSON.

Specifically, it does not sanitise HTML, XML, or SQL. Your clients should expect to receive strings exactly as they were sent, even if they were sent by a hostile client. Write your clients to resist injection attacks.

Dates and times

When you send dates and times to Command Centre you must use an ISO-8601 calendar date, time, and time zone designator, with hyphens separating the date fields and colons separating the time fields. This looks like YYYY-MM-DDTHH:MM:SSZ, where T is an actual T, and Z is a timezone designator such as Z for UTC or -0800 for Pacific Standard Time. Specify up to seven decimals on the seconds if you wish, but be aware that Command Centre may not use all of them. You must supply the year and month but omit the other fields as you like. Command Centre will assume sensible defaults, such as the top of the minute when you omit seconds, midnight when you omit the time, or first of the month when you omit the day.

Do not omit the timezone designator. If you do, Command Centre will make an assumption.

Item status

Most items have a status, and the API presents status the same way for all of them, so this document covers it up front.

Starting by using access zones as an example. They can be in one of a few different modes, and have a zone count that rises and falls with cardholders arriving and leaving. Inputs and outputs can be on or off. Any item can be in an unknown state when the REST server is out of touch with its hardware. Et cetera.

The REST API can send an item's status to you in a string ready for human consumption in a UI, or as a list of flags more suitable for an integration. Neither of those fields are on an item's summary or details pages by default; to obtain them reliably you need to subscribe to updates.

Subscribing to status updates

The server does not always have an item's status: to prevent unnecessary work on the controller hardware, network, and server, it will stop requesting updates when nothing is subscribed to them. It is very important that items stay in touch with their controllers, and controllers with each other, but it is normal for controllers to limit what they send back to the server.

The server will be up to date when one of the following happened recently:

  • an operator had the item visible in one of the thick or API-based clients,
  • an application monitored the item via another API,
  • a REST client used the item in a status subscription, or
  • a REST client followed the item's updates link from its details page.

If it is not up to date and you request the status on an item's summary or details page, the server will report that the status is unknown.

To retrieve the status of one item you could GET the item's updates link from its details page, but be careful not to swamp the server with too many simultaneous connections. To monitor the status of many items you should use the status subscription API on the items controller (added in 8.30).

Whichever API you use, if the server does not have an item's status when you ask it will request an update from the item itself. For hardware items that may involve a conversation with another server, a hardware controller, and another piece of hardware on the end of a serial line. That all takes time, but the server answers you immediately, so the first response you receive may be 'unknown'. The status request continues in the background.

No matter what you receive, you should follow the next link in a loop until it gives you a status you are looking for, or another status indicating why it cannot. Your original request started a subscription, which every subsequent request refreshes, so while you stay in that loop the server will have the item's current status for you and all other callers.

The first status you will receive after 'unknown' will probably be 'controller unknown', which means that the controller (or other hardware) has received the server's request but does not yet have an answer, because of that serial line. You need something better, so stay in the loop.

Staying current

When you use the updates link on the item's details page it will return immediately. When you follow the next link in the page it returns, it will send back the status straight away if it changed since your previous call, or block until it does change. If nothing happens within a minute or so, it will return with no updates.

Whether you received an update or not, the body will contain a next link for you to follow for the next update.

State changes are not queued: the API only keeps the last, so it only takes one call to get yourself up to date with the server. Remember that the server itself may not have been up to date, and your making the call will have started it on its own little journey of discovery, which will cause more updates.

The 'Site' tab of the sample application shows this in operation.

For a user interface

The statusText field describes the state of the item in a multi-line string taken from the server's language pack. The natural state of a door, for example, is


Closed, locked, secure access.

A fence zone's status text could be


On - HV.
Voltage: 8.2 kV.
Seven day High Voltage min to max: 0.1kV to 9.8kV.
Pre-arm check while Alarm Zone is arming.

For one-line display, the status field is the same thing with spaces instead of line endings.

Neither of these is intended for integrations. By all means display them in a user interface (as Gallagher software does) but do not attempt to parse information out of them.

For an integration

The statusFlags field contains an array of string enumerations (flags) that describe the item's condition in a reliable and machine-readable way.

Each item type has a different set of flags. Some overlap (doors, inputs, and outputs can all be closed, for example) but most flags apply to only one kind of item. The common exceptions are the flags which indicate why the server cannot return the item's actual status, covered next.

Abnormal status

These are the status flags that indicate the server does not have the current status of the item:

  • unsaved and deleted are transient conditions you should not encounter in normal use. Either way, the item is in no condition to query.

  • unconfigured is very common while a site is being set up. It means the item does not have all the configuration it needs for normal operation. For example, an access zone is not configured until it has at least one door.

  • remoteServerOffline is only possible in a multi-server setup. It means that the item is remote (on a different server) and the server answering your REST query cannot reach it.

  • processOffline means the Controller service that is meant to be running on the Command Centre server, handling all the communications with hardware controllers, is not.

  • controllerOffline means the software on the server is as it should be but the hardware controller (such as a C7000) is offline. That could mean it needs its certificate revalidated, or just that its power or networking is out.

  • notPolled means the item is shunted: Command Centre is ignoring the item's communications at the request of an operator. Probably to stop spurious alarms.

  • deviceNotResponding means exactly that. It means the server is in contact with the hardware controller, but there is a problem between there and the item. Probably a cable fault, unless encryptionKeysTampered accompanies it.

Those are fault conditions. If you see one of those, there is a configuration or hardware fault or a shunt preventing the server communicating with the item.

They are in priority order: if you receive one near the bottom of the list you can take heart in the knowledge that your item is suffering none of the preceding abnormalities.

There are two more flags that are common to most item types.

  • unknown means everything else is in order but you caught the server in a period when it simply had no need to stay in touch with the item. You will get this on a summary or details page, because they do not subscribe to updates for the item. The updates link will not send you this status flag.

  • controllerUnknown is a transient state, hopefully. The updates call often returns it the first time if the server does not have the item's status already. It means a component (such as a hardware controller) between the server and your item is working on bringing in an update. This generally resolves quickly, so if you follow the next link you will receive the latest status.

The server will not send any other flags with one of those eleven, apart from the possible pairing of encryptionKeysTampered and deviceNotResponding, and some unusual combinations noted later.

Do not go looking for all of the abnormal status flags above and assume the best if they are not there. Gallagher may add more fault conditions in future versions of the API.

Instead, read each item's section under Operations for what its flags will be when it is online. A paragraph called "flag rules" shows how you can tell if the item is in a correct state. For the impatient: doors, inputs, and outputs will be open or closed, fence zones will be on or off, and alarm and access zones will be in one of four zone states.

Servers
https://127.0.0.1:8904