> For the complete documentation index, see [llms.txt](https://help.security.gallagher.com/knowledge-hub/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.security.gallagher.com/knowledge-hub/developer/rest-api/events.md).

# Events

Use the GET methods in this API for historical searches or to stay up to date with new events as they occur. Use the POST method (added in version 8.10) to create events of your own.

There are no PATCH actions on events, because they are immutable. If an event is also an alarm it carries some changeable state and a log of activity and comments, but the underlying event never changes.

The API only returns events that are still in Command Centre's database. It will not return events that have been removed, even if they are in an archive file.

### Location events in 9.00

Command Centre has about 80 event types that occur when somebody authenticates at a device, usually by badging a card. Some of those event types also contain the access zones that the person started and finished in. Version 9.00 introduced some improvements that presented the cardholder and the two zones to API clients in a consistent way:

* A new event type `hasLocation` that lets you filter for only those events that reveal a cardholder's location. If your server is 9.00 or better, use it in the `type` query parameter as you would normally use an integer event type: `type=hasLocation`. Gallagher will update this as new versions add more event types. Do not use it on 8.90 or earlier: those servers will reject it.
* A new `location` block on events of those types that contains fields containing the cardholder and their location.

For more on using these new features, see the relevant use case below (search for 'location').

### Event use cases

#### Downloading the entire event database

1. `GET /api`
2. Follow the link at `features.events.events.href` ↪. You can add query parameters to alter the search. If you are running 8.70 or later and there is a danger that you might encounter a problem while processing a batch of events you should also use `fields` to get the `next` link for each event. Note that this is different from the `next` link you receive at the end of each result set.
3. Process the events you receive in that call. If you asked for the `next` field, write the link for each event you successfully process to disk before attempting the next one. Then, if the worst happens, your client can read that link from disk and pick up where it left off.
4. If there were results, follow the link at `next.href` and repeat.

If you then wish to stay up to date, switch to following the link at `updates.href` ↪ in the results. That call will block until more events arrive, or a minute passes (approximately).

#### Downloading the most recent events

1. `GET /api`
2. Take the link at `features.events.events.href` ↪ and append `previous=true&top=20`. Add the appropriate query separator `?` or `&` first, depending on whether there is a query parameter in the URL already, and change the 20 as appropriate. The default is 1000, which is probably more than you want.
3. Process the events you receive in that call.
4. Follow the link at `previous.href` to get earlier events, or `next.href` or `updates.href` for later events. The last is a long poll, which means that if no events are ready when you make the call it will block until new events arrive.

#### Reporting on events over a period.

1. `GET /api`
2. Follow the link at `features.events.events.href` ↪ appending `after=2017-01-01Z&before=2017-02-01Z` or whatever timestamps are appropriate (after the correct query separator, `?` or `&`).

Remember that some remote systems take their time sending events to Command Centre, so do not be too hasty running your reports. If you fire them off at the stroke of midnight, you may miss events that occurred before midnight but have not yet arrived at Command Centre.

#### Receiving new events as they occur, starting from now

1. `GET /api`
2. Follow the link at `features.events.updates.href` ↪ adding query parameters containing your search terms. The call will block until at least one matching event arrives at the server.
3. Process the events you receive in that call. Often there is only one: the first that arrived after you made the call.
4. Sleep to reduce load on the server.
5. Loop, following the link at `updates.href` after processing each batch of events. It will return immediately if there are new events waiting, or it will block until new events arrive. Follow the advice in downloading the entire event database about keeping track of your position if you might encounter a problem writing events mid-batch. Note that that advises using the `next` field, but you will be using the `updates` field, which is the same thing in long-poll form.

#### Receiving new events as they occur, starting from now, with no long polls

1. `GET /api`
2. Follow the link at `features.events.events.href` ↪ and append `previous=true&top=1`. Add the appropriate query separator `?` or `&` first, depending on whether there is a query parameter in the URL already. The call will return one event (which you can ignore) and a `next` link you'll need later.
3. Sleep and loop, following the link at `next.href` after processing each batch of events. It will return immediately whether or not there are new events waiting. Follow the advice in downloading the entire event database about keeping track of your position if you might encounter a problem writing events mid-batch.

#### Receiving new events as they occur, starting in the past

1. `GET /api`
2. Follow the link at `features.events.events.href` ↪ appending the query parameter `after=2021-05-08Z` (or whatever timestamp is appropriate).
3. Process the events you receive in that call.
4. Sleep to reduce load on the server.
5. Loop, following the link at `updates.href` after processing each batch of events. It will return immediately if there are new events waiting, or it will block until new events arrive. Follow the advice in downloading the entire event database about keeping track of your position if you might encounter a problem writing events mid-batch. Note that that advises using the `next` field, but you will be using the `updates` field, which is the same thing in long-poll form.

#### Searching for events related to particular cardholders

1. `GET /api`
2. Follow the link at `features.items.items.href` ↪, adding `name="your_cardholder_name"&type=1` to the query after the appropriate separator (`?` or `&`).

   The 'items' controller necessary for that step is available with the RESTEvents licence. If you also have the RESTCardholders licence you could use the link at `features.cardholders.cardholders.href` ↪ instead, adding a separator and `name="your_cardholder_name"`.

   In either case, remove the quotes if you want a substring search and can handle more than one cardholder in the results.
3. Extract the item ID of your cardholder or cardholders from that page, repeating as necessary for additional cardholders.
4. Follow the link on the `/api` page at `features.events.events.href` ↪ appending the separator and `cardholder=XX` or `cardholder=XX,YY,ZZ` with the cardholders' IDs.

To further improve the efficiency of your search, filter by event types and a time range.

#### Searching for events that indicate location or movement

If your server is running 8.60 or earlier, use the search filter `type=20001,20002,20003,20047,20107,15582,15583,15800,15808,42415`. That is not a complete list of movement event types but it includes the popular ones.

If your server is running 8.70-8.90 inclusive, give your operator the 'View cardholder events' privilege instead of 'View events'. Then you can request all events, and the server will only send you movements because that is all your operator is permitted to see.

If your server is running 9.00 or later, the 'View cardholder events' privilege is still an excellent idea to limit your operator's vision but you can also use the search filter `type=hasLocation&fields=location` (with a leading `?` or `&` of course, and more fields if you need them). That will limit the results to location events.

When using a server at version 9.00 or better:

1. `GET /api`
2. Get the URL of the head of the event queue by following the link at `features.events.updates.href` ↪ appending `type=hasLocation&fields=location` with the appropriate query separator `?` or `&` depending on whether there is a query parameter in the URL already. The call will block until a new location event arrives.
3. If this is your first time here you will have an array containing one event. If you looped up from a later step, the array may contain many more. In any case, process all the events in the results using the advice immediately below about interpreting the `location` block. Also follow the advice in downloading the entire event database about keeping track of your position if you might have to abort mid-batch. Note that that advises using the `next` field, but if you want long polls you will be using the `updates` field.
4. Sleep for a short time to reduce load on the server.
5. Follow the link at `updates.href` for a long poll that waits for new events to arrive, or follow `next.href` for a call that will return immediately even if there are no new events for you.
6. Loop up to process the events you received.

Interpreting the `location` block:

* If you are simply after a person's location and do not care how they arrived there, use the `afterLocation` block inside `location`. The `canonicalTypeName` field in there will tell you what kind of location it is (reception or access zone). The schema definition describes `afterLocation` in more detail.
* If you are after movements, which happen when a door grants a person access or an operator moves them on a tag board or via the API, and happen to some types of visitors when their host moves, ignore all events except those that have a `location.type` of `moved`. Look at the `afterLocation` to see where they landed. There will also be a `beforeLocation` if the door had two zones configured on it, in case you're interested in where they came from. The `canonicalTypeName` field in both blocks will tell you what kinds of item they are.
* If you are after denials, which happen when a person authenticates but fails the access check, look at the events that have a `location.type` of `denied`. Like 'moved'-type events, `location.afterLocation` will show where they ended up. The difference is that with 'denied'-type events, they started there too.

Each of those fields is covered in the schema definition.

Be aware that the events you receive are limited to those with a source item that is in a division in which your operator has a privilege that allows viewing events. In 9.00 those privileges are 'View Events' and 'View Cardholder Events', and of course 'Advanced User'. That makes this API unsuitable for handling emergencies such as evacuations if your operator's view is limited: if your operator does not have the privilege to view events generated by a particular door, this API will not tell you about movements through that door.

#### Searching for events coming from other items

Events such as 'access granted' and 'zone count maximum' come from doors and access zones. To search for them, follow the same process as the previous use case (getting cardholder events) but use the `source` filter parameter instead of `cardholder`. It will limit the results to just those events that came from the items you gave in the query. If you have the RESTStatus licence you can search for access zones, alarm zones, fence zones, macros, outputs, doors, and (in 8.10) inputs. If you do not, or if your source is not one of those types, use the items API with a suitable `type` filter.

You can also use the `type` parameter to limit the events to particular event types. By doing this you can (for example) subscribe to 'access granted' events from a collection of doors.

New in v8.70, you can also filter by `relatedItem`. Use this to find events related to item or items regardless of the type.

#### Creating a new event

1. `GET /api`
2. POST to the link at `features.events.events.href` ↪

There are some rules around creating events, so you should first have a careful read of the POST documentation.

#### Listing all event types

1. `GET /api`
2. GET the link at `features.events.eventGroups` ↪

That will return all event types in their groups.

#### Event 'updates' versus 'next'

This expands on the difference between the API endpoints at the ends of the long poll `updates` and short poll `next` links that you receive in event searches. It will make more sense after reading the operations' own sections (long poll, short poll).

The two API calls use the same filters and return the same payloads, including the same pagination links. They differ at two times:

* On your first call, the short-polling 'events' route will return you the first events in the historical record that meet your search criteria but the long-polling 'updates' route will wait until new events arrive.
* On the last call, when there are no events that meet your criteria that the server has not sent you already, 'events' will immediately return an empty result set but 'updates' will wait for more to arrive.

The short poll is appropriate when you do not wish to stay up-to-date. When you are extracting events from the past, and want to move on to other things as soon as you have them all. Generating reports, basically.

The long poll is appropriate when you will be continuing to make the call, probably forever, because you wish to stay current and to not miss any events.

You should only be using one of the two. Using both in the same integration may indicate a design issue.

### Efficiency tips

* Use search parameters to reduce the filtering burden on the server.
* When downloading a significant number of events, leave `top` at 1000 or more, provided your client can handle results over a megabyte (events are around 1 KB each). Performance tests have shown that throughput decreases dramatically if `top` is too low.
* If using 8.40 or later, use its `field` query parameter to cut back on the fields the server sends to you. Not only will it save bandwidth, but it will save the server looking up all those values and serialising them for you.
* If you are using the `updates` link to keep up to date with events, sleep between calls for as long as your requirements allow. Doing that will improve the likelihood of your collecting more than one event when it is busy.\
  For example, if Command Centre is generating ten events per second and you do not sleep between REST calls, you will be calling `updates` ten times per second for one event each time. However if you sleep for two seconds after each call you will receive 20 events at a time, saving CPU and I/O.

### Event field specifiers

What you can do with the `fields` query parameter on an events method has improved through the versions, so explaining it is a topic in itself.

In 8.40 and later the values you can list are the same as the field names in the details page, plus the special value for a personal data field described below. You can pick whichever fields you want, including `defaults`, though we urge you to only list the fields you need. Anything you wrote for 8.30 or earlier will work in 8.40 as it did before.

In versions up to 8.30 you can only add fields to the event summary and details pages, not remove them. If you send the parameter it must start with `fields=defaults`. That gives you the default set. What you can add after that depends on the version of Command Centre you're calling.

In 8.10 and earlier the only field you can add is `cardholder.pdf_XXXX`, where XXXX is the ID of a PDF. Find that ID with a query to the PDFs controller. Don't forget a separating comma between it and `defaults`.

That will add a cardholder's PDF to the events that are related to them.

You can only pick one PDF. It will only appear on events that have a related cardholder, such as access events, because without a cardholder there is no PDF. The security model applies too, so it will only appear if your REST operator has the appropriate privileges on that cardholder and PDF.

In 8.20 and later you can also add `details`. Make sure you have a separating comma after `defaults` or `cardholder.pdf_XXXX`.

An event detail string can be kilobytes long so we left it optional. It is the only field in the details page that is not in the search results, by the way, so if you are running 8.20 or later you can add it to your search results and you will not need the details page.

| Server version  | Valid fields parameter values                                                                                 |
| --------------- | ------------------------------------------------------------------------------------------------------------- |
| Older than 8.20 | defaults,cardholder.pdf\_XXXX                                                                                 |
| 8.20 to 8.30    | <p>defaults,cardholder.pdf\_XXXX<br>or<br>defaults,details<br>or<br>defaults,cardholder.pdf\_XXXX,details</p> |
| 8.40 and later  | any                                                                                                           |

#### Per-event bookmarks

If you are running 8.70 or later and you put `previous`, `next`, or `updates` in the field list of an event search, the server will add those fields to each event. All server versions include links with those names at the end of results, but they are not useful if you crash out midway through processing a batch. The per-event links, only available in 8.70 and later and only on request, give you a place to pick up from without being re-sent the events you already processed.

### Licensing

* The GETs that collect alarms and events require the RESTEvents licence.
* The POST that creates events requires RESTCreateEvents.
* The GET to collect event types requires RESTEvents or RESTCreateEvents.

## Search events

> This returns the next batch of events matching the supplied filters starting\
> at the beginning of the database, or at the time specified by the\
> \`after\` parameter.\
> \
> For its correct use in various scenarios, see the \[use cases]\(#event-use-cases).\
> \
> By default the result will contain no more than 1000 events; for\
> efficient transfer of large numbers of events you should increase this\
> with the \`top\` parameter in the request URL.\
> \
> Each response will contain a \`next\` and an \`updates\` link.  Following\
> the \`next\` link will return the next batch of events, or an empty list\
> if there are no more available.  Following the \`updates\` link will also\
> return immediately if more events are available, but if there are none,\
> it becomes a long poll.  It will block until an event is available\
> that matches the specified filters, or a timeout passes.\
> \
> Do not code this URL into your application.  Take it from \`events.events.href\` in the\
> results of \`GET /api\`.<br>

```json
{"openapi":"3.2.0","info":{"title":"Command Centre REST API","version":"2.0"},"tags":[{"name":"Events","description":"Use the GET methods in this API for historical searches or to stay up to date with new events as\nthey occur.  Use the POST method (added in version 8.10) to create events of your own.\n\nThere are no PATCH actions on events, because they are immutable.  If an event is also an alarm\nit carries some changeable state and a log of activity and comments, but the underlying event\nnever changes.\n\nThe API only returns events that are still in Command Centre's database.  It will not return\nevents that have been removed, even if they are in an archive file.\n\n## Location events in 9.00\n\nCommand Centre has about 80 event types that occur when somebody authenticates at a device,\nusually by badging a card.  Some of those event types also contain the access zones that the\nperson started and finished in.  Version 9.00 introduced some improvements that presented the\ncardholder and the two zones to API clients in a consistent way:\n\n  * A new event type `hasLocation` that lets you filter for only those events that reveal a\n    cardholder's location.  If your server is 9.00 or better, use it in the `type` query\n    parameter as you would normally use an integer event type:  `type=hasLocation`.  Gallagher\n    will update this as new versions add more event types.  Do not use it on 8.90 or earlier:\n    those servers will reject it.\n\n  * A new `location` block on events of those types that contains fields containing the\n    cardholder and their location.\n\nFor more on using these new features, see the relevant use case below (search for 'location').\n\n## Event use cases\n\n### Downloading the entire event database\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events).  You\n   can add query parameters to alter the search.  If you are running 8.70 or later and there\n   is a danger that you might encounter a problem while processing a batch of events you should\n   also use `fields` to get the `next` link for each event.  Note that this is different from\n   the `next` link you receive at the end of each result set.\n3. Process the events you receive in that call.  If you asked for the `next` field, write the\n   link for each event you successfully process to disk before attempting the next one.  Then,\n   if the worst happens, your client can read that link from disk and pick up where it left off.\n4. If there were results, follow the link at `next.href` and repeat.\n\nIf you then wish to stay up to date, switch to following the link at `updates.href`\n[↪](events#get-api-events-updates) in the results.  That call will block until more\nevents arrive, or a minute passes (approximately).\n\n### Downloading the most recent events\n1. `GET /api`\n2. Take the link at `features.events.events.href` [↪](events#get-api-events) and\n   append `previous=true&top=20`.  Add the appropriate query separator `?` or `&` first,\n   depending on whether there is a query parameter in the URL already, and change the 20 as\n   appropriate.  The default is 1000, which is probably more than you want.\n3. Process the events you receive in that call.\n4. Follow the link at `previous.href` to get earlier events, or `next.href` or `updates.href`\n   for later events.  The last is a long poll, which means that if no events are ready when\n   you make the call it will block until new events arrive.\n\n### Reporting on events over a period.\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) appending\n   `after=2017-01-01Z&before=2017-02-01Z` or whatever timestamps are appropriate (after the\n   correct query separator, `?` or `&`).\n\nRemember that some remote systems take their time sending events to Command Centre, so\ndo not be too hasty running your reports.  If you fire them off at the stroke of\nmidnight, you may miss events that occurred before midnight but have not yet arrived\nat Command Centre.\n\n### Receiving new events as they occur, starting from now\n1. `GET /api`\n2. Follow the link at `features.events.updates.href`\n   [↪](events#get-api-events-updates) adding query parameters containing your search\n   terms.  The call will block until at least one matching event arrives at the server.\n3. Process the events you receive in that call.  Often there is only one:  the first that\n   arrived after you made the call.\n4. Sleep to reduce load on the server.\n5. Loop, following the link at `updates.href` after processing each batch of events.  It will\n   return immediately if there are new events waiting, or it will block until new events arrive.\n   Follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might encounter a problem writing events mid-batch.  Note that that advises using the `next`\n   field, but you will be using the `updates` field, which is the same thing in long-poll form.\n\n### Receiving new events as they occur, starting from now, with no long polls\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) and append\n   `previous=true&top=1`.  Add the appropriate query separator `?` or `&` first, depending on\n   whether there is a query parameter in the URL already.  The call will return one event (which\n   you can ignore) and a `next` link you'll need later.\n5. Sleep and loop, following the link at `next.href` after processing each batch of events.  It\n   will return immediately whether or not there are new events waiting.  Follow the advice in\n   [downloading the entire event database](#downloading-the-entire-event-database) about keeping\n   track of your position if you might encounter a problem writing events mid-batch.\n\n### Receiving new events as they occur, starting in the past\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) appending\n   the query parameter `after=2021-05-08Z` (or whatever timestamp is appropriate).\n3. Process the events you receive in that call.\n4. Sleep to reduce load on the server.\n5. Loop, following the link at `updates.href` after processing each batch of events.  It will\n   return immediately if there are new events waiting, or it will block until new events arrive.\n   Follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might encounter a problem writing events mid-batch.  Note that that advises using the `next`\n   field, but you will be using the `updates` field, which is the same thing in long-poll form.\n\n### Searching for events related to particular cardholders\n1. `GET /api`\n\n2. Follow the link at `features.items.items.href` [↪](items#get-api-items), adding\n   `name=\"your_cardholder_name\"&type=1` to the query after the appropriate separator (`?` or\n   `&`).\n\n   The 'items' controller necessary for that step is available with the RESTEvents licence.  If\n   you also have the RESTCardholders licence you could use the link at\n   `features.cardholders.cardholders.href` [↪](cardholders#get-api-cardholders)\n   instead, adding a separator and `name=\"your_cardholder_name\"`.\n\n   In either case, remove the quotes if you want a substring search and can handle more than\n   one cardholder in the results.\n   \n1. Extract the item ID of your cardholder or cardholders from that page, repeating as\n   necessary for additional cardholders.\n\n1. Follow the link on the `/api` page at `features.events.events.href`\n   [↪](events#get-api-events) appending the separator and `cardholder=XX` or\n   `cardholder=XX,YY,ZZ` with the cardholders' IDs.\n\nTo further improve the efficiency of your search, filter by event types and a time\nrange.\n\n### Searching for events that indicate location or movement\n\nIf your server is running 8.60 or earlier, use the search filter\n`type=20001,20002,20003,20047,20107,15582,15583,15800,15808,42415`.  That is not a complete list\nof movement event types but it includes the popular ones.\n\nIf your server is running 8.70-8.90 inclusive, give your operator the 'View cardholder events'\nprivilege instead of 'View events'.  Then you can request all events, and the server will only\nsend you movements because that is all your operator is permitted to see.\n\nIf your server is running 9.00 or later, the 'View cardholder events' privilege is still an\nexcellent idea to limit your operator's vision but you can also use the search filter\n`type=hasLocation&fields=location` (with a leading `?` or `&` of course, and more fields if you\nneed them).  That will limit the results to location events.\n\nWhen using a server at version 9.00 or better:\n\n1. `GET /api`\n\n2. Get the URL of the head of the event queue by following the link at\n   `features.events.updates.href` [↪](events#get-api-events-updates) appending\n   `type=hasLocation&fields=location` with the appropriate query separator `?` or `&` depending\n   on whether there is a query parameter in the URL already.  The call will block until a new\n   location event arrives.\n\n5. If this is your first time here you will have an array containing one event.  If you looped\n   up from a later step, the array may contain many more.  In any case, process all the events\n   in the results using the advice immediately below about interpreting the `location` block.\n   Also follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might have to abort mid-batch.  Note that that advises using the `next` field, but if you\n   want long polls you will be using the `updates` field.\n\n4. Sleep for a short time to reduce load on the server.\n\n5. Follow the link at `updates.href` for a long poll that waits for new events to arrive, or\n   follow `next.href` for a call that will return immediately even if there are no new events\n   for you.\n\n6. Loop up to process the events you received.\n\nInterpreting the `location` block:\n\n* If you are simply after a person's location and do not care how they arrived there, use the\n  `afterLocation` block inside `location`.  The `canonicalTypeName` field in there will tell you\n  what kind of location it is (reception or access zone).  The [schema\n  definition](models#eventdetail) describes `afterLocation` in more detail.\n\n* If you are after movements, which happen when a door grants a person access or an operator\n  moves them on a tag board or via the API, and happen to some types of visitors when their host\n  moves, ignore all events except those that have a `location.type` of `moved`.  Look at the\n  `afterLocation` to see where they landed.  There will also be a `beforeLocation` if the door\n  had two zones configured on it, in case you're interested in where they came from.  The\n  `canonicalTypeName` field in both blocks will tell you what kinds of item they are.\n\n* If you are after denials, which happen when a person authenticates but fails the access check,\n  look at the events that have a `location.type` of `denied`.  Like 'moved'-type events,\n  `location.afterLocation` will show where they ended up.  The difference is that with\n  'denied'-type events, they started there too.\n\nEach of those fields is covered in the [schema definition](models#eventdetail).\n\nBe aware that the events you receive are limited to those with a source item that is in a\ndivision in which your operator has a privilege that allows viewing events.  In 9.00 those\nprivileges are 'View Events' and 'View Cardholder Events', and of course 'Advanced User'.  That\nmakes this API unsuitable for handling emergencies such as evacuations if your operator's view\nis limited:  if your operator does not have the privilege to view events generated by a\nparticular door, this API will not tell you about movements through that door.\n\n### Searching for events coming from other items\n\nEvents such as 'access granted' and 'zone count maximum' come from doors and access zones.  To\nsearch for them, follow the same process as the previous use case (getting cardholder events)\nbut use the `source` filter parameter instead of `cardholder`.  It will limit the results to\njust those events that came from the items you gave in the query.  If you have the RESTStatus\nlicence you can search for access zones, alarm\nzones, fence zones, macros, outputs, doors, and (in 8.10) inputs.  If you do not, or if your\nsource is not one of those types, use the [items API](items) with a suitable `type` filter.\n\nYou can also use the `type` parameter to limit the events to particular event types.  By doing\nthis you can (for example) subscribe to 'access granted' events from a collection of doors.\n\nNew in v8.70, you can also filter by `relatedItem`. Use this to find events related\nto item or items regardless of the type.\n\n### Creating a new event\n\n1. `GET /api`\n2. POST to the link at `features.events.events.href` [↪](events#post-api-events)\n\nThere are some rules around creating events, so you should first have a careful read of the\n[POST documentation](events#post-api-events).\n\n### Listing all event types\n\n1. `GET /api`\n2. GET the link at `features.events.eventGroups` [↪](events#get-api-events-groups)\n\nThat will return all event types in their groups.\n\n### Event 'updates' versus 'next'\n\nThis expands on the difference between the API endpoints at the ends of the long poll `updates`\nand short poll `next` links that you receive in event searches.  It will make more sense after\nreading the operations' own sections ([long poll](events#get-api-events-updates), [short\npoll](events#get-api-events)).\n\nThe two API calls use the same filters and return the same payloads, including the same\npagination links.  They differ at two times:\n  \n  * On your first call, the short-polling 'events' route will return you the first events in the\n    historical record that meet your search criteria but the long-polling 'updates' route will\n    wait until new events arrive.\n\n  * On the last call, when there are no events that meet your criteria that the server has not\n    sent you already, 'events' will immediately return an empty result set but 'updates' will\n    wait for more to arrive.\n\nThe short poll is appropriate when you do not wish to stay up-to-date.  When you are extracting\nevents from the past, and want to move on to other things as soon as you have them all.\nGenerating reports, basically.\n\nThe long poll is appropriate when you will be continuing to make the call, probably forever,\nbecause you wish to stay current and to not miss any events.\n    \nYou should only be using one of the two.  Using both in the same integration may indicate a\ndesign issue.\n\n## Efficiency tips\n\n* Use search parameters to reduce the filtering burden on the server.\n\n* When downloading a significant number of events, leave `top` at 1000 or more,\n  provided your client can handle results over a megabyte (events are\n  around 1 KB each).  Performance tests have shown that throughput decreases\n  dramatically if `top` is too low.\n\n* If using 8.40 or later, use its `field` query parameter to cut back on the fields the server\n  sends to you.  Not only will it save bandwidth, but it will save the server looking up all\n  those values and serialising them for you.\n    \n* If you are using the `updates` link to keep up to date with events, sleep between calls for as\n  long as your requirements allow.  Doing that will improve the likelihood of your collecting\n  more than one event when it is busy.<br>For example, if Command Centre is generating ten\n  events per second and you do not sleep between REST calls, you will be calling `updates` ten\n  times per second for one event each time.  However if you sleep for two seconds after each\n  call you will receive 20 events at a time, saving CPU and I/O.\n\n## Event field specifiers\n\nWhat you can do with the `fields` query parameter on an events method has improved through the\nversions, so explaining it is a topic in itself.\n\nIn 8.40 and later the values you can list are the same as the field names in the [details\npage](models#eventdetail), plus the special value for a personal data field described\nbelow.  You can pick whichever fields you want, including `defaults`, though we urge you to\nonly list the fields you need.  Anything you wrote for 8.30 or earlier will\nwork in 8.40 as it did before.\n\nIn versions up to 8.30 you can only add fields to the event summary and details pages, not\nremove them.  If you send the parameter it must start with `fields=defaults`.  That gives you\nthe default set.  What you can add after that depends on the version of Command Centre you're\ncalling.\n\nIn 8.10 and earlier the only field you can add is `cardholder.pdf_XXXX`, where XXXX is the ID\nof a PDF.  Find that ID with a query to the [PDFs\ncontroller](pdf-definitions#get-api-personal_data_fields).  Don't forget a\nseparating comma between it and `defaults`.\n\nThat will add a cardholder's PDF to the events that are related to them.\n\nYou can only pick one PDF.  It will only appear on events that have a related cardholder, such\nas access events, because without a cardholder there is no PDF.  The security model applies\ntoo, so it will only appear if your REST operator has the appropriate privileges on that\ncardholder and PDF.\n\nIn 8.20 and later you can also add `details`.  Make sure you have a separating comma after\n`defaults` or `cardholder.pdf_XXXX`.\n\nAn event detail string can be kilobytes long so we left it optional.  It is the only field in\nthe details page that is not in the search results, by the way, so if you are running 8.20 or\nlater you can add it to your search results and you will not need the details page.\n\n| Server version | Valid fields parameter values\n| ------------ | --------------\n| Older than 8.20 | defaults,cardholder.pdf_XXXX \n| 8.20 to 8.30 | defaults,cardholder.pdf_XXXX<br>or<br>defaults,details<br>or<br>defaults,cardholder.pdf_XXXX,details\n| 8.40 and later | any\n\n### Per-event bookmarks\n\nIf you are running 8.70 or later and you put `previous`, `next`, or `updates` in the field\nlist of an event search, the server will add those fields to each event.  All server versions\ninclude links with those names at the end of results, but they are not useful if you crash out\nmidway through processing a batch.  The per-event links, only available in 8.70 and later\nand only on request, give you a place to pick up from without being re-sent the events you\nalready processed.\n\n## Licensing\n\n* The GETs that collect alarms and events require the RESTEvents licence.\n\n* The POST that creates events requires RESTCreateEvents.\n\n* The GET to collect event types requires RESTEvents or RESTCreateEvents.\n"}],"servers":[{"url":"https://127.0.0.1:8904"}],"security":[{"API_key":[]},{"basic":[]}],"components":{"securitySchemes":{"API_key":{"type":"apiKey","name":"Authorization","in":"header","description":"\nClients authenticate by including a pre-shared API key in the `Authorization` header of each\nrequest after an authorisation method of `GGL-API-KEY`:\n\n`Authorization: GGL-API-KEY C774-B01F-D695-AA4B-215F-A158-AC22-ADEB`\n\nFor a fuller description see [API authentication](api-authentication).\n"},"basic":{"type":"http","scheme":"basic","description":"This is HTTP Basic authentication using a blank username and the API key as the password.\n\nExample:  `Authorization: Basic OkM3NzQtQjAxRi1ENjk1LUFBNEItMjE1Ri1BMTU4LUFDMjItQURFQg==`\n\nThat example is equivalent to the example in the description of the api_Key method:\nprepending a colon to the API key beginning with `C774` then encoding it into Base64\nproduces the 56 characters beginning with `OkM3`.\n\nThe colon is a separator between a username, which is blank in our case, and the password,\nwhich is our API key.\n\nFor a fuller description see [API authentication](api-authentication)\n"}},"parameters":{"eventfields":{"name":"fields","description":"In 8.40 and later the values you can list are the same as the field names in the [details\npage](models#eventdetail), plus a special field name for a personal data field,\ndescribed next.  You can pick whichever fields you want, including `defaults` though we urge\nyou to avoid that and only ask for the fields you need.\n\nYou can request `cardholder.pdf_XXXX` where XXXX is the ID of a PDF, which you can discover\nwith a query to the [PDFs\ncontroller](pdf-definitions#get-api-personal_data_fields).  That will add a\ncardholder's PDF to the events that are related to them.\n\nYou can only pick one personal data field.  It will only appear on events that have a\nrelated cardholder, such as access events, because without a cardholder there is no personal\ndata.  The security model applies too, so it will only appear if your REST operator has the\nappropriate privileges on that cardholder and PDF.\n","in":"query","schema":{"type":"string","enum":["defaults","details","cardholder.pdf_*","href","id","serverDisplayName","time","message","occurrences","priority","alarm","operator","source","group","type","eventType","division","cardholder","entryAccessZone","exitAccessZone","door","accessGroup","card","modifiedItem","lastOccurrenceTime","previous","next","updates","location"]}}},"schemas":{"EventSearch":{"title":"Event search","description":"`/api/events` and `/api/events/updates` return this structure.","type":"object","properties":{"events":{"type":"array","description":"A list of event summaries.","items":{"$ref":"#/components/schemas/EventSummary"}},"previous":{"type":"object","description":"Follow this link to make a non-blocking call to collect the previous page of events (in\norder of arrival).  It will return an empty page if you have already received the first\nevent in the database.\n","properties":{"href":{"type":"string","format":"uri-reference"}}},"next":{"type":"object","description":"Follow this link to make a non-blocking call to collect the next page of events, moving\nforward in arrival time.  It will return an empty page if no more events are available.\n","properties":{"href":{"type":"string","format":"uri-reference"}}},"updates":{"type":"object","description":"This is a link to an [updates](events#get-api-events-updates) call.  Follow it to\nmake a blocking call to collect more events.  If there are none, the call will block until\none arrives or the call times out.  This link will contain your column select, pagination,\nand filtering parameters (`fields`, `top`, `after`, `before`, `source`, `type`, etc.) but it drops\n`deadline`.  You need to add that to each call.\n","properties":{"href":{"type":"string","format":"uri-reference"}}}}},"EventSummary":{"title":"Event summary","type":"object","description":"`/api/events` and `/api/events/updates` return an array of these, and `/api/events/{id}`\nreturns one with more fields.\n\nThe message and event type in this example indicate an operator attempting to log in with an\nincorrect password, but for the sake of illustration the example also contains references to\nitems that would never appear on such an event.  The card, cardholder, and access zones, for\nexample.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"A link to the details of this event, also usable as an identifier.  It is not globally\nunique but it is unique to the site and, barring a database restore, it will not be\nrecycled by another event or alarm.\n"},"id":{"type":"string","description":"An alphanumeric identifier for this event, unique to the site but not across sites.\nOnce allocated they are not re-used, except after totally resetting the server's state\nby restoring the database.\n"},"serverDisplayName":{"type":"string","description":"The host name of this event's origin server, if it was aggregated from a remote host.\nAbsent for local events.\n\nNote that this is not the descriptive name of the remote server's item, but the host name\nused for address resolution.\n\nNew to 8.40.\n"},"time":{"type":"string","format":"date-time","description":"The time the event occurred."},"message":{"type":"string","description":"The event's message."},"occurrences":{"type":"integer","description":"If an event arrives with the same essential properties as a previous event, the server\nwill start counting them.  Each event is still individually addressable and will appear in\nthe API as normal, but the first in the\ngroup will also have this property.  It only appears on the first, and it does not appear\nif the event is a singleton.\n\nIf present on an event's detail or alarm page, there will also be a `lastOccurrenceTime`.\n\nOutside of the `alarm` block, which contains an alarm's state, this is the only field on\nan event that can change.\n","minimum":2},"priority":{"type":"integer","description":"Numeric priority.  9 is critical and 0 is not an event.","minimum":0,"maximum":9},"alarm":{"type":"object","description":"If an event is also an alarm, this object will contain\nits state and a link to its details page in the alarms controller.\n\nOnly the first event in a group (see the `occurrences` field) can become an alarm.\n","properties":{"state":{"description":"Alarms start unacknowledged.  Acknowledging or processing them changes that.","type":"string","enum":["unacknowledged","acknowledged","processed"]},"href":{"type":"string","format":"uri-reference","description":"Link to the alarm entity corresponding to the event. GET the href for full alarm details."}}},"operator":{"description":"The href and name of the operator or system behind this event.  This will appear when an operator\nhas modified an item.  New in v8.00.\n\nThe item he or she modified will appear in the `modifiedItem` block (added in 8.40).\n\n***Change is coming.***\n\nThe operator may not be a cardholder.  A version of Command Centre after 9.30 will\nreturn events where the operator item is of a different kind.  In that case, the\n`operator` block will also contain a `canonicalTypeName` field telling you what kind of\nitem is at the other end of the href.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the operator who caused this event by editing an item.  New in 8.00."},"name":{"type":"string","description":"The name the operator held at the time.  New in 8.40."}}},"source":{"type":"object","description":"ID and name of the source of the event, as recorded at the time of the event.","properties":{"id":{"type":"string","description":"The alphanumeric ID of the event source item.  Search for events with the same source\nas this one with `source=321` in the query parameters.\n"},"name":{"type":"string","description":"This could be different from the current name of the source item."},"href":{"type":"string","format":"uri-reference","description":"Link to the source item.  New in 8.00."}}},"group":{"type":"object","description":"ID and name of the event group this event belongs to.  Do not confuse this with an access\ngroup or operator group:  this is the event type group to which the event's type belongs.\nThere are about 150 and you can list them at\n[/events/groups](events#get-api-events-groups).\n","properties":{"id":{"type":"string","description":"The alphanumeric ID of the event group.  Search for events of the same rough category\nas this one with `type=35` in the query parameters.\n"},"name":{"type":"string","description":"The name of the event group."}}},"type":{"type":"object","description":"ID and name of the event's type.  There is a long list of them at\n[/events/groups](events#get-api-events-groups).\n","properties":{"id":{"type":"string","description":"The alphanumeric ID of the event type.  To search for events of the same type as this\nexample, put `type=23035` in the query parameters of\n[/events](events#get-api-events).\n"},"name":{"type":"string","description":"The name of the event type."}}},"eventType":{"description":"ID and name of the event's or alarm's type.  There is a long list of them at\n[/events/groups](events#get-api-events-groups).\n\nUnlike the `type` field, this has the same format in an event as it does in an alarm.\n\nAdded in 8.90.  Because it is a new field, it does not appear by default.  Ask for it using\nthe `fields` parameter.\n","type":"object"},"division":{"type":"object","description":"ID, name, and href of the event's division (which is the division of the event's source\nitem, for most event types).\n","properties":{"id":{"type":"string","description":"The alphanumeric ID of the event's division.  Search for other events from items in\nthe same division as this example by putting `division=2` in the query parameters.\n"},"href":{"type":"string","format":"uri-reference","description":"The link to the division item."},"name":{"type":"string","description":"The division's name.  Added in 8.40."}}},"cardholder":{"type":"object","description":"Summary information about an event's cardholder, if there is one.  This will be the\ncardholder who badged their card at a door in an access event, or the cardholder an\noperator modified in an operator event.  Search for other events related to this example's\ncardholder with `cardholder=325` in the query parameters.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the cardholder entity representing the cardholder of the event.  GET the href\nfor full details.\n"},"id":{"type":"string","description":"The alphanumeric ID of the cardholder associated with this event."},"name":{"type":"string","description":"In versions up to and including 8.10 this is the current name of the cardholder.  In\n8.20 it is the name of the cardholder at the time of the event.\n"},"firstName":{"type":"string","description":"The current value of the firstName field of this cardholder.  Added in 8.20."},"lastName":{"type":"string","description":"The current value of the lastName field of this cardholder.  Added in 8.20."}}},"entryAccessZone":{"description":"The name and href of the entry access zone related to the event.  In the case of card\nevents, it is the zone into which a cardholder was attempting to gain access.\n\nThat is true for successful entries, successful exits, and access denials.  Regardless of\nwhether the cardholder badged at the entry or exit reader, this field refers to the zone\nthat he or she attempted to access.\n\nFor example, for 'Card entry granted' events this field will contain the door's entry\nzone, but for 'Card exit granted' events this field will contain the door's _exit_ zone,\nbecause 'exit granted' means the cardholder was in the door's entry zone, badged at its\nexit reader, and was granted access to its exit zone.  Think of it as going through a door\nin its reverse direction.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the access zone entity representing the entry access zone related to this\nevent.  GET the href for the access zone's full details.  This will be missing if the\nserver lacks the RESTStatus licence, or your operator lacks the necessary privileges\n(such as 'View Site').\n"},"name":{"type":"string","description":"The current name of the access zone.  Expect a future version of Command Centre to\nchange this to the name of the access zone at the time of the event.\n"},"id":{"type":"string","description":"Deprecated."}}},"exitAccessZone":{"description":"The name and href of the exit access zone related to the event.  In card events, it is the\nzone from which a cardholder was attempting to leave, if the door had an exit zone\nconfigured (many do not).\n\nThat is true for successful entries, successful exits, and access denials.  Regardless of\nwhether the cardholder badged at the entry or exit reader, this field refers to the zone\nthat he or she attempted to leave.\n\nFor example, for 'Card entry granted' events this field will contain the door's exit zone,\nif there was one, but for 'Card exit granted' events this field will contain the door's\n_entry_ zone.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the access zone entity representing the exit access zone related to this\nevent.  This will be missing if the server lacks the RESTStatus licence, or your\noperator lacks the necessary privileges (such as 'View Site').\n"},"name":{"type":"string","description":"The current name of the exit access zone.  Expect a future version of Command Centre\nto change this to the name of the exit access zone at the time of the event.\n"},"id":{"type":"string","description":"Deprecated."}}},"door":{"description":"The name and href of the door related to the event.  These are not as common as you may\nthink, because when a door is relevant (to card events, for example) it is usually the\nevent's source, not its door, so it will be in the `source` block.\n\nNew in 8.10.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the entity representing the door related to this event.  This will be missing\nif the server lacks the RESTStatus licence, or your operator lacks the necessary\nprivileges (such as 'View Site').\n"},"name":{"type":"string","description":"The name the door had when the event occurred."}}},"accessGroup":{"description":"The href of the access group that a cardholder just gained or lost in a 'Membership\nActivated' or 'Membership Expired' event.  Those happen when a group membership's 'from'\nor 'until' time passes.\n\nDEPRECATED for the events generated when an operator creates, modifies, or deletes an\naccess group.  Use the 'modifiedItem' field instead (new in 8.40).\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the access group related to this event."}}},"card":{"description":"Details of the card associated with the event.\n\nVersions prior to 8.60 returned this block and a card number of zero for all access\nevents, even if they did not involve a credential (after a person entered their user code\nat a keypad, for example).  Version 8.60 does not return this block for such events.\n","type":"object","properties":{"facilityCode":{"type":"string","description":"The card's facility code at the time of the event expressed as one letter followed by\nup to five digits.\n"},"number":{"type":"string","description":"The card's number at the time of the event.  Despite the name it may not necessarily\nbe an actual number; mobile card numbers are arbitrary strings, for example.\n\nNote that card numbers are not guaranteed unique.  The combination of facility code,\nissue level, and card number will be unique for card types that have a facility code\nand issue level.\n\nBefore 8.60 this number was a signed 32-bit integer, so numeric card numbers greater\nthan 2^31 came out negative and mobile card numbers were arbitrary.  In 8.60 numeric\ncard numbers are positive and mobile card numbers are their ID strings, which\noperators can set to anything, and default to GUIDs.\n"},"issueLevel":{"type":"integer","description":"The issue level of the card at the time.\n"}}},"modifiedItem":{"description":"The href and type of the item that an operator created, changed, or deleted, for those\nkinds of events.\n\nNew in 8.40.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the item that this event modified.  Watch for 404s:  this link will be here\neven for deleted items.\n"},"type":{"type":"object","properties":{"id":{"type":"string","description":"A short alphanum identifying the item's type.\n"},"name":{"type":"string","description":"A human-readable name of the item's type, suitable for display.\n\nThis string is translated using the installation's language pack, and Gallagher\nreserves the right to change item type names in new versions, so you should not do\nanything with this string except show it to a person.\n"}}}}},"next":{"description":"The URL to the search that will return the page of events following this one.  It will\ninclude your search filters and pagination parameters.\n\nThis link is intended for integrations that take great gulps of events and send them to a\ndownstream system.  If it suffers a problem in the middle of a result set, it needs to\nrecord where in the event trail it got up to so that when it restarts it will not miss or\nduplicate events.\n\nNew to 8.70.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference"}}},"previous":{"description":"The URL to the search that will return the page of events preceding this one.  It will\ninclude your search filters and pagination parameters.\n\nThe `previous` link on the first event in a result set will be the same as the `previous`\nlink outside the results, since they both indicate the latest event that preceded the\nresult set.\n\nNew to 8.70.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference"}}},"updates":{"description":"The URL to the [updates](events#get-api-events-updates) call that will return the\npage of events following this one, or wait for one to arrive if there are none.  It will\ninclude your search filters and pagination parameters.\n\nNew to 8.70.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference"}}}}}}},"paths":{"/api/events":{"get":{"tags":["Events"],"summary":"Search events","description":"This returns the next batch of events matching the supplied filters starting\nat the beginning of the database, or at the time specified by the\n`after` parameter.\n\nFor its correct use in various scenarios, see the [use cases](#event-use-cases).\n\nBy default the result will contain no more than 1000 events; for\nefficient transfer of large numbers of events you should increase this\nwith the `top` parameter in the request URL.\n\nEach response will contain a `next` and an `updates` link.  Following\nthe `next` link will return the next batch of events, or an empty list\nif there are no more available.  Following the `updates` link will also\nreturn immediately if more events are available, but if there are none,\nit becomes a long poll.  It will block until an event is available\nthat matches the specified filters, or a timeout passes.\n\nDo not code this URL into your application.  Take it from `events.events.href` in the\nresults of `GET /api`.\n","parameters":[{"name":"top","in":"query","description":"Sets the maximum number of events to return per page.","schema":{"maximum":10000,"minimum":1,"type":"integer","default":1000}},{"name":"after","in":"query","schema":{"type":"string","format":"date-time"},"description":"Restricts events to those that occurred at or after this time.\n\nThe server accepts extended ISO-8601 time stamp formats.  There must be hyphen separators\nin the date and colons in the time, and a `T` separating the two.\n\nFor predictable results you should also add a timezone specifier.  A `Z` means UTC and is\nrecommended, but `+hh`, `+hhmm`, and `+hh:mm` also work.  Note that you need to encode\nplus-signs as `%2b` in a URL.\n\nIf you omit the time, the server will assume midnight.  If you omit just the seconds, the\nserver will take it to the top of the minute, `:00`.\n"},{"name":"before","in":"query","schema":{"type":"string","format":"date-time"},"description":"Restricts events to those that occurred before this time.  Events that occurred at this\nexact time (to the second) will not appear in the results.  For example, to collect all\nevents that occurred on 1 January 2017, use `after=2017-01-01Z&before=2017-01-02Z`.  You\nwill not receive any events from 2 January.\n\nThe `after` parameter (above) describes the time stamp formats that the server accepts.\n"},{"name":"source","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"}},"description":"Restricts events to those whose source item has this ID.  Separate multiple IDs with\ncommas.  Use the [items API](items) to search Command Centre's items.\n"},{"name":"type","in":"query","required":false,"explode":false,"schema":{"type":"array","items":{"type":"string"}},"description":"Restricts events to those whose type is in this list.  Separate multiple IDs with commas.\n\nThe results may include other event types if you also use the `group` parameter\nbecause the `type` and `group` fields are combined as an 'OR', not an 'AND'.\n\nUse the [event groups call](events#get-api-events-groups) to see all event types.\nThe IDs you need for this query parameter are strings but look like small integers.  That\ncall shows the event types along with the groups they are in, so do not confuse event\ntypes with event groups.  They are separated in the results of the API call, but as a\ngeneral rule you can tell them apart by their integer value:  event group IDs are in the\nhundreds, while most event type IDs are in the thousands.\n\nIn version 9.00 and later use the special value `hasLocation` to include all event types\nthat can reveal a cardholder's location or access zone.  In 9.00 it is a set of about 80\nevent types; it may be more in future versions.  If you use `hasLocation` you probably\nalso want to ask for the `location` block using the `fields` query parameter.\n\nDo not send `type=hasLocation` to a server running 8.90 or earlier:  it will reject it.\n"},{"name":"group","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"}},"explode":false,"description":"Restricts events to those with this event group ID.  Separate multiple IDs with commas.\n\n`group` is ORed with `type`.  In fact it is shorthand for `type=` followed by the IDs of\nall the event types in the event type groups you list, and the search uses the union of\nthe two lists.\n\nUse the [event groups call](events#get-api-events-groups) to see all event types and\ngroups.\n"},{"name":"cardholder","in":"query","required":false,"schema":{"type":"string"},"explode":false,"description":"Restricts events to those associated with the cardholder that has this Command Centre ID.\nSeparate multiple IDs with commas.\n"},{"name":"division","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"}},"explode":false,"description":"Restricts events to those in these divisions or their descendants.  Separate IDs with\ncommas.\n\nA more secure option for limiting your client's visibility is to set the operator's\nprivileges so that it only has access to those divisions.\n"},{"name":"directDivision","in":"query","required":false,"schema":{"type":"string"},"description":"Restricts events to those whose division is in this list.  Unlike `division=`, it does not\nfollow ancestry.  The name `directDivision` is case-sensitive.  Separate IDs with\ncommas.\n\nExample:  `directDivision=2,101`.\"\n"},{"name":"relatedItem","in":"query","required":false,"schema":{"type":"string"},"description":"Restrict events to those associated with the item that has this Command Centre\nID. Separate multiple IDs with commas.\n\nExample: `relatedItem=3,102`\n"},{"$ref":"#/components/parameters/eventfields"},{"name":"previous","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Returns the newest events rather than the oldest.  Without this option the API will return\nevents starting from the epoch, but if you set it to `true` the server will return the\nmost recent events, the last of which will be the latest to arrive at the server.\n\nIn both cases you can move backward and forward in arrival time with the 'next' and\n'previous' links.\n"},{"name":"pos","in":"query","required":false,"schema":{"type":"integer","minimum":0},"description":"INTERNAL USE ONLY.  This is how Command Centre tracks the events you have seen already.\nDo not set it yourself.  Retain the 'next' or 'updates' link in your application instead.\n"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventSearch"}}}},"403":{"description":"The site does not have a RESTEvents licence."}}}}}}
```

## Add an event

> Use this method to create an event in Command Centre v8.10 or later.\
> \
> Do not code this URL into your application.  Take it from \`events.events.href\` in the\
> results of \`GET /api\`.\
> \
> Each field has particular rules and has its own effects on the event and subsequent reports,\
> and misconfiguration (such as inadvertently causing a macro to run itself) can land you in\
> real trouble, so have a good look at the documentation below and the example \[POST\
> body]\(models#eventpostbody).\
> \
> Events are immutable:  you cannot PATCH or DELETE them after you create them.\
> \
> \## Usable event types\
> \
> You must supply an \[event type]\(events#get-api-events-groups).  At the time of writing\
> (9.50), CC ships with 30 event types you can use, each in its own event type group.  The\
> POST body schema definition linked above shows which event types you can use:  they have\
> 'external' in their name.\
> \
> You can create 970 of your own event types using the External Event Type Configuration\
> Utility, a separate Windows application that lets you create external event types and make\
> them appear on items' Event Response and Alarm Instructions tabs in the Configuration\
> Client.  You will find the release note for that utility in the Documentation folder on the\
> installation media.\
> \
> 1000 event types sounds like a lot, but be aware that you cannot delete event types, and the\
> only thing you can modify on an existing event type is its name.  Their event type group and\
> item types are permanent once you save them from the utility.  Please plan carefully, and\
> take backups!\
> \
> \## A note on event type groups\
> \
> There is much confusion between event types and groups.\
> \
> You do not specify a type \_group\_ when creating a new event.  You specify a type.  The parts\
> of Command Centre that work with the event later will look up what group the event type is\
> in, principally to select an action plan to run, but you do not need to consider groups when\
> creating the event.\
> \
> \## Usable source items\
> \
> Every event needs a source item.  You can let the server pick one for you (it will use the\
> REST Client item identified by your API key) or you can use any item that has an 'Event\
> Response' tab in its Configuration Client window (which is most of them).  Our existing\
> integrations use items like doors, external system items, and cameras.\
> \
> If you allow the server to default to your REST client item as the source, or if you specify it\
> yourself, your operator must have 'Create events and alarms' in at least one division for\
> the call to succeed.  Any division will do.  Otherwise you'll receive a 403.\
> \
> If you specify a source item to a server running 8.90 or later and that item is not your\
> REST Client item, your operator must have the 'Create events and alarms' privilege in that\
> item's division.  In older versions it was enough for your operator to have that privilege\
> in any division.\
> \
> Cardholders cannot be event sources because they do not have an 'Event Response' tab, but...\
> \
> \## Related items\
> \
> Along with a source, you can link other items to the events you create.  If you link a\
> cardholder, for example, your events will show on an activity report generated for that\
> cardholder.  To link an item your operator must have a privilege that allows viewing it\
> ('View cardholders' for cardholders or 'View site' for most other item types).\
> \
> \## Action plans\
> \
> An event can fire an action plan, which will\
> \* set the priority if the REST client did not set one in the body of the POST, and\
> \* run a macro on the server.\
> \
> Macros are extremely powerful, and a thorough treatment requires more room than we have, so\
> it is sufficient to say that you should not aim for a dramatic first test.  A good first\
> result is to turn on a virtual output made for the purpose.  Just make sure that it will not\
> trigger another macro because it is possible to create loops, causing havoc.\
> \
> You do not pick an action plan to run when you POST your event.  Command Centre does that in\
> three steps:\
> &#x20; \
> &#x20; 1\. The server looks at the configuration of the source item in the Event Response tab of\
> &#x20;    its property page in the Configuration Client.  If there is an entry for the event type\
> &#x20;    that is not "use default", Command Centre will fire that action plan and skip the next\
> &#x20;    steps.  In versions older than 8.30 the control is per event group, not per event.\
> &#x20; 2\. Since the server did not find an action plan on the item, it tries its alarm zone.\
> &#x20;    Specifically, the Event Defaults tab of the alarm zone's property page in the\
> &#x20;    Configuration Client.  Again the control is per event group not per event type in older\
> &#x20;    versions.  If the event's action plan is not 'use default', the server fires that\
> &#x20;    action plan and goes no further.\
> &#x20; 3\. Since the server did not find an action plan on the item or its alarm zone, it looks at\
> &#x20;    the configuration in the Event Defaults tab of the server properties.  There is always\
> &#x20;    an action plan there, even if it does nothing more than set the priority of the event.\
> \
> Once it has found the action plan to run, the server will assign the event its priority (if\
> you did not specify a priority yourself) and run the macro if there is one, both from the 'Command\
> Centre' tab of the action plan's property page in the Configuration Client.  The server will\
> not use the configuration from the other tabs.\
> \
> It is not possible to submit an event with priority zero, but it is possible to submit an\
> event with no priority, and have the action plan assign it priority zero.  This will run the\
> macro on the action plan then drop the event before it reaches the database.\
> \
> \## Alarm instructions\
> \
> Alarm instructions are marked-up text fields that Command Centre presents to security\
> personnel when events occur.  Picking an alarm instruction to use follows the same decision\
> path as picking an action plan:  Command Centre looks at the configuration of the source\
> item first, and finding nothing there will turn to the source item's alarm zone, and finally\
> to the server properties.  If all three are unset the operator will not receive any special\
> instructions.\
> \
> So, what an operator sees when your event arrives on their board depends on the priority and\
> the event source.\
> \
> \## When events become alarms\
> \
> After the server has established an event's priority, either from the body you POSTed or the\
> action plan, it looks at the Event Priorities tab of the server properties.  There is a\
> slider there that sets the level above which an event becomes an alarm.  By default it is\
> set to two, meaning that any event with a priority of two or higher will appear as an alarm.<br>

```json
{"openapi":"3.2.0","info":{"title":"Command Centre REST API","version":"2.0"},"tags":[{"name":"Events","description":"Use the GET methods in this API for historical searches or to stay up to date with new events as\nthey occur.  Use the POST method (added in version 8.10) to create events of your own.\n\nThere are no PATCH actions on events, because they are immutable.  If an event is also an alarm\nit carries some changeable state and a log of activity and comments, but the underlying event\nnever changes.\n\nThe API only returns events that are still in Command Centre's database.  It will not return\nevents that have been removed, even if they are in an archive file.\n\n## Location events in 9.00\n\nCommand Centre has about 80 event types that occur when somebody authenticates at a device,\nusually by badging a card.  Some of those event types also contain the access zones that the\nperson started and finished in.  Version 9.00 introduced some improvements that presented the\ncardholder and the two zones to API clients in a consistent way:\n\n  * A new event type `hasLocation` that lets you filter for only those events that reveal a\n    cardholder's location.  If your server is 9.00 or better, use it in the `type` query\n    parameter as you would normally use an integer event type:  `type=hasLocation`.  Gallagher\n    will update this as new versions add more event types.  Do not use it on 8.90 or earlier:\n    those servers will reject it.\n\n  * A new `location` block on events of those types that contains fields containing the\n    cardholder and their location.\n\nFor more on using these new features, see the relevant use case below (search for 'location').\n\n## Event use cases\n\n### Downloading the entire event database\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events).  You\n   can add query parameters to alter the search.  If you are running 8.70 or later and there\n   is a danger that you might encounter a problem while processing a batch of events you should\n   also use `fields` to get the `next` link for each event.  Note that this is different from\n   the `next` link you receive at the end of each result set.\n3. Process the events you receive in that call.  If you asked for the `next` field, write the\n   link for each event you successfully process to disk before attempting the next one.  Then,\n   if the worst happens, your client can read that link from disk and pick up where it left off.\n4. If there were results, follow the link at `next.href` and repeat.\n\nIf you then wish to stay up to date, switch to following the link at `updates.href`\n[↪](events#get-api-events-updates) in the results.  That call will block until more\nevents arrive, or a minute passes (approximately).\n\n### Downloading the most recent events\n1. `GET /api`\n2. Take the link at `features.events.events.href` [↪](events#get-api-events) and\n   append `previous=true&top=20`.  Add the appropriate query separator `?` or `&` first,\n   depending on whether there is a query parameter in the URL already, and change the 20 as\n   appropriate.  The default is 1000, which is probably more than you want.\n3. Process the events you receive in that call.\n4. Follow the link at `previous.href` to get earlier events, or `next.href` or `updates.href`\n   for later events.  The last is a long poll, which means that if no events are ready when\n   you make the call it will block until new events arrive.\n\n### Reporting on events over a period.\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) appending\n   `after=2017-01-01Z&before=2017-02-01Z` or whatever timestamps are appropriate (after the\n   correct query separator, `?` or `&`).\n\nRemember that some remote systems take their time sending events to Command Centre, so\ndo not be too hasty running your reports.  If you fire them off at the stroke of\nmidnight, you may miss events that occurred before midnight but have not yet arrived\nat Command Centre.\n\n### Receiving new events as they occur, starting from now\n1. `GET /api`\n2. Follow the link at `features.events.updates.href`\n   [↪](events#get-api-events-updates) adding query parameters containing your search\n   terms.  The call will block until at least one matching event arrives at the server.\n3. Process the events you receive in that call.  Often there is only one:  the first that\n   arrived after you made the call.\n4. Sleep to reduce load on the server.\n5. Loop, following the link at `updates.href` after processing each batch of events.  It will\n   return immediately if there are new events waiting, or it will block until new events arrive.\n   Follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might encounter a problem writing events mid-batch.  Note that that advises using the `next`\n   field, but you will be using the `updates` field, which is the same thing in long-poll form.\n\n### Receiving new events as they occur, starting from now, with no long polls\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) and append\n   `previous=true&top=1`.  Add the appropriate query separator `?` or `&` first, depending on\n   whether there is a query parameter in the URL already.  The call will return one event (which\n   you can ignore) and a `next` link you'll need later.\n5. Sleep and loop, following the link at `next.href` after processing each batch of events.  It\n   will return immediately whether or not there are new events waiting.  Follow the advice in\n   [downloading the entire event database](#downloading-the-entire-event-database) about keeping\n   track of your position if you might encounter a problem writing events mid-batch.\n\n### Receiving new events as they occur, starting in the past\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) appending\n   the query parameter `after=2021-05-08Z` (or whatever timestamp is appropriate).\n3. Process the events you receive in that call.\n4. Sleep to reduce load on the server.\n5. Loop, following the link at `updates.href` after processing each batch of events.  It will\n   return immediately if there are new events waiting, or it will block until new events arrive.\n   Follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might encounter a problem writing events mid-batch.  Note that that advises using the `next`\n   field, but you will be using the `updates` field, which is the same thing in long-poll form.\n\n### Searching for events related to particular cardholders\n1. `GET /api`\n\n2. Follow the link at `features.items.items.href` [↪](items#get-api-items), adding\n   `name=\"your_cardholder_name\"&type=1` to the query after the appropriate separator (`?` or\n   `&`).\n\n   The 'items' controller necessary for that step is available with the RESTEvents licence.  If\n   you also have the RESTCardholders licence you could use the link at\n   `features.cardholders.cardholders.href` [↪](cardholders#get-api-cardholders)\n   instead, adding a separator and `name=\"your_cardholder_name\"`.\n\n   In either case, remove the quotes if you want a substring search and can handle more than\n   one cardholder in the results.\n   \n1. Extract the item ID of your cardholder or cardholders from that page, repeating as\n   necessary for additional cardholders.\n\n1. Follow the link on the `/api` page at `features.events.events.href`\n   [↪](events#get-api-events) appending the separator and `cardholder=XX` or\n   `cardholder=XX,YY,ZZ` with the cardholders' IDs.\n\nTo further improve the efficiency of your search, filter by event types and a time\nrange.\n\n### Searching for events that indicate location or movement\n\nIf your server is running 8.60 or earlier, use the search filter\n`type=20001,20002,20003,20047,20107,15582,15583,15800,15808,42415`.  That is not a complete list\nof movement event types but it includes the popular ones.\n\nIf your server is running 8.70-8.90 inclusive, give your operator the 'View cardholder events'\nprivilege instead of 'View events'.  Then you can request all events, and the server will only\nsend you movements because that is all your operator is permitted to see.\n\nIf your server is running 9.00 or later, the 'View cardholder events' privilege is still an\nexcellent idea to limit your operator's vision but you can also use the search filter\n`type=hasLocation&fields=location` (with a leading `?` or `&` of course, and more fields if you\nneed them).  That will limit the results to location events.\n\nWhen using a server at version 9.00 or better:\n\n1. `GET /api`\n\n2. Get the URL of the head of the event queue by following the link at\n   `features.events.updates.href` [↪](events#get-api-events-updates) appending\n   `type=hasLocation&fields=location` with the appropriate query separator `?` or `&` depending\n   on whether there is a query parameter in the URL already.  The call will block until a new\n   location event arrives.\n\n5. If this is your first time here you will have an array containing one event.  If you looped\n   up from a later step, the array may contain many more.  In any case, process all the events\n   in the results using the advice immediately below about interpreting the `location` block.\n   Also follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might have to abort mid-batch.  Note that that advises using the `next` field, but if you\n   want long polls you will be using the `updates` field.\n\n4. Sleep for a short time to reduce load on the server.\n\n5. Follow the link at `updates.href` for a long poll that waits for new events to arrive, or\n   follow `next.href` for a call that will return immediately even if there are no new events\n   for you.\n\n6. Loop up to process the events you received.\n\nInterpreting the `location` block:\n\n* If you are simply after a person's location and do not care how they arrived there, use the\n  `afterLocation` block inside `location`.  The `canonicalTypeName` field in there will tell you\n  what kind of location it is (reception or access zone).  The [schema\n  definition](models#eventdetail) describes `afterLocation` in more detail.\n\n* If you are after movements, which happen when a door grants a person access or an operator\n  moves them on a tag board or via the API, and happen to some types of visitors when their host\n  moves, ignore all events except those that have a `location.type` of `moved`.  Look at the\n  `afterLocation` to see where they landed.  There will also be a `beforeLocation` if the door\n  had two zones configured on it, in case you're interested in where they came from.  The\n  `canonicalTypeName` field in both blocks will tell you what kinds of item they are.\n\n* If you are after denials, which happen when a person authenticates but fails the access check,\n  look at the events that have a `location.type` of `denied`.  Like 'moved'-type events,\n  `location.afterLocation` will show where they ended up.  The difference is that with\n  'denied'-type events, they started there too.\n\nEach of those fields is covered in the [schema definition](models#eventdetail).\n\nBe aware that the events you receive are limited to those with a source item that is in a\ndivision in which your operator has a privilege that allows viewing events.  In 9.00 those\nprivileges are 'View Events' and 'View Cardholder Events', and of course 'Advanced User'.  That\nmakes this API unsuitable for handling emergencies such as evacuations if your operator's view\nis limited:  if your operator does not have the privilege to view events generated by a\nparticular door, this API will not tell you about movements through that door.\n\n### Searching for events coming from other items\n\nEvents such as 'access granted' and 'zone count maximum' come from doors and access zones.  To\nsearch for them, follow the same process as the previous use case (getting cardholder events)\nbut use the `source` filter parameter instead of `cardholder`.  It will limit the results to\njust those events that came from the items you gave in the query.  If you have the RESTStatus\nlicence you can search for access zones, alarm\nzones, fence zones, macros, outputs, doors, and (in 8.10) inputs.  If you do not, or if your\nsource is not one of those types, use the [items API](items) with a suitable `type` filter.\n\nYou can also use the `type` parameter to limit the events to particular event types.  By doing\nthis you can (for example) subscribe to 'access granted' events from a collection of doors.\n\nNew in v8.70, you can also filter by `relatedItem`. Use this to find events related\nto item or items regardless of the type.\n\n### Creating a new event\n\n1. `GET /api`\n2. POST to the link at `features.events.events.href` [↪](events#post-api-events)\n\nThere are some rules around creating events, so you should first have a careful read of the\n[POST documentation](events#post-api-events).\n\n### Listing all event types\n\n1. `GET /api`\n2. GET the link at `features.events.eventGroups` [↪](events#get-api-events-groups)\n\nThat will return all event types in their groups.\n\n### Event 'updates' versus 'next'\n\nThis expands on the difference between the API endpoints at the ends of the long poll `updates`\nand short poll `next` links that you receive in event searches.  It will make more sense after\nreading the operations' own sections ([long poll](events#get-api-events-updates), [short\npoll](events#get-api-events)).\n\nThe two API calls use the same filters and return the same payloads, including the same\npagination links.  They differ at two times:\n  \n  * On your first call, the short-polling 'events' route will return you the first events in the\n    historical record that meet your search criteria but the long-polling 'updates' route will\n    wait until new events arrive.\n\n  * On the last call, when there are no events that meet your criteria that the server has not\n    sent you already, 'events' will immediately return an empty result set but 'updates' will\n    wait for more to arrive.\n\nThe short poll is appropriate when you do not wish to stay up-to-date.  When you are extracting\nevents from the past, and want to move on to other things as soon as you have them all.\nGenerating reports, basically.\n\nThe long poll is appropriate when you will be continuing to make the call, probably forever,\nbecause you wish to stay current and to not miss any events.\n    \nYou should only be using one of the two.  Using both in the same integration may indicate a\ndesign issue.\n\n## Efficiency tips\n\n* Use search parameters to reduce the filtering burden on the server.\n\n* When downloading a significant number of events, leave `top` at 1000 or more,\n  provided your client can handle results over a megabyte (events are\n  around 1 KB each).  Performance tests have shown that throughput decreases\n  dramatically if `top` is too low.\n\n* If using 8.40 or later, use its `field` query parameter to cut back on the fields the server\n  sends to you.  Not only will it save bandwidth, but it will save the server looking up all\n  those values and serialising them for you.\n    \n* If you are using the `updates` link to keep up to date with events, sleep between calls for as\n  long as your requirements allow.  Doing that will improve the likelihood of your collecting\n  more than one event when it is busy.<br>For example, if Command Centre is generating ten\n  events per second and you do not sleep between REST calls, you will be calling `updates` ten\n  times per second for one event each time.  However if you sleep for two seconds after each\n  call you will receive 20 events at a time, saving CPU and I/O.\n\n## Event field specifiers\n\nWhat you can do with the `fields` query parameter on an events method has improved through the\nversions, so explaining it is a topic in itself.\n\nIn 8.40 and later the values you can list are the same as the field names in the [details\npage](models#eventdetail), plus the special value for a personal data field described\nbelow.  You can pick whichever fields you want, including `defaults`, though we urge you to\nonly list the fields you need.  Anything you wrote for 8.30 or earlier will\nwork in 8.40 as it did before.\n\nIn versions up to 8.30 you can only add fields to the event summary and details pages, not\nremove them.  If you send the parameter it must start with `fields=defaults`.  That gives you\nthe default set.  What you can add after that depends on the version of Command Centre you're\ncalling.\n\nIn 8.10 and earlier the only field you can add is `cardholder.pdf_XXXX`, where XXXX is the ID\nof a PDF.  Find that ID with a query to the [PDFs\ncontroller](pdf-definitions#get-api-personal_data_fields).  Don't forget a\nseparating comma between it and `defaults`.\n\nThat will add a cardholder's PDF to the events that are related to them.\n\nYou can only pick one PDF.  It will only appear on events that have a related cardholder, such\nas access events, because without a cardholder there is no PDF.  The security model applies\ntoo, so it will only appear if your REST operator has the appropriate privileges on that\ncardholder and PDF.\n\nIn 8.20 and later you can also add `details`.  Make sure you have a separating comma after\n`defaults` or `cardholder.pdf_XXXX`.\n\nAn event detail string can be kilobytes long so we left it optional.  It is the only field in\nthe details page that is not in the search results, by the way, so if you are running 8.20 or\nlater you can add it to your search results and you will not need the details page.\n\n| Server version | Valid fields parameter values\n| ------------ | --------------\n| Older than 8.20 | defaults,cardholder.pdf_XXXX \n| 8.20 to 8.30 | defaults,cardholder.pdf_XXXX<br>or<br>defaults,details<br>or<br>defaults,cardholder.pdf_XXXX,details\n| 8.40 and later | any\n\n### Per-event bookmarks\n\nIf you are running 8.70 or later and you put `previous`, `next`, or `updates` in the field\nlist of an event search, the server will add those fields to each event.  All server versions\ninclude links with those names at the end of results, but they are not useful if you crash out\nmidway through processing a batch.  The per-event links, only available in 8.70 and later\nand only on request, give you a place to pick up from without being re-sent the events you\nalready processed.\n\n## Licensing\n\n* The GETs that collect alarms and events require the RESTEvents licence.\n\n* The POST that creates events requires RESTCreateEvents.\n\n* The GET to collect event types requires RESTEvents or RESTCreateEvents.\n"}],"servers":[{"url":"https://127.0.0.1:8904"}],"security":[{"API_key":[]},{"basic":[]}],"components":{"securitySchemes":{"API_key":{"type":"apiKey","name":"Authorization","in":"header","description":"\nClients authenticate by including a pre-shared API key in the `Authorization` header of each\nrequest after an authorisation method of `GGL-API-KEY`:\n\n`Authorization: GGL-API-KEY C774-B01F-D695-AA4B-215F-A158-AC22-ADEB`\n\nFor a fuller description see [API authentication](api-authentication).\n"},"basic":{"type":"http","scheme":"basic","description":"This is HTTP Basic authentication using a blank username and the API key as the password.\n\nExample:  `Authorization: Basic OkM3NzQtQjAxRi1ENjk1LUFBNEItMjE1Ri1BMTU4LUFDMjItQURFQg==`\n\nThat example is equivalent to the example in the description of the api_Key method:\nprepending a colon to the API key beginning with `C774` then encoding it into Base64\nproduces the 56 characters beginning with `OkM3`.\n\nThe colon is a separator between a username, which is blank in our case, and the password,\nwhich is our API key.\n\nFor a fuller description see [API authentication](api-authentication)\n"}},"schemas":{"EventPOSTBody":{"title":"Event POST body","required":["eventType"],"properties":{"type":{"deprecated":true,"description":"A new event must contain either this or (if your server is running 8.90 or later) `eventType`.\nWithout one of them, the POST will fail.\n\nThe event type is mandatory because the server cannot assume a reasonable default, as it\ndoes for the other fields.\n\nIf you send both a `type` block and an `eventType` block to a server running 8.90 or later\nit will use `eventType`.  Versions before 8.90 do not know about `eventType` so they use `type`.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference"}}},"eventType":{"description":"A new event must contain either this or `type`.  Without one of them, the POST will\nfail.\n\nThe event type is mandatory because the server cannot assume a reasonable default, as it\ndoes for the other fields.\n\nIf you send both a `type` block and an `eventType` block to a server running 8.90 or later\nit will use `eventType`.  Versions before 8.90 do not know about `eventType` so they use `type`.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"Take this href from the list of [event types](events#get-api-events-groups).\nNote that you can only use event types in one of the thirty external event groups with\nIDs 57-66 and 190-209.  Command Centre ships with one event type per group, IDs\n4000-4009 and 6010-6029, but you can create 970 more using the External Event Type\nConfiguration utility.\n"}}},"source":{"description":"This block should contain the href of the item you wish to use as the source of your\nevent.  It can be any site item to which your operator has view access including all\nhardware, access zones, fence zones, doors, lockers, car parks, servers, external systems,\nand many other item types.  If you do not supply one Command Centre will use the REST\nClient item identified by the API key in the `Authorization` header.\n\nCardholders cannot be event sources.  To relate a cardholder to your event, use the\n`cardholder` block.\n\nMake sure that your operator has the 'Create Events and Alarms' privilege on this item's\ndivision.  8.90 and later insist on it.\n\nThe API will use the source's division as the event's division.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"Get the href using the API controller for that type of item (such as\n[doors](doors)) or from the more general [item\nsearch](items#get-api-items).\n"}}},"priority":{"type":"integer","minimum":1,"maximum":9,"description":"It is not possible to submit an event with priority zero in the body, but if you submit an\nevent with no priority it will use the one on the event type's action plan, which can be\nzero.\n"},"time":{"type":"string","format":"date-time","description":"Like all other fields in this POST apart from the type, this field is optional.  If you\nsend it, it must be in the format described [here](text-encoding).\n\nIf you do not send this, the server will use the time that it received your request\n(its \"now\").\n"},"message":{"type":"string","description":"This is the first thing an operator will see when they look at this event.  Some\ninteractive clients do not give it a lot of room on screen so put the important\nparts of your message first.  It has a limit of 1024 characters.\n"},"details":{"type":"string","description":"Command Centre will attach this string to event, as it does the message, but\noperators will have to look more closely at the event to see it.  On the upside,\nit can be longer than the message:  2048 characters in 8.10.\n"},"cardholder":{"description":"If you wish to attach a cardholder to your event, link it here.  Reports can show or\nfilter by the cardholder.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"This can be the href of any cardholder to which your operator has view access.  Get\nthe href from the [cardholders controller](cardholders).\n"}}},"operator":{"description":"If you wish to attach an operator to your event, link it here.  Like the cardholder,\nreports can show or filter by the operator.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"This can be the href of any cardholder to which your operator has view access.  It\ndoes not need to be an operator (a member of an operator group).\n"}}},"entryAccessZone":{"description":"If you wish to attach an access zone to your event, link it here.  Reports can filter by\nand show the entry access zone on events.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"This can be the href of any access zone to which your operator has view access.  Get\nthe href using the [access zones controller](tag-Access-Zones) or from\n`/items`.\n"}}},"accessGroup":{"description":"If you wish to attach an access group to your event, link it here.\n\nUnlike cardholders, operators, and entry access zones, access groups do not appear in\nCommand Centre activity reports.  You can add a filter to restrict an activity report by\naccess groups, but the group that allowed an event into the report will not appear in a\ncolumn.\n\nLike all the other items you link to your event it will, of course, appear when you GET\nthe event from the API later.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"This can be the href of any access group to which your operator has view access.\nGet the href using the [groups controller](access-groups) or\nthe [items controller](items).\n"}}},"lockerBank":{"description":"If you wish to attach a locker bank to your event, link it here.\n\nLike an event's access group, you can filter a Command Centre activity report to events\nthat involve a locker bank, but the bank will not appear in the report itself.\n\nIf you link both a locker and a locker bank to an event, Command Centre does not require\nthat the locker is in the locker bank, but you may find that downstream reporting software\nmisbehaves when it is not.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"This can be the href of any locker bank to which your operator has view access.  Get\nthe href using the [locker banks](lockers) calls or the more general\n[items](items) routes.\n"}}},"locker":{"description":"If you wish to link a locker to your event, do it here.  Like an event's access group and\nlocker bank, you can filter a Command Centre activity report to events that involve a\nlocker, but the locker will not appear in the report itself.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"This can be the href of any locker your operator can view.  Get the href from the\n[items](items) controller or the `lockers` field of [a locker\nbank](models#lockerbankdetail).\n"}}},"door":{"description":"If you wish to link a door to your event for later extraction or a report filter, do it\nhere.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"This can be the href of any door your operator can see.  Get it with a\n[doors](doors) call or a more general [items\nsearch](items#get-api-items).\n"}}}}}}},"paths":{"/api/events":{"post":{"tags":["Events"],"summary":"Add an event","description":"Use this method to create an event in Command Centre v8.10 or later.\n\nDo not code this URL into your application.  Take it from `events.events.href` in the\nresults of `GET /api`.\n\nEach field has particular rules and has its own effects on the event and subsequent reports,\nand misconfiguration (such as inadvertently causing a macro to run itself) can land you in\nreal trouble, so have a good look at the documentation below and the example [POST\nbody](models#eventpostbody).\n\nEvents are immutable:  you cannot PATCH or DELETE them after you create them.\n\n## Usable event types\n\nYou must supply an [event type](events#get-api-events-groups).  At the time of writing\n(9.50), CC ships with 30 event types you can use, each in its own event type group.  The\nPOST body schema definition linked above shows which event types you can use:  they have\n'external' in their name.\n\nYou can create 970 of your own event types using the External Event Type Configuration\nUtility, a separate Windows application that lets you create external event types and make\nthem appear on items' Event Response and Alarm Instructions tabs in the Configuration\nClient.  You will find the release note for that utility in the Documentation folder on the\ninstallation media.\n\n1000 event types sounds like a lot, but be aware that you cannot delete event types, and the\nonly thing you can modify on an existing event type is its name.  Their event type group and\nitem types are permanent once you save them from the utility.  Please plan carefully, and\ntake backups!\n\n## A note on event type groups\n\nThere is much confusion between event types and groups.\n\nYou do not specify a type _group_ when creating a new event.  You specify a type.  The parts\nof Command Centre that work with the event later will look up what group the event type is\nin, principally to select an action plan to run, but you do not need to consider groups when\ncreating the event.\n\n## Usable source items\n\nEvery event needs a source item.  You can let the server pick one for you (it will use the\nREST Client item identified by your API key) or you can use any item that has an 'Event\nResponse' tab in its Configuration Client window (which is most of them).  Our existing\nintegrations use items like doors, external system items, and cameras.\n\nIf you allow the server to default to your REST client item as the source, or if you specify it\nyourself, your operator must have 'Create events and alarms' in at least one division for\nthe call to succeed.  Any division will do.  Otherwise you'll receive a 403.\n\nIf you specify a source item to a server running 8.90 or later and that item is not your\nREST Client item, your operator must have the 'Create events and alarms' privilege in that\nitem's division.  In older versions it was enough for your operator to have that privilege\nin any division.\n\nCardholders cannot be event sources because they do not have an 'Event Response' tab, but...\n\n## Related items\n\nAlong with a source, you can link other items to the events you create.  If you link a\ncardholder, for example, your events will show on an activity report generated for that\ncardholder.  To link an item your operator must have a privilege that allows viewing it\n('View cardholders' for cardholders or 'View site' for most other item types).\n\n## Action plans\n\nAn event can fire an action plan, which will\n* set the priority if the REST client did not set one in the body of the POST, and\n* run a macro on the server.\n\nMacros are extremely powerful, and a thorough treatment requires more room than we have, so\nit is sufficient to say that you should not aim for a dramatic first test.  A good first\nresult is to turn on a virtual output made for the purpose.  Just make sure that it will not\ntrigger another macro because it is possible to create loops, causing havoc.\n\nYou do not pick an action plan to run when you POST your event.  Command Centre does that in\nthree steps:\n  \n  1. The server looks at the configuration of the source item in the Event Response tab of\n     its property page in the Configuration Client.  If there is an entry for the event type\n     that is not \"use default\", Command Centre will fire that action plan and skip the next\n     steps.  In versions older than 8.30 the control is per event group, not per event.\n  2. Since the server did not find an action plan on the item, it tries its alarm zone.\n     Specifically, the Event Defaults tab of the alarm zone's property page in the\n     Configuration Client.  Again the control is per event group not per event type in older\n     versions.  If the event's action plan is not 'use default', the server fires that\n     action plan and goes no further.\n  3. Since the server did not find an action plan on the item or its alarm zone, it looks at\n     the configuration in the Event Defaults tab of the server properties.  There is always\n     an action plan there, even if it does nothing more than set the priority of the event.\n\nOnce it has found the action plan to run, the server will assign the event its priority (if\nyou did not specify a priority yourself) and run the macro if there is one, both from the 'Command\nCentre' tab of the action plan's property page in the Configuration Client.  The server will\nnot use the configuration from the other tabs.\n\nIt is not possible to submit an event with priority zero, but it is possible to submit an\nevent with no priority, and have the action plan assign it priority zero.  This will run the\nmacro on the action plan then drop the event before it reaches the database.\n\n## Alarm instructions\n\nAlarm instructions are marked-up text fields that Command Centre presents to security\npersonnel when events occur.  Picking an alarm instruction to use follows the same decision\npath as picking an action plan:  Command Centre looks at the configuration of the source\nitem first, and finding nothing there will turn to the source item's alarm zone, and finally\nto the server properties.  If all three are unset the operator will not receive any special\ninstructions.\n\nSo, what an operator sees when your event arrives on their board depends on the priority and\nthe event source.\n\n## When events become alarms\n\nAfter the server has established an event's priority, either from the body you POSTed or the\naction plan, it looks at the Event Priorities tab of the server properties.  There is a\nslider there that sets the level above which an event becomes an alarm.  By default it is\nset to two, meaning that any event with a priority of two or higher will appear as an alarm.\n","requestBody":{"description":"You can specify many things on an event but the only mandatory field is the type.  When\nyou are developing, start with just that.\n","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventPOSTBody"}}}},"responses":{"201":{"description":"Success.","headers":{"location":{"description":"The href of the new event.","schema":{"type":"string","format":"uri-reference"}}}},"204":{"description":"Success with no event created, probably because the priority in the action plan was\nzero.\n"},"400":{"description":"The parameters are invalid.  Check the body of the response for an error message.\n\n8.90 and later will reject the POST with a 400 if your event specifies a source item\nthat is not your REST Client item and your operator does not have 'Create Events and\nAlarms' on its division.\n"},"403":{"description":"The site does not have the RESTCreateEvents licence (in which case the body of the\nresponse will say so) or the operator does not have the 'Create Events and Alarms'\nprivilege.\n"}}}}}}
```

## Get new events (or wait)

> Poll this link to receive new events that match the specified filters.  If there are none\
> ready, the call will block until one arrives or a deadline passes.\
> \
> For its correct use in various scenarios, see the \[use cases]\(#event-use-cases).  In\
> particular, sleep between calls to reduce load on the server.\
> \
> The way this call picks its initial set of events is different from \`/api/events\`:\
> \
> \- If you follow the link at \`events.updates.href\` in the results of \`GET /api\`, it will\
> &#x20; block until at least one event arrives that meets your search criteria, then return them.\
> \
> \- If you follow the \`updates\` link from the results of \`GET /api/events\` or \`GET\
> &#x20; /api/events/updates\`, the link will contain a bookmark parameter that causes the server to\
> &#x20; return the first events that arrived after that bookmark (and that meet your search\
> &#x20; criteria, of course).  If there are none, it will block until some arrive that do.\
> \
> The response will contain an \`updates\` link back to the same API call with a new bookmark\
> that will cause it to return the next page of results.\
> \
> Each response will also contain a \`next\` link that will take you to the non-blocking version\
> of the call at \[/api/events]\(events#get-api-events).  However if you are using this\
> call you should not also be using the \`next\` link:  applications typically use one or the\
> other, not both.\
> \
> However long you wait between calls, following a \`next\` or \`updates\` link will always return\
> the first events that arrived after your previous call.\
> \
> Do not code this URL into your application.  Take it from \`events.updates.href\` in the\
> results of \`GET /api\`, or from \`updates\` in the results of \`GET /api/events\`.<br>

```json
{"openapi":"3.2.0","info":{"title":"Command Centre REST API","version":"2.0"},"tags":[{"name":"Events","description":"Use the GET methods in this API for historical searches or to stay up to date with new events as\nthey occur.  Use the POST method (added in version 8.10) to create events of your own.\n\nThere are no PATCH actions on events, because they are immutable.  If an event is also an alarm\nit carries some changeable state and a log of activity and comments, but the underlying event\nnever changes.\n\nThe API only returns events that are still in Command Centre's database.  It will not return\nevents that have been removed, even if they are in an archive file.\n\n## Location events in 9.00\n\nCommand Centre has about 80 event types that occur when somebody authenticates at a device,\nusually by badging a card.  Some of those event types also contain the access zones that the\nperson started and finished in.  Version 9.00 introduced some improvements that presented the\ncardholder and the two zones to API clients in a consistent way:\n\n  * A new event type `hasLocation` that lets you filter for only those events that reveal a\n    cardholder's location.  If your server is 9.00 or better, use it in the `type` query\n    parameter as you would normally use an integer event type:  `type=hasLocation`.  Gallagher\n    will update this as new versions add more event types.  Do not use it on 8.90 or earlier:\n    those servers will reject it.\n\n  * A new `location` block on events of those types that contains fields containing the\n    cardholder and their location.\n\nFor more on using these new features, see the relevant use case below (search for 'location').\n\n## Event use cases\n\n### Downloading the entire event database\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events).  You\n   can add query parameters to alter the search.  If you are running 8.70 or later and there\n   is a danger that you might encounter a problem while processing a batch of events you should\n   also use `fields` to get the `next` link for each event.  Note that this is different from\n   the `next` link you receive at the end of each result set.\n3. Process the events you receive in that call.  If you asked for the `next` field, write the\n   link for each event you successfully process to disk before attempting the next one.  Then,\n   if the worst happens, your client can read that link from disk and pick up where it left off.\n4. If there were results, follow the link at `next.href` and repeat.\n\nIf you then wish to stay up to date, switch to following the link at `updates.href`\n[↪](events#get-api-events-updates) in the results.  That call will block until more\nevents arrive, or a minute passes (approximately).\n\n### Downloading the most recent events\n1. `GET /api`\n2. Take the link at `features.events.events.href` [↪](events#get-api-events) and\n   append `previous=true&top=20`.  Add the appropriate query separator `?` or `&` first,\n   depending on whether there is a query parameter in the URL already, and change the 20 as\n   appropriate.  The default is 1000, which is probably more than you want.\n3. Process the events you receive in that call.\n4. Follow the link at `previous.href` to get earlier events, or `next.href` or `updates.href`\n   for later events.  The last is a long poll, which means that if no events are ready when\n   you make the call it will block until new events arrive.\n\n### Reporting on events over a period.\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) appending\n   `after=2017-01-01Z&before=2017-02-01Z` or whatever timestamps are appropriate (after the\n   correct query separator, `?` or `&`).\n\nRemember that some remote systems take their time sending events to Command Centre, so\ndo not be too hasty running your reports.  If you fire them off at the stroke of\nmidnight, you may miss events that occurred before midnight but have not yet arrived\nat Command Centre.\n\n### Receiving new events as they occur, starting from now\n1. `GET /api`\n2. Follow the link at `features.events.updates.href`\n   [↪](events#get-api-events-updates) adding query parameters containing your search\n   terms.  The call will block until at least one matching event arrives at the server.\n3. Process the events you receive in that call.  Often there is only one:  the first that\n   arrived after you made the call.\n4. Sleep to reduce load on the server.\n5. Loop, following the link at `updates.href` after processing each batch of events.  It will\n   return immediately if there are new events waiting, or it will block until new events arrive.\n   Follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might encounter a problem writing events mid-batch.  Note that that advises using the `next`\n   field, but you will be using the `updates` field, which is the same thing in long-poll form.\n\n### Receiving new events as they occur, starting from now, with no long polls\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) and append\n   `previous=true&top=1`.  Add the appropriate query separator `?` or `&` first, depending on\n   whether there is a query parameter in the URL already.  The call will return one event (which\n   you can ignore) and a `next` link you'll need later.\n5. Sleep and loop, following the link at `next.href` after processing each batch of events.  It\n   will return immediately whether or not there are new events waiting.  Follow the advice in\n   [downloading the entire event database](#downloading-the-entire-event-database) about keeping\n   track of your position if you might encounter a problem writing events mid-batch.\n\n### Receiving new events as they occur, starting in the past\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) appending\n   the query parameter `after=2021-05-08Z` (or whatever timestamp is appropriate).\n3. Process the events you receive in that call.\n4. Sleep to reduce load on the server.\n5. Loop, following the link at `updates.href` after processing each batch of events.  It will\n   return immediately if there are new events waiting, or it will block until new events arrive.\n   Follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might encounter a problem writing events mid-batch.  Note that that advises using the `next`\n   field, but you will be using the `updates` field, which is the same thing in long-poll form.\n\n### Searching for events related to particular cardholders\n1. `GET /api`\n\n2. Follow the link at `features.items.items.href` [↪](items#get-api-items), adding\n   `name=\"your_cardholder_name\"&type=1` to the query after the appropriate separator (`?` or\n   `&`).\n\n   The 'items' controller necessary for that step is available with the RESTEvents licence.  If\n   you also have the RESTCardholders licence you could use the link at\n   `features.cardholders.cardholders.href` [↪](cardholders#get-api-cardholders)\n   instead, adding a separator and `name=\"your_cardholder_name\"`.\n\n   In either case, remove the quotes if you want a substring search and can handle more than\n   one cardholder in the results.\n   \n1. Extract the item ID of your cardholder or cardholders from that page, repeating as\n   necessary for additional cardholders.\n\n1. Follow the link on the `/api` page at `features.events.events.href`\n   [↪](events#get-api-events) appending the separator and `cardholder=XX` or\n   `cardholder=XX,YY,ZZ` with the cardholders' IDs.\n\nTo further improve the efficiency of your search, filter by event types and a time\nrange.\n\n### Searching for events that indicate location or movement\n\nIf your server is running 8.60 or earlier, use the search filter\n`type=20001,20002,20003,20047,20107,15582,15583,15800,15808,42415`.  That is not a complete list\nof movement event types but it includes the popular ones.\n\nIf your server is running 8.70-8.90 inclusive, give your operator the 'View cardholder events'\nprivilege instead of 'View events'.  Then you can request all events, and the server will only\nsend you movements because that is all your operator is permitted to see.\n\nIf your server is running 9.00 or later, the 'View cardholder events' privilege is still an\nexcellent idea to limit your operator's vision but you can also use the search filter\n`type=hasLocation&fields=location` (with a leading `?` or `&` of course, and more fields if you\nneed them).  That will limit the results to location events.\n\nWhen using a server at version 9.00 or better:\n\n1. `GET /api`\n\n2. Get the URL of the head of the event queue by following the link at\n   `features.events.updates.href` [↪](events#get-api-events-updates) appending\n   `type=hasLocation&fields=location` with the appropriate query separator `?` or `&` depending\n   on whether there is a query parameter in the URL already.  The call will block until a new\n   location event arrives.\n\n5. If this is your first time here you will have an array containing one event.  If you looped\n   up from a later step, the array may contain many more.  In any case, process all the events\n   in the results using the advice immediately below about interpreting the `location` block.\n   Also follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might have to abort mid-batch.  Note that that advises using the `next` field, but if you\n   want long polls you will be using the `updates` field.\n\n4. Sleep for a short time to reduce load on the server.\n\n5. Follow the link at `updates.href` for a long poll that waits for new events to arrive, or\n   follow `next.href` for a call that will return immediately even if there are no new events\n   for you.\n\n6. Loop up to process the events you received.\n\nInterpreting the `location` block:\n\n* If you are simply after a person's location and do not care how they arrived there, use the\n  `afterLocation` block inside `location`.  The `canonicalTypeName` field in there will tell you\n  what kind of location it is (reception or access zone).  The [schema\n  definition](models#eventdetail) describes `afterLocation` in more detail.\n\n* If you are after movements, which happen when a door grants a person access or an operator\n  moves them on a tag board or via the API, and happen to some types of visitors when their host\n  moves, ignore all events except those that have a `location.type` of `moved`.  Look at the\n  `afterLocation` to see where they landed.  There will also be a `beforeLocation` if the door\n  had two zones configured on it, in case you're interested in where they came from.  The\n  `canonicalTypeName` field in both blocks will tell you what kinds of item they are.\n\n* If you are after denials, which happen when a person authenticates but fails the access check,\n  look at the events that have a `location.type` of `denied`.  Like 'moved'-type events,\n  `location.afterLocation` will show where they ended up.  The difference is that with\n  'denied'-type events, they started there too.\n\nEach of those fields is covered in the [schema definition](models#eventdetail).\n\nBe aware that the events you receive are limited to those with a source item that is in a\ndivision in which your operator has a privilege that allows viewing events.  In 9.00 those\nprivileges are 'View Events' and 'View Cardholder Events', and of course 'Advanced User'.  That\nmakes this API unsuitable for handling emergencies such as evacuations if your operator's view\nis limited:  if your operator does not have the privilege to view events generated by a\nparticular door, this API will not tell you about movements through that door.\n\n### Searching for events coming from other items\n\nEvents such as 'access granted' and 'zone count maximum' come from doors and access zones.  To\nsearch for them, follow the same process as the previous use case (getting cardholder events)\nbut use the `source` filter parameter instead of `cardholder`.  It will limit the results to\njust those events that came from the items you gave in the query.  If you have the RESTStatus\nlicence you can search for access zones, alarm\nzones, fence zones, macros, outputs, doors, and (in 8.10) inputs.  If you do not, or if your\nsource is not one of those types, use the [items API](items) with a suitable `type` filter.\n\nYou can also use the `type` parameter to limit the events to particular event types.  By doing\nthis you can (for example) subscribe to 'access granted' events from a collection of doors.\n\nNew in v8.70, you can also filter by `relatedItem`. Use this to find events related\nto item or items regardless of the type.\n\n### Creating a new event\n\n1. `GET /api`\n2. POST to the link at `features.events.events.href` [↪](events#post-api-events)\n\nThere are some rules around creating events, so you should first have a careful read of the\n[POST documentation](events#post-api-events).\n\n### Listing all event types\n\n1. `GET /api`\n2. GET the link at `features.events.eventGroups` [↪](events#get-api-events-groups)\n\nThat will return all event types in their groups.\n\n### Event 'updates' versus 'next'\n\nThis expands on the difference between the API endpoints at the ends of the long poll `updates`\nand short poll `next` links that you receive in event searches.  It will make more sense after\nreading the operations' own sections ([long poll](events#get-api-events-updates), [short\npoll](events#get-api-events)).\n\nThe two API calls use the same filters and return the same payloads, including the same\npagination links.  They differ at two times:\n  \n  * On your first call, the short-polling 'events' route will return you the first events in the\n    historical record that meet your search criteria but the long-polling 'updates' route will\n    wait until new events arrive.\n\n  * On the last call, when there are no events that meet your criteria that the server has not\n    sent you already, 'events' will immediately return an empty result set but 'updates' will\n    wait for more to arrive.\n\nThe short poll is appropriate when you do not wish to stay up-to-date.  When you are extracting\nevents from the past, and want to move on to other things as soon as you have them all.\nGenerating reports, basically.\n\nThe long poll is appropriate when you will be continuing to make the call, probably forever,\nbecause you wish to stay current and to not miss any events.\n    \nYou should only be using one of the two.  Using both in the same integration may indicate a\ndesign issue.\n\n## Efficiency tips\n\n* Use search parameters to reduce the filtering burden on the server.\n\n* When downloading a significant number of events, leave `top` at 1000 or more,\n  provided your client can handle results over a megabyte (events are\n  around 1 KB each).  Performance tests have shown that throughput decreases\n  dramatically if `top` is too low.\n\n* If using 8.40 or later, use its `field` query parameter to cut back on the fields the server\n  sends to you.  Not only will it save bandwidth, but it will save the server looking up all\n  those values and serialising them for you.\n    \n* If you are using the `updates` link to keep up to date with events, sleep between calls for as\n  long as your requirements allow.  Doing that will improve the likelihood of your collecting\n  more than one event when it is busy.<br>For example, if Command Centre is generating ten\n  events per second and you do not sleep between REST calls, you will be calling `updates` ten\n  times per second for one event each time.  However if you sleep for two seconds after each\n  call you will receive 20 events at a time, saving CPU and I/O.\n\n## Event field specifiers\n\nWhat you can do with the `fields` query parameter on an events method has improved through the\nversions, so explaining it is a topic in itself.\n\nIn 8.40 and later the values you can list are the same as the field names in the [details\npage](models#eventdetail), plus the special value for a personal data field described\nbelow.  You can pick whichever fields you want, including `defaults`, though we urge you to\nonly list the fields you need.  Anything you wrote for 8.30 or earlier will\nwork in 8.40 as it did before.\n\nIn versions up to 8.30 you can only add fields to the event summary and details pages, not\nremove them.  If you send the parameter it must start with `fields=defaults`.  That gives you\nthe default set.  What you can add after that depends on the version of Command Centre you're\ncalling.\n\nIn 8.10 and earlier the only field you can add is `cardholder.pdf_XXXX`, where XXXX is the ID\nof a PDF.  Find that ID with a query to the [PDFs\ncontroller](pdf-definitions#get-api-personal_data_fields).  Don't forget a\nseparating comma between it and `defaults`.\n\nThat will add a cardholder's PDF to the events that are related to them.\n\nYou can only pick one PDF.  It will only appear on events that have a related cardholder, such\nas access events, because without a cardholder there is no PDF.  The security model applies\ntoo, so it will only appear if your REST operator has the appropriate privileges on that\ncardholder and PDF.\n\nIn 8.20 and later you can also add `details`.  Make sure you have a separating comma after\n`defaults` or `cardholder.pdf_XXXX`.\n\nAn event detail string can be kilobytes long so we left it optional.  It is the only field in\nthe details page that is not in the search results, by the way, so if you are running 8.20 or\nlater you can add it to your search results and you will not need the details page.\n\n| Server version | Valid fields parameter values\n| ------------ | --------------\n| Older than 8.20 | defaults,cardholder.pdf_XXXX \n| 8.20 to 8.30 | defaults,cardholder.pdf_XXXX<br>or<br>defaults,details<br>or<br>defaults,cardholder.pdf_XXXX,details\n| 8.40 and later | any\n\n### Per-event bookmarks\n\nIf you are running 8.70 or later and you put `previous`, `next`, or `updates` in the field\nlist of an event search, the server will add those fields to each event.  All server versions\ninclude links with those names at the end of results, but they are not useful if you crash out\nmidway through processing a batch.  The per-event links, only available in 8.70 and later\nand only on request, give you a place to pick up from without being re-sent the events you\nalready processed.\n\n## Licensing\n\n* The GETs that collect alarms and events require the RESTEvents licence.\n\n* The POST that creates events requires RESTCreateEvents.\n\n* The GET to collect event types requires RESTEvents or RESTCreateEvents.\n"}],"servers":[{"url":"https://127.0.0.1:8904"}],"security":[{"API_key":[]},{"basic":[]}],"components":{"securitySchemes":{"API_key":{"type":"apiKey","name":"Authorization","in":"header","description":"\nClients authenticate by including a pre-shared API key in the `Authorization` header of each\nrequest after an authorisation method of `GGL-API-KEY`:\n\n`Authorization: GGL-API-KEY C774-B01F-D695-AA4B-215F-A158-AC22-ADEB`\n\nFor a fuller description see [API authentication](api-authentication).\n"},"basic":{"type":"http","scheme":"basic","description":"This is HTTP Basic authentication using a blank username and the API key as the password.\n\nExample:  `Authorization: Basic OkM3NzQtQjAxRi1ENjk1LUFBNEItMjE1Ri1BMTU4LUFDMjItQURFQg==`\n\nThat example is equivalent to the example in the description of the api_Key method:\nprepending a colon to the API key beginning with `C774` then encoding it into Base64\nproduces the 56 characters beginning with `OkM3`.\n\nThe colon is a separator between a username, which is blank in our case, and the password,\nwhich is our API key.\n\nFor a fuller description see [API authentication](api-authentication)\n"}},"parameters":{"eventfields":{"name":"fields","description":"In 8.40 and later the values you can list are the same as the field names in the [details\npage](models#eventdetail), plus a special field name for a personal data field,\ndescribed next.  You can pick whichever fields you want, including `defaults` though we urge\nyou to avoid that and only ask for the fields you need.\n\nYou can request `cardholder.pdf_XXXX` where XXXX is the ID of a PDF, which you can discover\nwith a query to the [PDFs\ncontroller](pdf-definitions#get-api-personal_data_fields).  That will add a\ncardholder's PDF to the events that are related to them.\n\nYou can only pick one personal data field.  It will only appear on events that have a\nrelated cardholder, such as access events, because without a cardholder there is no personal\ndata.  The security model applies too, so it will only appear if your REST operator has the\nappropriate privileges on that cardholder and PDF.\n","in":"query","schema":{"type":"string","enum":["defaults","details","cardholder.pdf_*","href","id","serverDisplayName","time","message","occurrences","priority","alarm","operator","source","group","type","eventType","division","cardholder","entryAccessZone","exitAccessZone","door","accessGroup","card","modifiedItem","lastOccurrenceTime","previous","next","updates","location"]}}},"schemas":{"EventSearch":{"title":"Event search","description":"`/api/events` and `/api/events/updates` return this structure.","type":"object","properties":{"events":{"type":"array","description":"A list of event summaries.","items":{"$ref":"#/components/schemas/EventSummary"}},"previous":{"type":"object","description":"Follow this link to make a non-blocking call to collect the previous page of events (in\norder of arrival).  It will return an empty page if you have already received the first\nevent in the database.\n","properties":{"href":{"type":"string","format":"uri-reference"}}},"next":{"type":"object","description":"Follow this link to make a non-blocking call to collect the next page of events, moving\nforward in arrival time.  It will return an empty page if no more events are available.\n","properties":{"href":{"type":"string","format":"uri-reference"}}},"updates":{"type":"object","description":"This is a link to an [updates](events#get-api-events-updates) call.  Follow it to\nmake a blocking call to collect more events.  If there are none, the call will block until\none arrives or the call times out.  This link will contain your column select, pagination,\nand filtering parameters (`fields`, `top`, `after`, `before`, `source`, `type`, etc.) but it drops\n`deadline`.  You need to add that to each call.\n","properties":{"href":{"type":"string","format":"uri-reference"}}}}},"EventSummary":{"title":"Event summary","type":"object","description":"`/api/events` and `/api/events/updates` return an array of these, and `/api/events/{id}`\nreturns one with more fields.\n\nThe message and event type in this example indicate an operator attempting to log in with an\nincorrect password, but for the sake of illustration the example also contains references to\nitems that would never appear on such an event.  The card, cardholder, and access zones, for\nexample.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"A link to the details of this event, also usable as an identifier.  It is not globally\nunique but it is unique to the site and, barring a database restore, it will not be\nrecycled by another event or alarm.\n"},"id":{"type":"string","description":"An alphanumeric identifier for this event, unique to the site but not across sites.\nOnce allocated they are not re-used, except after totally resetting the server's state\nby restoring the database.\n"},"serverDisplayName":{"type":"string","description":"The host name of this event's origin server, if it was aggregated from a remote host.\nAbsent for local events.\n\nNote that this is not the descriptive name of the remote server's item, but the host name\nused for address resolution.\n\nNew to 8.40.\n"},"time":{"type":"string","format":"date-time","description":"The time the event occurred."},"message":{"type":"string","description":"The event's message."},"occurrences":{"type":"integer","description":"If an event arrives with the same essential properties as a previous event, the server\nwill start counting them.  Each event is still individually addressable and will appear in\nthe API as normal, but the first in the\ngroup will also have this property.  It only appears on the first, and it does not appear\nif the event is a singleton.\n\nIf present on an event's detail or alarm page, there will also be a `lastOccurrenceTime`.\n\nOutside of the `alarm` block, which contains an alarm's state, this is the only field on\nan event that can change.\n","minimum":2},"priority":{"type":"integer","description":"Numeric priority.  9 is critical and 0 is not an event.","minimum":0,"maximum":9},"alarm":{"type":"object","description":"If an event is also an alarm, this object will contain\nits state and a link to its details page in the alarms controller.\n\nOnly the first event in a group (see the `occurrences` field) can become an alarm.\n","properties":{"state":{"description":"Alarms start unacknowledged.  Acknowledging or processing them changes that.","type":"string","enum":["unacknowledged","acknowledged","processed"]},"href":{"type":"string","format":"uri-reference","description":"Link to the alarm entity corresponding to the event. GET the href for full alarm details."}}},"operator":{"description":"The href and name of the operator or system behind this event.  This will appear when an operator\nhas modified an item.  New in v8.00.\n\nThe item he or she modified will appear in the `modifiedItem` block (added in 8.40).\n\n***Change is coming.***\n\nThe operator may not be a cardholder.  A version of Command Centre after 9.30 will\nreturn events where the operator item is of a different kind.  In that case, the\n`operator` block will also contain a `canonicalTypeName` field telling you what kind of\nitem is at the other end of the href.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the operator who caused this event by editing an item.  New in 8.00."},"name":{"type":"string","description":"The name the operator held at the time.  New in 8.40."}}},"source":{"type":"object","description":"ID and name of the source of the event, as recorded at the time of the event.","properties":{"id":{"type":"string","description":"The alphanumeric ID of the event source item.  Search for events with the same source\nas this one with `source=321` in the query parameters.\n"},"name":{"type":"string","description":"This could be different from the current name of the source item."},"href":{"type":"string","format":"uri-reference","description":"Link to the source item.  New in 8.00."}}},"group":{"type":"object","description":"ID and name of the event group this event belongs to.  Do not confuse this with an access\ngroup or operator group:  this is the event type group to which the event's type belongs.\nThere are about 150 and you can list them at\n[/events/groups](events#get-api-events-groups).\n","properties":{"id":{"type":"string","description":"The alphanumeric ID of the event group.  Search for events of the same rough category\nas this one with `type=35` in the query parameters.\n"},"name":{"type":"string","description":"The name of the event group."}}},"type":{"type":"object","description":"ID and name of the event's type.  There is a long list of them at\n[/events/groups](events#get-api-events-groups).\n","properties":{"id":{"type":"string","description":"The alphanumeric ID of the event type.  To search for events of the same type as this\nexample, put `type=23035` in the query parameters of\n[/events](events#get-api-events).\n"},"name":{"type":"string","description":"The name of the event type."}}},"eventType":{"description":"ID and name of the event's or alarm's type.  There is a long list of them at\n[/events/groups](events#get-api-events-groups).\n\nUnlike the `type` field, this has the same format in an event as it does in an alarm.\n\nAdded in 8.90.  Because it is a new field, it does not appear by default.  Ask for it using\nthe `fields` parameter.\n","type":"object"},"division":{"type":"object","description":"ID, name, and href of the event's division (which is the division of the event's source\nitem, for most event types).\n","properties":{"id":{"type":"string","description":"The alphanumeric ID of the event's division.  Search for other events from items in\nthe same division as this example by putting `division=2` in the query parameters.\n"},"href":{"type":"string","format":"uri-reference","description":"The link to the division item."},"name":{"type":"string","description":"The division's name.  Added in 8.40."}}},"cardholder":{"type":"object","description":"Summary information about an event's cardholder, if there is one.  This will be the\ncardholder who badged their card at a door in an access event, or the cardholder an\noperator modified in an operator event.  Search for other events related to this example's\ncardholder with `cardholder=325` in the query parameters.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the cardholder entity representing the cardholder of the event.  GET the href\nfor full details.\n"},"id":{"type":"string","description":"The alphanumeric ID of the cardholder associated with this event."},"name":{"type":"string","description":"In versions up to and including 8.10 this is the current name of the cardholder.  In\n8.20 it is the name of the cardholder at the time of the event.\n"},"firstName":{"type":"string","description":"The current value of the firstName field of this cardholder.  Added in 8.20."},"lastName":{"type":"string","description":"The current value of the lastName field of this cardholder.  Added in 8.20."}}},"entryAccessZone":{"description":"The name and href of the entry access zone related to the event.  In the case of card\nevents, it is the zone into which a cardholder was attempting to gain access.\n\nThat is true for successful entries, successful exits, and access denials.  Regardless of\nwhether the cardholder badged at the entry or exit reader, this field refers to the zone\nthat he or she attempted to access.\n\nFor example, for 'Card entry granted' events this field will contain the door's entry\nzone, but for 'Card exit granted' events this field will contain the door's _exit_ zone,\nbecause 'exit granted' means the cardholder was in the door's entry zone, badged at its\nexit reader, and was granted access to its exit zone.  Think of it as going through a door\nin its reverse direction.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the access zone entity representing the entry access zone related to this\nevent.  GET the href for the access zone's full details.  This will be missing if the\nserver lacks the RESTStatus licence, or your operator lacks the necessary privileges\n(such as 'View Site').\n"},"name":{"type":"string","description":"The current name of the access zone.  Expect a future version of Command Centre to\nchange this to the name of the access zone at the time of the event.\n"},"id":{"type":"string","description":"Deprecated."}}},"exitAccessZone":{"description":"The name and href of the exit access zone related to the event.  In card events, it is the\nzone from which a cardholder was attempting to leave, if the door had an exit zone\nconfigured (many do not).\n\nThat is true for successful entries, successful exits, and access denials.  Regardless of\nwhether the cardholder badged at the entry or exit reader, this field refers to the zone\nthat he or she attempted to leave.\n\nFor example, for 'Card entry granted' events this field will contain the door's exit zone,\nif there was one, but for 'Card exit granted' events this field will contain the door's\n_entry_ zone.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the access zone entity representing the exit access zone related to this\nevent.  This will be missing if the server lacks the RESTStatus licence, or your\noperator lacks the necessary privileges (such as 'View Site').\n"},"name":{"type":"string","description":"The current name of the exit access zone.  Expect a future version of Command Centre\nto change this to the name of the exit access zone at the time of the event.\n"},"id":{"type":"string","description":"Deprecated."}}},"door":{"description":"The name and href of the door related to the event.  These are not as common as you may\nthink, because when a door is relevant (to card events, for example) it is usually the\nevent's source, not its door, so it will be in the `source` block.\n\nNew in 8.10.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the entity representing the door related to this event.  This will be missing\nif the server lacks the RESTStatus licence, or your operator lacks the necessary\nprivileges (such as 'View Site').\n"},"name":{"type":"string","description":"The name the door had when the event occurred."}}},"accessGroup":{"description":"The href of the access group that a cardholder just gained or lost in a 'Membership\nActivated' or 'Membership Expired' event.  Those happen when a group membership's 'from'\nor 'until' time passes.\n\nDEPRECATED for the events generated when an operator creates, modifies, or deletes an\naccess group.  Use the 'modifiedItem' field instead (new in 8.40).\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the access group related to this event."}}},"card":{"description":"Details of the card associated with the event.\n\nVersions prior to 8.60 returned this block and a card number of zero for all access\nevents, even if they did not involve a credential (after a person entered their user code\nat a keypad, for example).  Version 8.60 does not return this block for such events.\n","type":"object","properties":{"facilityCode":{"type":"string","description":"The card's facility code at the time of the event expressed as one letter followed by\nup to five digits.\n"},"number":{"type":"string","description":"The card's number at the time of the event.  Despite the name it may not necessarily\nbe an actual number; mobile card numbers are arbitrary strings, for example.\n\nNote that card numbers are not guaranteed unique.  The combination of facility code,\nissue level, and card number will be unique for card types that have a facility code\nand issue level.\n\nBefore 8.60 this number was a signed 32-bit integer, so numeric card numbers greater\nthan 2^31 came out negative and mobile card numbers were arbitrary.  In 8.60 numeric\ncard numbers are positive and mobile card numbers are their ID strings, which\noperators can set to anything, and default to GUIDs.\n"},"issueLevel":{"type":"integer","description":"The issue level of the card at the time.\n"}}},"modifiedItem":{"description":"The href and type of the item that an operator created, changed, or deleted, for those\nkinds of events.\n\nNew in 8.40.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the item that this event modified.  Watch for 404s:  this link will be here\neven for deleted items.\n"},"type":{"type":"object","properties":{"id":{"type":"string","description":"A short alphanum identifying the item's type.\n"},"name":{"type":"string","description":"A human-readable name of the item's type, suitable for display.\n\nThis string is translated using the installation's language pack, and Gallagher\nreserves the right to change item type names in new versions, so you should not do\nanything with this string except show it to a person.\n"}}}}},"next":{"description":"The URL to the search that will return the page of events following this one.  It will\ninclude your search filters and pagination parameters.\n\nThis link is intended for integrations that take great gulps of events and send them to a\ndownstream system.  If it suffers a problem in the middle of a result set, it needs to\nrecord where in the event trail it got up to so that when it restarts it will not miss or\nduplicate events.\n\nNew to 8.70.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference"}}},"previous":{"description":"The URL to the search that will return the page of events preceding this one.  It will\ninclude your search filters and pagination parameters.\n\nThe `previous` link on the first event in a result set will be the same as the `previous`\nlink outside the results, since they both indicate the latest event that preceded the\nresult set.\n\nNew to 8.70.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference"}}},"updates":{"description":"The URL to the [updates](events#get-api-events-updates) call that will return the\npage of events following this one, or wait for one to arrive if there are none.  It will\ninclude your search filters and pagination parameters.\n\nNew to 8.70.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference"}}}}}}},"paths":{"/api/events/updates":{"get":{"tags":["Events"],"summary":"Get new events (or wait)","description":"Poll this link to receive new events that match the specified filters.  If there are none\nready, the call will block until one arrives or a deadline passes.\n\nFor its correct use in various scenarios, see the [use cases](#event-use-cases).  In\nparticular, sleep between calls to reduce load on the server.\n\nThe way this call picks its initial set of events is different from `/api/events`:\n\n- If you follow the link at `events.updates.href` in the results of `GET /api`, it will\n  block until at least one event arrives that meets your search criteria, then return them.\n\n- If you follow the `updates` link from the results of `GET /api/events` or `GET\n  /api/events/updates`, the link will contain a bookmark parameter that causes the server to\n  return the first events that arrived after that bookmark (and that meet your search\n  criteria, of course).  If there are none, it will block until some arrive that do.\n\nThe response will contain an `updates` link back to the same API call with a new bookmark\nthat will cause it to return the next page of results.\n\nEach response will also contain a `next` link that will take you to the non-blocking version\nof the call at [/api/events](events#get-api-events).  However if you are using this\ncall you should not also be using the `next` link:  applications typically use one or the\nother, not both.\n\nHowever long you wait between calls, following a `next` or `updates` link will always return\nthe first events that arrived after your previous call.\n\nDo not code this URL into your application.  Take it from `events.updates.href` in the\nresults of `GET /api`, or from `updates` in the results of `GET /api/events`.\n","parameters":[{"name":"top","in":"query","required":false,"schema":{"maximum":10000,"minimum":1,"type":"integer"},"description":"Sets the maximum number of events to return per page."},{"name":"deadline","in":"query","required":false,"schema":{"maximum":86400,"minimum":1,"type":"integer"},"description":"Sets the number of seconds to wait for an event, if none are ready when you make the call.\nIf none arrive before this number of seconds pass the result set will be empty. If not\nspecified, a default will apply.\n"},{"name":"after","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Removes events that occurred before this time from the result set.  It must be an ISO-8601\ndate or date-time with a timezone.\n\nIt is unlikely you will add this parameter to `GET /api/events/updates`.  However it is a\nvery useful parameter to [/api/events](events#get-api-events), and it will pass from\nthere into the `updates` URL that that call returns.  In that case it has no effect; you\ncan leave it there.\n\nThis will not push the start time of the search into the past.  As described above, the\nsearch will start at the time of the call or after the last event in a previous result set\ndepending on the `pos` parameter.  The `after` parameter reduces the results to those\nevents that _arrived_ after the start time of the search and _occurred_ after the `after`\ntimestamp.  Note that an event's arrival time can be different from its occurrence time.\n"},{"name":"before","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Removes events that occurred at or after this time from the result set.  It must be an\nISO-8601 date or date-time string with a timezone.\n\nIf no events arrive with an occurrence time earlier than this parameter, the call will\neventually time out.\n\nIt is unlikely you will want this parameter in a call to `GET /api/events/updates`.  It\nputs an end-date on the search, which is a very odd thing to do on a call intended to keep\nthe caller up to date with events as they arrive.  If you find yourself using it, you may\nwish to reconsider your approach.\n\nIf you only wish to receive events up to a point in history, use the `before` parameter on\n[/api/events](events#get-api-events), following its `next` block in a loop until you\nget an empty result.  If you only wish to receive events up to a point in the future, use\n`/api/events` again but loop until you receive an event with a date beyond your stopping\npoint.\n"},{"name":"source","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"}},"description":"Restricts events to those whose source item has this ID.  Separate multiple IDs with\ncommas.  Use `/api/items` to search Command Centre's items.\n"},{"name":"type","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"}},"description":"Restricts events to those with this event type ID.  Separate multiple IDs with commas.\n\nUse [the API](events#get-api-events-groups) to see all of Command Centre's event types and groups.  Event\ntype names and IDs rarely change, but the ID is the more stable of the two.  Therefore it\nis probably safer to use that API for reference then hard-code the event type IDs you find\nthere into your application.\n"},{"name":"group","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"}},"description":"Restricts events to those with this event group ID.  Separate multiple IDs with commas.\n\nThe documentation for `/api/events/groups` advises when to filter for event groups instead\nof event types.\n\nLike event types, hard-coding the ID into your application is probably stabler (and\ndefinitely simpler) than searching for it at runtime.\n"},{"name":"cardholder","in":"query","required":false,"schema":{"type":"string"},"description":"Restricts events to those associated with the cardholder with this Command Centre ID.\nSeparate multiple IDs with commas.\n\nExample:  `cardholder=325`\n"},{"name":"division","in":"query","required":false,"schema":{"type":"string"},"description":"Restricts events to those in the division with this ID and its descendant divisions.\nSeparate multiple IDs with commas.\n\nExample:  `division=2,101`\n"},{"$ref":"#/components/parameters/eventfields"},{"name":"pos","in":"query","required":false,"schema":{"type":"integer","minimum":0},"description":"INTERNAL USE ONLY.  Retain the 'next' or 'updates' link in your application instead.  This\nis how Command Centre tracks the events you have seen already.  Do not set it yourself.\n"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventSearch"}}}},"403":{"description":"The site does not have a RESTEvents licence."}}}}}}
```

## Get details of an event

> Full details for an event. You could follow the \`href\` in the event summary to get here, but\
> if you are running 8.20 or later you could just use the \`fields\` parameter to add the\
> \`details\` field to the summary results for the same result.<br>

```json
{"openapi":"3.2.0","info":{"title":"Command Centre REST API","version":"2.0"},"tags":[{"name":"Events","description":"Use the GET methods in this API for historical searches or to stay up to date with new events as\nthey occur.  Use the POST method (added in version 8.10) to create events of your own.\n\nThere are no PATCH actions on events, because they are immutable.  If an event is also an alarm\nit carries some changeable state and a log of activity and comments, but the underlying event\nnever changes.\n\nThe API only returns events that are still in Command Centre's database.  It will not return\nevents that have been removed, even if they are in an archive file.\n\n## Location events in 9.00\n\nCommand Centre has about 80 event types that occur when somebody authenticates at a device,\nusually by badging a card.  Some of those event types also contain the access zones that the\nperson started and finished in.  Version 9.00 introduced some improvements that presented the\ncardholder and the two zones to API clients in a consistent way:\n\n  * A new event type `hasLocation` that lets you filter for only those events that reveal a\n    cardholder's location.  If your server is 9.00 or better, use it in the `type` query\n    parameter as you would normally use an integer event type:  `type=hasLocation`.  Gallagher\n    will update this as new versions add more event types.  Do not use it on 8.90 or earlier:\n    those servers will reject it.\n\n  * A new `location` block on events of those types that contains fields containing the\n    cardholder and their location.\n\nFor more on using these new features, see the relevant use case below (search for 'location').\n\n## Event use cases\n\n### Downloading the entire event database\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events).  You\n   can add query parameters to alter the search.  If you are running 8.70 or later and there\n   is a danger that you might encounter a problem while processing a batch of events you should\n   also use `fields` to get the `next` link for each event.  Note that this is different from\n   the `next` link you receive at the end of each result set.\n3. Process the events you receive in that call.  If you asked for the `next` field, write the\n   link for each event you successfully process to disk before attempting the next one.  Then,\n   if the worst happens, your client can read that link from disk and pick up where it left off.\n4. If there were results, follow the link at `next.href` and repeat.\n\nIf you then wish to stay up to date, switch to following the link at `updates.href`\n[↪](events#get-api-events-updates) in the results.  That call will block until more\nevents arrive, or a minute passes (approximately).\n\n### Downloading the most recent events\n1. `GET /api`\n2. Take the link at `features.events.events.href` [↪](events#get-api-events) and\n   append `previous=true&top=20`.  Add the appropriate query separator `?` or `&` first,\n   depending on whether there is a query parameter in the URL already, and change the 20 as\n   appropriate.  The default is 1000, which is probably more than you want.\n3. Process the events you receive in that call.\n4. Follow the link at `previous.href` to get earlier events, or `next.href` or `updates.href`\n   for later events.  The last is a long poll, which means that if no events are ready when\n   you make the call it will block until new events arrive.\n\n### Reporting on events over a period.\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) appending\n   `after=2017-01-01Z&before=2017-02-01Z` or whatever timestamps are appropriate (after the\n   correct query separator, `?` or `&`).\n\nRemember that some remote systems take their time sending events to Command Centre, so\ndo not be too hasty running your reports.  If you fire them off at the stroke of\nmidnight, you may miss events that occurred before midnight but have not yet arrived\nat Command Centre.\n\n### Receiving new events as they occur, starting from now\n1. `GET /api`\n2. Follow the link at `features.events.updates.href`\n   [↪](events#get-api-events-updates) adding query parameters containing your search\n   terms.  The call will block until at least one matching event arrives at the server.\n3. Process the events you receive in that call.  Often there is only one:  the first that\n   arrived after you made the call.\n4. Sleep to reduce load on the server.\n5. Loop, following the link at `updates.href` after processing each batch of events.  It will\n   return immediately if there are new events waiting, or it will block until new events arrive.\n   Follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might encounter a problem writing events mid-batch.  Note that that advises using the `next`\n   field, but you will be using the `updates` field, which is the same thing in long-poll form.\n\n### Receiving new events as they occur, starting from now, with no long polls\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) and append\n   `previous=true&top=1`.  Add the appropriate query separator `?` or `&` first, depending on\n   whether there is a query parameter in the URL already.  The call will return one event (which\n   you can ignore) and a `next` link you'll need later.\n5. Sleep and loop, following the link at `next.href` after processing each batch of events.  It\n   will return immediately whether or not there are new events waiting.  Follow the advice in\n   [downloading the entire event database](#downloading-the-entire-event-database) about keeping\n   track of your position if you might encounter a problem writing events mid-batch.\n\n### Receiving new events as they occur, starting in the past\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) appending\n   the query parameter `after=2021-05-08Z` (or whatever timestamp is appropriate).\n3. Process the events you receive in that call.\n4. Sleep to reduce load on the server.\n5. Loop, following the link at `updates.href` after processing each batch of events.  It will\n   return immediately if there are new events waiting, or it will block until new events arrive.\n   Follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might encounter a problem writing events mid-batch.  Note that that advises using the `next`\n   field, but you will be using the `updates` field, which is the same thing in long-poll form.\n\n### Searching for events related to particular cardholders\n1. `GET /api`\n\n2. Follow the link at `features.items.items.href` [↪](items#get-api-items), adding\n   `name=\"your_cardholder_name\"&type=1` to the query after the appropriate separator (`?` or\n   `&`).\n\n   The 'items' controller necessary for that step is available with the RESTEvents licence.  If\n   you also have the RESTCardholders licence you could use the link at\n   `features.cardholders.cardholders.href` [↪](cardholders#get-api-cardholders)\n   instead, adding a separator and `name=\"your_cardholder_name\"`.\n\n   In either case, remove the quotes if you want a substring search and can handle more than\n   one cardholder in the results.\n   \n1. Extract the item ID of your cardholder or cardholders from that page, repeating as\n   necessary for additional cardholders.\n\n1. Follow the link on the `/api` page at `features.events.events.href`\n   [↪](events#get-api-events) appending the separator and `cardholder=XX` or\n   `cardholder=XX,YY,ZZ` with the cardholders' IDs.\n\nTo further improve the efficiency of your search, filter by event types and a time\nrange.\n\n### Searching for events that indicate location or movement\n\nIf your server is running 8.60 or earlier, use the search filter\n`type=20001,20002,20003,20047,20107,15582,15583,15800,15808,42415`.  That is not a complete list\nof movement event types but it includes the popular ones.\n\nIf your server is running 8.70-8.90 inclusive, give your operator the 'View cardholder events'\nprivilege instead of 'View events'.  Then you can request all events, and the server will only\nsend you movements because that is all your operator is permitted to see.\n\nIf your server is running 9.00 or later, the 'View cardholder events' privilege is still an\nexcellent idea to limit your operator's vision but you can also use the search filter\n`type=hasLocation&fields=location` (with a leading `?` or `&` of course, and more fields if you\nneed them).  That will limit the results to location events.\n\nWhen using a server at version 9.00 or better:\n\n1. `GET /api`\n\n2. Get the URL of the head of the event queue by following the link at\n   `features.events.updates.href` [↪](events#get-api-events-updates) appending\n   `type=hasLocation&fields=location` with the appropriate query separator `?` or `&` depending\n   on whether there is a query parameter in the URL already.  The call will block until a new\n   location event arrives.\n\n5. If this is your first time here you will have an array containing one event.  If you looped\n   up from a later step, the array may contain many more.  In any case, process all the events\n   in the results using the advice immediately below about interpreting the `location` block.\n   Also follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might have to abort mid-batch.  Note that that advises using the `next` field, but if you\n   want long polls you will be using the `updates` field.\n\n4. Sleep for a short time to reduce load on the server.\n\n5. Follow the link at `updates.href` for a long poll that waits for new events to arrive, or\n   follow `next.href` for a call that will return immediately even if there are no new events\n   for you.\n\n6. Loop up to process the events you received.\n\nInterpreting the `location` block:\n\n* If you are simply after a person's location and do not care how they arrived there, use the\n  `afterLocation` block inside `location`.  The `canonicalTypeName` field in there will tell you\n  what kind of location it is (reception or access zone).  The [schema\n  definition](models#eventdetail) describes `afterLocation` in more detail.\n\n* If you are after movements, which happen when a door grants a person access or an operator\n  moves them on a tag board or via the API, and happen to some types of visitors when their host\n  moves, ignore all events except those that have a `location.type` of `moved`.  Look at the\n  `afterLocation` to see where they landed.  There will also be a `beforeLocation` if the door\n  had two zones configured on it, in case you're interested in where they came from.  The\n  `canonicalTypeName` field in both blocks will tell you what kinds of item they are.\n\n* If you are after denials, which happen when a person authenticates but fails the access check,\n  look at the events that have a `location.type` of `denied`.  Like 'moved'-type events,\n  `location.afterLocation` will show where they ended up.  The difference is that with\n  'denied'-type events, they started there too.\n\nEach of those fields is covered in the [schema definition](models#eventdetail).\n\nBe aware that the events you receive are limited to those with a source item that is in a\ndivision in which your operator has a privilege that allows viewing events.  In 9.00 those\nprivileges are 'View Events' and 'View Cardholder Events', and of course 'Advanced User'.  That\nmakes this API unsuitable for handling emergencies such as evacuations if your operator's view\nis limited:  if your operator does not have the privilege to view events generated by a\nparticular door, this API will not tell you about movements through that door.\n\n### Searching for events coming from other items\n\nEvents such as 'access granted' and 'zone count maximum' come from doors and access zones.  To\nsearch for them, follow the same process as the previous use case (getting cardholder events)\nbut use the `source` filter parameter instead of `cardholder`.  It will limit the results to\njust those events that came from the items you gave in the query.  If you have the RESTStatus\nlicence you can search for access zones, alarm\nzones, fence zones, macros, outputs, doors, and (in 8.10) inputs.  If you do not, or if your\nsource is not one of those types, use the [items API](items) with a suitable `type` filter.\n\nYou can also use the `type` parameter to limit the events to particular event types.  By doing\nthis you can (for example) subscribe to 'access granted' events from a collection of doors.\n\nNew in v8.70, you can also filter by `relatedItem`. Use this to find events related\nto item or items regardless of the type.\n\n### Creating a new event\n\n1. `GET /api`\n2. POST to the link at `features.events.events.href` [↪](events#post-api-events)\n\nThere are some rules around creating events, so you should first have a careful read of the\n[POST documentation](events#post-api-events).\n\n### Listing all event types\n\n1. `GET /api`\n2. GET the link at `features.events.eventGroups` [↪](events#get-api-events-groups)\n\nThat will return all event types in their groups.\n\n### Event 'updates' versus 'next'\n\nThis expands on the difference between the API endpoints at the ends of the long poll `updates`\nand short poll `next` links that you receive in event searches.  It will make more sense after\nreading the operations' own sections ([long poll](events#get-api-events-updates), [short\npoll](events#get-api-events)).\n\nThe two API calls use the same filters and return the same payloads, including the same\npagination links.  They differ at two times:\n  \n  * On your first call, the short-polling 'events' route will return you the first events in the\n    historical record that meet your search criteria but the long-polling 'updates' route will\n    wait until new events arrive.\n\n  * On the last call, when there are no events that meet your criteria that the server has not\n    sent you already, 'events' will immediately return an empty result set but 'updates' will\n    wait for more to arrive.\n\nThe short poll is appropriate when you do not wish to stay up-to-date.  When you are extracting\nevents from the past, and want to move on to other things as soon as you have them all.\nGenerating reports, basically.\n\nThe long poll is appropriate when you will be continuing to make the call, probably forever,\nbecause you wish to stay current and to not miss any events.\n    \nYou should only be using one of the two.  Using both in the same integration may indicate a\ndesign issue.\n\n## Efficiency tips\n\n* Use search parameters to reduce the filtering burden on the server.\n\n* When downloading a significant number of events, leave `top` at 1000 or more,\n  provided your client can handle results over a megabyte (events are\n  around 1 KB each).  Performance tests have shown that throughput decreases\n  dramatically if `top` is too low.\n\n* If using 8.40 or later, use its `field` query parameter to cut back on the fields the server\n  sends to you.  Not only will it save bandwidth, but it will save the server looking up all\n  those values and serialising them for you.\n    \n* If you are using the `updates` link to keep up to date with events, sleep between calls for as\n  long as your requirements allow.  Doing that will improve the likelihood of your collecting\n  more than one event when it is busy.<br>For example, if Command Centre is generating ten\n  events per second and you do not sleep between REST calls, you will be calling `updates` ten\n  times per second for one event each time.  However if you sleep for two seconds after each\n  call you will receive 20 events at a time, saving CPU and I/O.\n\n## Event field specifiers\n\nWhat you can do with the `fields` query parameter on an events method has improved through the\nversions, so explaining it is a topic in itself.\n\nIn 8.40 and later the values you can list are the same as the field names in the [details\npage](models#eventdetail), plus the special value for a personal data field described\nbelow.  You can pick whichever fields you want, including `defaults`, though we urge you to\nonly list the fields you need.  Anything you wrote for 8.30 or earlier will\nwork in 8.40 as it did before.\n\nIn versions up to 8.30 you can only add fields to the event summary and details pages, not\nremove them.  If you send the parameter it must start with `fields=defaults`.  That gives you\nthe default set.  What you can add after that depends on the version of Command Centre you're\ncalling.\n\nIn 8.10 and earlier the only field you can add is `cardholder.pdf_XXXX`, where XXXX is the ID\nof a PDF.  Find that ID with a query to the [PDFs\ncontroller](pdf-definitions#get-api-personal_data_fields).  Don't forget a\nseparating comma between it and `defaults`.\n\nThat will add a cardholder's PDF to the events that are related to them.\n\nYou can only pick one PDF.  It will only appear on events that have a related cardholder, such\nas access events, because without a cardholder there is no PDF.  The security model applies\ntoo, so it will only appear if your REST operator has the appropriate privileges on that\ncardholder and PDF.\n\nIn 8.20 and later you can also add `details`.  Make sure you have a separating comma after\n`defaults` or `cardholder.pdf_XXXX`.\n\nAn event detail string can be kilobytes long so we left it optional.  It is the only field in\nthe details page that is not in the search results, by the way, so if you are running 8.20 or\nlater you can add it to your search results and you will not need the details page.\n\n| Server version | Valid fields parameter values\n| ------------ | --------------\n| Older than 8.20 | defaults,cardholder.pdf_XXXX \n| 8.20 to 8.30 | defaults,cardholder.pdf_XXXX<br>or<br>defaults,details<br>or<br>defaults,cardholder.pdf_XXXX,details\n| 8.40 and later | any\n\n### Per-event bookmarks\n\nIf you are running 8.70 or later and you put `previous`, `next`, or `updates` in the field\nlist of an event search, the server will add those fields to each event.  All server versions\ninclude links with those names at the end of results, but they are not useful if you crash out\nmidway through processing a batch.  The per-event links, only available in 8.70 and later\nand only on request, give you a place to pick up from without being re-sent the events you\nalready processed.\n\n## Licensing\n\n* The GETs that collect alarms and events require the RESTEvents licence.\n\n* The POST that creates events requires RESTCreateEvents.\n\n* The GET to collect event types requires RESTEvents or RESTCreateEvents.\n"}],"servers":[{"url":"https://127.0.0.1:8904"}],"security":[{"API_key":[]},{"basic":[]}],"components":{"securitySchemes":{"API_key":{"type":"apiKey","name":"Authorization","in":"header","description":"\nClients authenticate by including a pre-shared API key in the `Authorization` header of each\nrequest after an authorisation method of `GGL-API-KEY`:\n\n`Authorization: GGL-API-KEY C774-B01F-D695-AA4B-215F-A158-AC22-ADEB`\n\nFor a fuller description see [API authentication](api-authentication).\n"},"basic":{"type":"http","scheme":"basic","description":"This is HTTP Basic authentication using a blank username and the API key as the password.\n\nExample:  `Authorization: Basic OkM3NzQtQjAxRi1ENjk1LUFBNEItMjE1Ri1BMTU4LUFDMjItQURFQg==`\n\nThat example is equivalent to the example in the description of the api_Key method:\nprepending a colon to the API key beginning with `C774` then encoding it into Base64\nproduces the 56 characters beginning with `OkM3`.\n\nThe colon is a separator between a username, which is blank in our case, and the password,\nwhich is our API key.\n\nFor a fuller description see [API authentication](api-authentication)\n"}},"parameters":{"id":{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"An internal identifier."},"eventfields":{"name":"fields","description":"In 8.40 and later the values you can list are the same as the field names in the [details\npage](models#eventdetail), plus a special field name for a personal data field,\ndescribed next.  You can pick whichever fields you want, including `defaults` though we urge\nyou to avoid that and only ask for the fields you need.\n\nYou can request `cardholder.pdf_XXXX` where XXXX is the ID of a PDF, which you can discover\nwith a query to the [PDFs\ncontroller](pdf-definitions#get-api-personal_data_fields).  That will add a\ncardholder's PDF to the events that are related to them.\n\nYou can only pick one personal data field.  It will only appear on events that have a\nrelated cardholder, such as access events, because without a cardholder there is no personal\ndata.  The security model applies too, so it will only appear if your REST operator has the\nappropriate privileges on that cardholder and PDF.\n","in":"query","schema":{"type":"string","enum":["defaults","details","cardholder.pdf_*","href","id","serverDisplayName","time","message","occurrences","priority","alarm","operator","source","group","type","eventType","division","cardholder","entryAccessZone","exitAccessZone","door","accessGroup","card","modifiedItem","lastOccurrenceTime","previous","next","updates","location"]}}},"schemas":{"EventDetail":{"title":"Event detail","description":"[/api/events/{id}](events#get-api-events-id-) returns one of these.  It contains\neverything from the event summary results, plus some extra fields that are too expensive to\ncompute and return for large result sets.\n\nLike the example in the [summary](models#alarmsummary), this example is forced:  no\nactual Command Centre event will contain all of these fields.\n","allOf":[{"$ref":"#/components/schemas/EventSummary"},{"type":"object","properties":{"lastOccurrenceTime":{"type":"string","format":"date-time","description":"When the event has occurred multiple times due to flooding, this will show the time it\noccurred most recently.  It only appears with `occurrences`, and you will only see it\non the first event in a group.\n"},"details":{"type":"string","description":"The full event details text.  This may be up to 2048 UTF-8 characters, each of which\ncould (theoretically) be four bytes long.\n"},"location":{"type":"object","description":"Added in 9.00, this block gathers together information present in about 80 different event\ntypes that contain a cardholder's location, presenting it in a consistent way.\n\nIt allows a client that is interested in movements to extract what it needs\nwithout needing to know what event types to look for or how they represent:\n\n  * the cardholder whose location the event contains,\n  * the access zone that they started in before the event, and\n  * the access zone or reception where they ended up.\n\nThe location block will only be in a result if you ask for it using the `fields` query\nparameter.\n","properties":{"type":{"type":"string","enum":["moved","observed","denied"],"description":"\nThis enum divides location events into three types:\n\n`moved` means a cardholder moved through a door from one zone to another.  Whether\nan operator moved them using our software, or they did it themselves using a\nplastic card, a mobile credential, biometrics, a QR code, a vehicle plate, or\nsomething implemented by a third-party integration, provided they were granted\naccess, this field's value will be `moved`.\n\n`observed` means they did something that indicated their location, such as logging\nin to a workstation or an alarms terminal, but they did not move.\n\n`denied` means the cardholder authenticated successfully and requested access at a\ndoor but failed the access check.  It also appears on some event types where the\ncardholder did not successfully authenticate; for those events there will be no\n`cardholder` block, covered next.\n"},"cardholder":{"type":"object","description":"\nA block describing the cardholder whose location is recorded by the event.\n\nIt will be missing if the cardholder did not successfully authenticate:  perhaps\nthey used their card but did not complete a second factor.  In most cases, though,\nif a cardholder does not authenticate properly (gets their PIN wrong, for example)\nthere will be no `location` block at all.\n","properties":{"name":{"type":"string","description":"The cardholder's name at the time of the event."},"href":{"type":"string","format":"uri-reference","description":"The cardholder item's href.  This will only be present if the cardholder\nhas not been deleted and your operator has the right to view it.\n"}}},"beforeLocation":{"description":"The href and name of the access zone or reception that the cardholder was in\nbefore this event occurred.  Future versions of Command Centre may add more item\ntypes as \"before locations\" so check its canonical type name, covered in the\n`afterLocation` description below.\n\nThe before location is only useful (and present) for 'moved'-type events, which\nhappen when a cardholder changes location.  For 'observed' and 'denied'-type\nevents, which happen when a cardholder does not move, `afterLocation` shows where\nthey were.\n\nThe name was correct at the time of the event.  It may be missing.\n\nThe href will be missing if your operator does not have the right to view the\nlocation.  That also happens when it is deleted.\n\nIf the cardholder moved from outside there will be a field in this block called\n`outside` with the value `true`, and `canonicaltypeName` and `href` will be\nmissing.\n"},"afterLocation":{"description":"The href and name of the item that indicates the cardholder's location after\nthe event.  For 'observed' and 'denied'-type events, this is also where they\nstarted.\n\nFor 'moved' and 'denied' events in 9.00 it will be an access zone or reception.\n\nFor 'observed' events it could be a workstation or an alarms terminal at which the\nperson authenticated.\n\nFuture versions of Command Centre may add more item types.  So that you can branch\non them, this block and `beforeLocation` contain a field called\n`canonicalTypeName`.  The values it returns are fixed:  it is safe to make\ndecisions based on the value.  We will add new values as Command Centre grows, but\nafter its first appearance an item type's `canonicalTypeName` will not change.\n\nCommon canonical type names are `accesszone`, `reception`, `workstation`, and (for\na T20 alarms terminal that uses the H-Bus protocol) `hbusterminal`.  You can get\nthe full list with the [item types](items#get-api-items-types).\n\nIf they moved \"outside the system\" (entering through a door with no entry zone, or\nexiting through a door with no exit zone), there will be no href or canonical\ntype, but there will be a field called `outside` with the value `true`.\n\nThe href will also be missing if your operator does not have the right to view\ntheir new location.\n\nIf present, the item's name was correct at the time of the event.  It may have\nchanged since.  It will be missing for some event types such as 15583, which\nhappens when an operator moves a cardholder outside the system using an\noperational client.\n"}}}}}]},"EventSummary":{"title":"Event summary","type":"object","description":"`/api/events` and `/api/events/updates` return an array of these, and `/api/events/{id}`\nreturns one with more fields.\n\nThe message and event type in this example indicate an operator attempting to log in with an\nincorrect password, but for the sake of illustration the example also contains references to\nitems that would never appear on such an event.  The card, cardholder, and access zones, for\nexample.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"A link to the details of this event, also usable as an identifier.  It is not globally\nunique but it is unique to the site and, barring a database restore, it will not be\nrecycled by another event or alarm.\n"},"id":{"type":"string","description":"An alphanumeric identifier for this event, unique to the site but not across sites.\nOnce allocated they are not re-used, except after totally resetting the server's state\nby restoring the database.\n"},"serverDisplayName":{"type":"string","description":"The host name of this event's origin server, if it was aggregated from a remote host.\nAbsent for local events.\n\nNote that this is not the descriptive name of the remote server's item, but the host name\nused for address resolution.\n\nNew to 8.40.\n"},"time":{"type":"string","format":"date-time","description":"The time the event occurred."},"message":{"type":"string","description":"The event's message."},"occurrences":{"type":"integer","description":"If an event arrives with the same essential properties as a previous event, the server\nwill start counting them.  Each event is still individually addressable and will appear in\nthe API as normal, but the first in the\ngroup will also have this property.  It only appears on the first, and it does not appear\nif the event is a singleton.\n\nIf present on an event's detail or alarm page, there will also be a `lastOccurrenceTime`.\n\nOutside of the `alarm` block, which contains an alarm's state, this is the only field on\nan event that can change.\n","minimum":2},"priority":{"type":"integer","description":"Numeric priority.  9 is critical and 0 is not an event.","minimum":0,"maximum":9},"alarm":{"type":"object","description":"If an event is also an alarm, this object will contain\nits state and a link to its details page in the alarms controller.\n\nOnly the first event in a group (see the `occurrences` field) can become an alarm.\n","properties":{"state":{"description":"Alarms start unacknowledged.  Acknowledging or processing them changes that.","type":"string","enum":["unacknowledged","acknowledged","processed"]},"href":{"type":"string","format":"uri-reference","description":"Link to the alarm entity corresponding to the event. GET the href for full alarm details."}}},"operator":{"description":"The href and name of the operator or system behind this event.  This will appear when an operator\nhas modified an item.  New in v8.00.\n\nThe item he or she modified will appear in the `modifiedItem` block (added in 8.40).\n\n***Change is coming.***\n\nThe operator may not be a cardholder.  A version of Command Centre after 9.30 will\nreturn events where the operator item is of a different kind.  In that case, the\n`operator` block will also contain a `canonicalTypeName` field telling you what kind of\nitem is at the other end of the href.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the operator who caused this event by editing an item.  New in 8.00."},"name":{"type":"string","description":"The name the operator held at the time.  New in 8.40."}}},"source":{"type":"object","description":"ID and name of the source of the event, as recorded at the time of the event.","properties":{"id":{"type":"string","description":"The alphanumeric ID of the event source item.  Search for events with the same source\nas this one with `source=321` in the query parameters.\n"},"name":{"type":"string","description":"This could be different from the current name of the source item."},"href":{"type":"string","format":"uri-reference","description":"Link to the source item.  New in 8.00."}}},"group":{"type":"object","description":"ID and name of the event group this event belongs to.  Do not confuse this with an access\ngroup or operator group:  this is the event type group to which the event's type belongs.\nThere are about 150 and you can list them at\n[/events/groups](events#get-api-events-groups).\n","properties":{"id":{"type":"string","description":"The alphanumeric ID of the event group.  Search for events of the same rough category\nas this one with `type=35` in the query parameters.\n"},"name":{"type":"string","description":"The name of the event group."}}},"type":{"type":"object","description":"ID and name of the event's type.  There is a long list of them at\n[/events/groups](events#get-api-events-groups).\n","properties":{"id":{"type":"string","description":"The alphanumeric ID of the event type.  To search for events of the same type as this\nexample, put `type=23035` in the query parameters of\n[/events](events#get-api-events).\n"},"name":{"type":"string","description":"The name of the event type."}}},"eventType":{"description":"ID and name of the event's or alarm's type.  There is a long list of them at\n[/events/groups](events#get-api-events-groups).\n\nUnlike the `type` field, this has the same format in an event as it does in an alarm.\n\nAdded in 8.90.  Because it is a new field, it does not appear by default.  Ask for it using\nthe `fields` parameter.\n","type":"object"},"division":{"type":"object","description":"ID, name, and href of the event's division (which is the division of the event's source\nitem, for most event types).\n","properties":{"id":{"type":"string","description":"The alphanumeric ID of the event's division.  Search for other events from items in\nthe same division as this example by putting `division=2` in the query parameters.\n"},"href":{"type":"string","format":"uri-reference","description":"The link to the division item."},"name":{"type":"string","description":"The division's name.  Added in 8.40."}}},"cardholder":{"type":"object","description":"Summary information about an event's cardholder, if there is one.  This will be the\ncardholder who badged their card at a door in an access event, or the cardholder an\noperator modified in an operator event.  Search for other events related to this example's\ncardholder with `cardholder=325` in the query parameters.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the cardholder entity representing the cardholder of the event.  GET the href\nfor full details.\n"},"id":{"type":"string","description":"The alphanumeric ID of the cardholder associated with this event."},"name":{"type":"string","description":"In versions up to and including 8.10 this is the current name of the cardholder.  In\n8.20 it is the name of the cardholder at the time of the event.\n"},"firstName":{"type":"string","description":"The current value of the firstName field of this cardholder.  Added in 8.20."},"lastName":{"type":"string","description":"The current value of the lastName field of this cardholder.  Added in 8.20."}}},"entryAccessZone":{"description":"The name and href of the entry access zone related to the event.  In the case of card\nevents, it is the zone into which a cardholder was attempting to gain access.\n\nThat is true for successful entries, successful exits, and access denials.  Regardless of\nwhether the cardholder badged at the entry or exit reader, this field refers to the zone\nthat he or she attempted to access.\n\nFor example, for 'Card entry granted' events this field will contain the door's entry\nzone, but for 'Card exit granted' events this field will contain the door's _exit_ zone,\nbecause 'exit granted' means the cardholder was in the door's entry zone, badged at its\nexit reader, and was granted access to its exit zone.  Think of it as going through a door\nin its reverse direction.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the access zone entity representing the entry access zone related to this\nevent.  GET the href for the access zone's full details.  This will be missing if the\nserver lacks the RESTStatus licence, or your operator lacks the necessary privileges\n(such as 'View Site').\n"},"name":{"type":"string","description":"The current name of the access zone.  Expect a future version of Command Centre to\nchange this to the name of the access zone at the time of the event.\n"},"id":{"type":"string","description":"Deprecated."}}},"exitAccessZone":{"description":"The name and href of the exit access zone related to the event.  In card events, it is the\nzone from which a cardholder was attempting to leave, if the door had an exit zone\nconfigured (many do not).\n\nThat is true for successful entries, successful exits, and access denials.  Regardless of\nwhether the cardholder badged at the entry or exit reader, this field refers to the zone\nthat he or she attempted to leave.\n\nFor example, for 'Card entry granted' events this field will contain the door's exit zone,\nif there was one, but for 'Card exit granted' events this field will contain the door's\n_entry_ zone.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the access zone entity representing the exit access zone related to this\nevent.  This will be missing if the server lacks the RESTStatus licence, or your\noperator lacks the necessary privileges (such as 'View Site').\n"},"name":{"type":"string","description":"The current name of the exit access zone.  Expect a future version of Command Centre\nto change this to the name of the exit access zone at the time of the event.\n"},"id":{"type":"string","description":"Deprecated."}}},"door":{"description":"The name and href of the door related to the event.  These are not as common as you may\nthink, because when a door is relevant (to card events, for example) it is usually the\nevent's source, not its door, so it will be in the `source` block.\n\nNew in 8.10.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the entity representing the door related to this event.  This will be missing\nif the server lacks the RESTStatus licence, or your operator lacks the necessary\nprivileges (such as 'View Site').\n"},"name":{"type":"string","description":"The name the door had when the event occurred."}}},"accessGroup":{"description":"The href of the access group that a cardholder just gained or lost in a 'Membership\nActivated' or 'Membership Expired' event.  Those happen when a group membership's 'from'\nor 'until' time passes.\n\nDEPRECATED for the events generated when an operator creates, modifies, or deletes an\naccess group.  Use the 'modifiedItem' field instead (new in 8.40).\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the access group related to this event."}}},"card":{"description":"Details of the card associated with the event.\n\nVersions prior to 8.60 returned this block and a card number of zero for all access\nevents, even if they did not involve a credential (after a person entered their user code\nat a keypad, for example).  Version 8.60 does not return this block for such events.\n","type":"object","properties":{"facilityCode":{"type":"string","description":"The card's facility code at the time of the event expressed as one letter followed by\nup to five digits.\n"},"number":{"type":"string","description":"The card's number at the time of the event.  Despite the name it may not necessarily\nbe an actual number; mobile card numbers are arbitrary strings, for example.\n\nNote that card numbers are not guaranteed unique.  The combination of facility code,\nissue level, and card number will be unique for card types that have a facility code\nand issue level.\n\nBefore 8.60 this number was a signed 32-bit integer, so numeric card numbers greater\nthan 2^31 came out negative and mobile card numbers were arbitrary.  In 8.60 numeric\ncard numbers are positive and mobile card numbers are their ID strings, which\noperators can set to anything, and default to GUIDs.\n"},"issueLevel":{"type":"integer","description":"The issue level of the card at the time.\n"}}},"modifiedItem":{"description":"The href and type of the item that an operator created, changed, or deleted, for those\nkinds of events.\n\nNew in 8.40.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference","description":"Link to the item that this event modified.  Watch for 404s:  this link will be here\neven for deleted items.\n"},"type":{"type":"object","properties":{"id":{"type":"string","description":"A short alphanum identifying the item's type.\n"},"name":{"type":"string","description":"A human-readable name of the item's type, suitable for display.\n\nThis string is translated using the installation's language pack, and Gallagher\nreserves the right to change item type names in new versions, so you should not do\nanything with this string except show it to a person.\n"}}}}},"next":{"description":"The URL to the search that will return the page of events following this one.  It will\ninclude your search filters and pagination parameters.\n\nThis link is intended for integrations that take great gulps of events and send them to a\ndownstream system.  If it suffers a problem in the middle of a result set, it needs to\nrecord where in the event trail it got up to so that when it restarts it will not miss or\nduplicate events.\n\nNew to 8.70.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference"}}},"previous":{"description":"The URL to the search that will return the page of events preceding this one.  It will\ninclude your search filters and pagination parameters.\n\nThe `previous` link on the first event in a result set will be the same as the `previous`\nlink outside the results, since they both indicate the latest event that preceded the\nresult set.\n\nNew to 8.70.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference"}}},"updates":{"description":"The URL to the [updates](events#get-api-events-updates) call that will return the\npage of events following this one, or wait for one to arrive if there are none.  It will\ninclude your search filters and pagination parameters.\n\nNew to 8.70.\n","type":"object","properties":{"href":{"type":"string","format":"uri-reference"}}}}}}},"paths":{"/api/events/{id}":{"get":{"tags":["Events"],"summary":"Get details of an event","description":"Full details for an event. You could follow the `href` in the event summary to get here, but\nif you are running 8.20 or later you could just use the `fields` parameter to add the\n`details` field to the summary results for the same result.\n","parameters":[{"$ref":"#/components/parameters/id"},{"$ref":"#/components/parameters/eventfields"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventDetail"}}}},"403":{"description":"The site does not have a RESTEvents licence."},"404":{"description":"That is not the URL of an event, or it is but you do not have privileges to read events\nin its division.\n"}}}}}}
```

## List event types

> Retrieves the list of event type groups and the event types within those groups. Useful for\
> obtaining IDs to use in event filters.  Command Centre ships with about 1000 event types\
> divided into\
> about 150 groups.  Each event type is in one group.\
> \
> 30 groups of event types are set aside for a site's own use.  They are called \_external\_\
> types and groups, because Command Centre does not use them.  A site may rename those 30\
> groups and may create another 970 event types for them.  Out of the factory they have names\
> containing the numbers zero to 29 but do not confuse those numbers with the database IDs.\
> For example, the external event type named 'External Event 0' has ID '4000'.  It is in a\
> group called 'External Event Group 0' with ID '57'.  Further down the line 'External Event\
> 10' has ID '6010' and is in a group with ID '190'.\
> \
> The results of this query vary with:\
> \
> &#x20; \- the server version,\
> &#x20; \- extra Gallagher software installed on the site, and\
> &#x20; \- changes to external event groups and types made by the customer.\
> \
> Event type identifiers do not often change between Command Centre versions, but the types in\
> each group do.  Therefore if you choose to use groups in filters rather than types you may\
> find that your filter catches more or fewer event types after a Command Centre upgrade.\
> That may be desirable if, for example, you are interested in a class of event and you want to\
> grow with CC as it grows new features.  If you do not want that, use types rather than\
> groups.\
> \
> Do not code this URL into your application.  Take it from \`events.eventGroups.href\` in the\
> results of \`GET /api\`.<br>

```json
{"openapi":"3.2.0","info":{"title":"Command Centre REST API","version":"2.0"},"tags":[{"name":"Events","description":"Use the GET methods in this API for historical searches or to stay up to date with new events as\nthey occur.  Use the POST method (added in version 8.10) to create events of your own.\n\nThere are no PATCH actions on events, because they are immutable.  If an event is also an alarm\nit carries some changeable state and a log of activity and comments, but the underlying event\nnever changes.\n\nThe API only returns events that are still in Command Centre's database.  It will not return\nevents that have been removed, even if they are in an archive file.\n\n## Location events in 9.00\n\nCommand Centre has about 80 event types that occur when somebody authenticates at a device,\nusually by badging a card.  Some of those event types also contain the access zones that the\nperson started and finished in.  Version 9.00 introduced some improvements that presented the\ncardholder and the two zones to API clients in a consistent way:\n\n  * A new event type `hasLocation` that lets you filter for only those events that reveal a\n    cardholder's location.  If your server is 9.00 or better, use it in the `type` query\n    parameter as you would normally use an integer event type:  `type=hasLocation`.  Gallagher\n    will update this as new versions add more event types.  Do not use it on 8.90 or earlier:\n    those servers will reject it.\n\n  * A new `location` block on events of those types that contains fields containing the\n    cardholder and their location.\n\nFor more on using these new features, see the relevant use case below (search for 'location').\n\n## Event use cases\n\n### Downloading the entire event database\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events).  You\n   can add query parameters to alter the search.  If you are running 8.70 or later and there\n   is a danger that you might encounter a problem while processing a batch of events you should\n   also use `fields` to get the `next` link for each event.  Note that this is different from\n   the `next` link you receive at the end of each result set.\n3. Process the events you receive in that call.  If you asked for the `next` field, write the\n   link for each event you successfully process to disk before attempting the next one.  Then,\n   if the worst happens, your client can read that link from disk and pick up where it left off.\n4. If there were results, follow the link at `next.href` and repeat.\n\nIf you then wish to stay up to date, switch to following the link at `updates.href`\n[↪](events#get-api-events-updates) in the results.  That call will block until more\nevents arrive, or a minute passes (approximately).\n\n### Downloading the most recent events\n1. `GET /api`\n2. Take the link at `features.events.events.href` [↪](events#get-api-events) and\n   append `previous=true&top=20`.  Add the appropriate query separator `?` or `&` first,\n   depending on whether there is a query parameter in the URL already, and change the 20 as\n   appropriate.  The default is 1000, which is probably more than you want.\n3. Process the events you receive in that call.\n4. Follow the link at `previous.href` to get earlier events, or `next.href` or `updates.href`\n   for later events.  The last is a long poll, which means that if no events are ready when\n   you make the call it will block until new events arrive.\n\n### Reporting on events over a period.\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) appending\n   `after=2017-01-01Z&before=2017-02-01Z` or whatever timestamps are appropriate (after the\n   correct query separator, `?` or `&`).\n\nRemember that some remote systems take their time sending events to Command Centre, so\ndo not be too hasty running your reports.  If you fire them off at the stroke of\nmidnight, you may miss events that occurred before midnight but have not yet arrived\nat Command Centre.\n\n### Receiving new events as they occur, starting from now\n1. `GET /api`\n2. Follow the link at `features.events.updates.href`\n   [↪](events#get-api-events-updates) adding query parameters containing your search\n   terms.  The call will block until at least one matching event arrives at the server.\n3. Process the events you receive in that call.  Often there is only one:  the first that\n   arrived after you made the call.\n4. Sleep to reduce load on the server.\n5. Loop, following the link at `updates.href` after processing each batch of events.  It will\n   return immediately if there are new events waiting, or it will block until new events arrive.\n   Follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might encounter a problem writing events mid-batch.  Note that that advises using the `next`\n   field, but you will be using the `updates` field, which is the same thing in long-poll form.\n\n### Receiving new events as they occur, starting from now, with no long polls\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) and append\n   `previous=true&top=1`.  Add the appropriate query separator `?` or `&` first, depending on\n   whether there is a query parameter in the URL already.  The call will return one event (which\n   you can ignore) and a `next` link you'll need later.\n5. Sleep and loop, following the link at `next.href` after processing each batch of events.  It\n   will return immediately whether or not there are new events waiting.  Follow the advice in\n   [downloading the entire event database](#downloading-the-entire-event-database) about keeping\n   track of your position if you might encounter a problem writing events mid-batch.\n\n### Receiving new events as they occur, starting in the past\n1. `GET /api`\n2. Follow the link at `features.events.events.href` [↪](events#get-api-events) appending\n   the query parameter `after=2021-05-08Z` (or whatever timestamp is appropriate).\n3. Process the events you receive in that call.\n4. Sleep to reduce load on the server.\n5. Loop, following the link at `updates.href` after processing each batch of events.  It will\n   return immediately if there are new events waiting, or it will block until new events arrive.\n   Follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might encounter a problem writing events mid-batch.  Note that that advises using the `next`\n   field, but you will be using the `updates` field, which is the same thing in long-poll form.\n\n### Searching for events related to particular cardholders\n1. `GET /api`\n\n2. Follow the link at `features.items.items.href` [↪](items#get-api-items), adding\n   `name=\"your_cardholder_name\"&type=1` to the query after the appropriate separator (`?` or\n   `&`).\n\n   The 'items' controller necessary for that step is available with the RESTEvents licence.  If\n   you also have the RESTCardholders licence you could use the link at\n   `features.cardholders.cardholders.href` [↪](cardholders#get-api-cardholders)\n   instead, adding a separator and `name=\"your_cardholder_name\"`.\n\n   In either case, remove the quotes if you want a substring search and can handle more than\n   one cardholder in the results.\n   \n1. Extract the item ID of your cardholder or cardholders from that page, repeating as\n   necessary for additional cardholders.\n\n1. Follow the link on the `/api` page at `features.events.events.href`\n   [↪](events#get-api-events) appending the separator and `cardholder=XX` or\n   `cardholder=XX,YY,ZZ` with the cardholders' IDs.\n\nTo further improve the efficiency of your search, filter by event types and a time\nrange.\n\n### Searching for events that indicate location or movement\n\nIf your server is running 8.60 or earlier, use the search filter\n`type=20001,20002,20003,20047,20107,15582,15583,15800,15808,42415`.  That is not a complete list\nof movement event types but it includes the popular ones.\n\nIf your server is running 8.70-8.90 inclusive, give your operator the 'View cardholder events'\nprivilege instead of 'View events'.  Then you can request all events, and the server will only\nsend you movements because that is all your operator is permitted to see.\n\nIf your server is running 9.00 or later, the 'View cardholder events' privilege is still an\nexcellent idea to limit your operator's vision but you can also use the search filter\n`type=hasLocation&fields=location` (with a leading `?` or `&` of course, and more fields if you\nneed them).  That will limit the results to location events.\n\nWhen using a server at version 9.00 or better:\n\n1. `GET /api`\n\n2. Get the URL of the head of the event queue by following the link at\n   `features.events.updates.href` [↪](events#get-api-events-updates) appending\n   `type=hasLocation&fields=location` with the appropriate query separator `?` or `&` depending\n   on whether there is a query parameter in the URL already.  The call will block until a new\n   location event arrives.\n\n5. If this is your first time here you will have an array containing one event.  If you looped\n   up from a later step, the array may contain many more.  In any case, process all the events\n   in the results using the advice immediately below about interpreting the `location` block.\n   Also follow the advice in [downloading the entire event\n   database](#downloading-the-entire-event-database) about keeping track of your position if you\n   might have to abort mid-batch.  Note that that advises using the `next` field, but if you\n   want long polls you will be using the `updates` field.\n\n4. Sleep for a short time to reduce load on the server.\n\n5. Follow the link at `updates.href` for a long poll that waits for new events to arrive, or\n   follow `next.href` for a call that will return immediately even if there are no new events\n   for you.\n\n6. Loop up to process the events you received.\n\nInterpreting the `location` block:\n\n* If you are simply after a person's location and do not care how they arrived there, use the\n  `afterLocation` block inside `location`.  The `canonicalTypeName` field in there will tell you\n  what kind of location it is (reception or access zone).  The [schema\n  definition](models#eventdetail) describes `afterLocation` in more detail.\n\n* If you are after movements, which happen when a door grants a person access or an operator\n  moves them on a tag board or via the API, and happen to some types of visitors when their host\n  moves, ignore all events except those that have a `location.type` of `moved`.  Look at the\n  `afterLocation` to see where they landed.  There will also be a `beforeLocation` if the door\n  had two zones configured on it, in case you're interested in where they came from.  The\n  `canonicalTypeName` field in both blocks will tell you what kinds of item they are.\n\n* If you are after denials, which happen when a person authenticates but fails the access check,\n  look at the events that have a `location.type` of `denied`.  Like 'moved'-type events,\n  `location.afterLocation` will show where they ended up.  The difference is that with\n  'denied'-type events, they started there too.\n\nEach of those fields is covered in the [schema definition](models#eventdetail).\n\nBe aware that the events you receive are limited to those with a source item that is in a\ndivision in which your operator has a privilege that allows viewing events.  In 9.00 those\nprivileges are 'View Events' and 'View Cardholder Events', and of course 'Advanced User'.  That\nmakes this API unsuitable for handling emergencies such as evacuations if your operator's view\nis limited:  if your operator does not have the privilege to view events generated by a\nparticular door, this API will not tell you about movements through that door.\n\n### Searching for events coming from other items\n\nEvents such as 'access granted' and 'zone count maximum' come from doors and access zones.  To\nsearch for them, follow the same process as the previous use case (getting cardholder events)\nbut use the `source` filter parameter instead of `cardholder`.  It will limit the results to\njust those events that came from the items you gave in the query.  If you have the RESTStatus\nlicence you can search for access zones, alarm\nzones, fence zones, macros, outputs, doors, and (in 8.10) inputs.  If you do not, or if your\nsource is not one of those types, use the [items API](items) with a suitable `type` filter.\n\nYou can also use the `type` parameter to limit the events to particular event types.  By doing\nthis you can (for example) subscribe to 'access granted' events from a collection of doors.\n\nNew in v8.70, you can also filter by `relatedItem`. Use this to find events related\nto item or items regardless of the type.\n\n### Creating a new event\n\n1. `GET /api`\n2. POST to the link at `features.events.events.href` [↪](events#post-api-events)\n\nThere are some rules around creating events, so you should first have a careful read of the\n[POST documentation](events#post-api-events).\n\n### Listing all event types\n\n1. `GET /api`\n2. GET the link at `features.events.eventGroups` [↪](events#get-api-events-groups)\n\nThat will return all event types in their groups.\n\n### Event 'updates' versus 'next'\n\nThis expands on the difference between the API endpoints at the ends of the long poll `updates`\nand short poll `next` links that you receive in event searches.  It will make more sense after\nreading the operations' own sections ([long poll](events#get-api-events-updates), [short\npoll](events#get-api-events)).\n\nThe two API calls use the same filters and return the same payloads, including the same\npagination links.  They differ at two times:\n  \n  * On your first call, the short-polling 'events' route will return you the first events in the\n    historical record that meet your search criteria but the long-polling 'updates' route will\n    wait until new events arrive.\n\n  * On the last call, when there are no events that meet your criteria that the server has not\n    sent you already, 'events' will immediately return an empty result set but 'updates' will\n    wait for more to arrive.\n\nThe short poll is appropriate when you do not wish to stay up-to-date.  When you are extracting\nevents from the past, and want to move on to other things as soon as you have them all.\nGenerating reports, basically.\n\nThe long poll is appropriate when you will be continuing to make the call, probably forever,\nbecause you wish to stay current and to not miss any events.\n    \nYou should only be using one of the two.  Using both in the same integration may indicate a\ndesign issue.\n\n## Efficiency tips\n\n* Use search parameters to reduce the filtering burden on the server.\n\n* When downloading a significant number of events, leave `top` at 1000 or more,\n  provided your client can handle results over a megabyte (events are\n  around 1 KB each).  Performance tests have shown that throughput decreases\n  dramatically if `top` is too low.\n\n* If using 8.40 or later, use its `field` query parameter to cut back on the fields the server\n  sends to you.  Not only will it save bandwidth, but it will save the server looking up all\n  those values and serialising them for you.\n    \n* If you are using the `updates` link to keep up to date with events, sleep between calls for as\n  long as your requirements allow.  Doing that will improve the likelihood of your collecting\n  more than one event when it is busy.<br>For example, if Command Centre is generating ten\n  events per second and you do not sleep between REST calls, you will be calling `updates` ten\n  times per second for one event each time.  However if you sleep for two seconds after each\n  call you will receive 20 events at a time, saving CPU and I/O.\n\n## Event field specifiers\n\nWhat you can do with the `fields` query parameter on an events method has improved through the\nversions, so explaining it is a topic in itself.\n\nIn 8.40 and later the values you can list are the same as the field names in the [details\npage](models#eventdetail), plus the special value for a personal data field described\nbelow.  You can pick whichever fields you want, including `defaults`, though we urge you to\nonly list the fields you need.  Anything you wrote for 8.30 or earlier will\nwork in 8.40 as it did before.\n\nIn versions up to 8.30 you can only add fields to the event summary and details pages, not\nremove them.  If you send the parameter it must start with `fields=defaults`.  That gives you\nthe default set.  What you can add after that depends on the version of Command Centre you're\ncalling.\n\nIn 8.10 and earlier the only field you can add is `cardholder.pdf_XXXX`, where XXXX is the ID\nof a PDF.  Find that ID with a query to the [PDFs\ncontroller](pdf-definitions#get-api-personal_data_fields).  Don't forget a\nseparating comma between it and `defaults`.\n\nThat will add a cardholder's PDF to the events that are related to them.\n\nYou can only pick one PDF.  It will only appear on events that have a related cardholder, such\nas access events, because without a cardholder there is no PDF.  The security model applies\ntoo, so it will only appear if your REST operator has the appropriate privileges on that\ncardholder and PDF.\n\nIn 8.20 and later you can also add `details`.  Make sure you have a separating comma after\n`defaults` or `cardholder.pdf_XXXX`.\n\nAn event detail string can be kilobytes long so we left it optional.  It is the only field in\nthe details page that is not in the search results, by the way, so if you are running 8.20 or\nlater you can add it to your search results and you will not need the details page.\n\n| Server version | Valid fields parameter values\n| ------------ | --------------\n| Older than 8.20 | defaults,cardholder.pdf_XXXX \n| 8.20 to 8.30 | defaults,cardholder.pdf_XXXX<br>or<br>defaults,details<br>or<br>defaults,cardholder.pdf_XXXX,details\n| 8.40 and later | any\n\n### Per-event bookmarks\n\nIf you are running 8.70 or later and you put `previous`, `next`, or `updates` in the field\nlist of an event search, the server will add those fields to each event.  All server versions\ninclude links with those names at the end of results, but they are not useful if you crash out\nmidway through processing a batch.  The per-event links, only available in 8.70 and later\nand only on request, give you a place to pick up from without being re-sent the events you\nalready processed.\n\n## Licensing\n\n* The GETs that collect alarms and events require the RESTEvents licence.\n\n* The POST that creates events requires RESTCreateEvents.\n\n* The GET to collect event types requires RESTEvents or RESTCreateEvents.\n"}],"servers":[{"url":"https://127.0.0.1:8904"}],"security":[{"API_key":[]},{"basic":[]}],"components":{"securitySchemes":{"API_key":{"type":"apiKey","name":"Authorization","in":"header","description":"\nClients authenticate by including a pre-shared API key in the `Authorization` header of each\nrequest after an authorisation method of `GGL-API-KEY`:\n\n`Authorization: GGL-API-KEY C774-B01F-D695-AA4B-215F-A158-AC22-ADEB`\n\nFor a fuller description see [API authentication](api-authentication).\n"},"basic":{"type":"http","scheme":"basic","description":"This is HTTP Basic authentication using a blank username and the API key as the password.\n\nExample:  `Authorization: Basic OkM3NzQtQjAxRi1ENjk1LUFBNEItMjE1Ri1BMTU4LUFDMjItQURFQg==`\n\nThat example is equivalent to the example in the description of the api_Key method:\nprepending a colon to the API key beginning with `C774` then encoding it into Base64\nproduces the 56 characters beginning with `OkM3`.\n\nThe colon is a separator between a username, which is blank in our case, and the password,\nwhich is our API key.\n\nFor a fuller description see [API authentication](api-authentication)\n"}},"schemas":{"EventGroups":{"title":"Event groups","description":"Calls to `/api/events/groups/` return this object, which is a named array of groups of event types.","type":"object","properties":{"eventGroups":{"type":"array","description":"An array of event group objects.  There will be about 150.  Most groups contain fewer than 100 event types;  one contains around 200.","items":{"type":"object","properties":{"id":{"type":"string","description":"The alphanumeric ID of the event group.  Use this ID in the `group` filter when requesting events."},"name":{"type":"string","description":"The name of the event group."},"eventTypes":{"type":"array","description":"An array of all the event types in the group.","items":{"type":"object","properties":{"href":{"type":"string","format":"uri-reference"},"id":{"type":"string","description":"The alphanumeric ID of the event type.  Use this ID in the `type` filter when requesting events."},"name":{"type":"string"}}}}}}}}}}},"paths":{"/api/events/groups":{"get":{"tags":["Events"],"summary":"List event types","description":"Retrieves the list of event type groups and the event types within those groups. Useful for\nobtaining IDs to use in event filters.  Command Centre ships with about 1000 event types\ndivided into\nabout 150 groups.  Each event type is in one group.\n\n30 groups of event types are set aside for a site's own use.  They are called _external_\ntypes and groups, because Command Centre does not use them.  A site may rename those 30\ngroups and may create another 970 event types for them.  Out of the factory they have names\ncontaining the numbers zero to 29 but do not confuse those numbers with the database IDs.\nFor example, the external event type named 'External Event 0' has ID '4000'.  It is in a\ngroup called 'External Event Group 0' with ID '57'.  Further down the line 'External Event\n10' has ID '6010' and is in a group with ID '190'.\n\nThe results of this query vary with:\n\n  - the server version,\n  - extra Gallagher software installed on the site, and\n  - changes to external event groups and types made by the customer.\n\nEvent type identifiers do not often change between Command Centre versions, but the types in\neach group do.  Therefore if you choose to use groups in filters rather than types you may\nfind that your filter catches more or fewer event types after a Command Centre upgrade.\nThat may be desirable if, for example, you are interested in a class of event and you want to\ngrow with CC as it grows new features.  If you do not want that, use types rather than\ngroups.\n\nDo not code this URL into your application.  Take it from `events.eventGroups.href` in the\nresults of `GET /api`.\n","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventGroups"}}}},"403":{"description":"The site does not have the RESTEvents or RESTCreateEvents licence."}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://help.security.gallagher.com/knowledge-hub/developer/rest-api/events.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
