> 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/access-groups.md).

# Access Groups

These methods give you access to the access groups in Command Centre. You can search for groups, see their lineage, and list their cardholder members. In 8.40 or later you can see how they affect those members. In 9.30 and later you can create, modify, and delete them.

Your REST operator will need the 'View' or 'Edit Access Groups' operator privileges for the GETs, and 'Edit Access Groups' for the POST and PATCH.

These methods also provide the links you need to manage memberships. Those links are hrefs to cardholders, to which you would send PATCH requests containing your updates. Your REST operator will need 'Edit Cardholders' privilege on the cardholder for that.

### Use cases

#### Finding members of an access group, and managing memberships.

1. `GET /api`.
2. Follow the link at `features.accessGroups.accessGroups.href` ↪ adding search terms, and setting `top` high to save pagination.
3. Find your access group in the results.
4. The link at `cardholders` ↪ returns the cardholders who have *direct* membership of your group. This is only a subset of the cardholders who are affected by that group, as the groups that list this group as their parent inherit its effects recursively. If you are after every cardholder who has *effective* membership of your group, follow the group's href to get its detail page, which includes its child groups in an array called `children`. In a depth-first traversal you would recurse down through the hrefs in that array before proceeding.
5. Get the link at `cardholders` (which is the same on the search results and the details page), look in that cardholder's `accessGroups` array, and manage each membership as you require. Send a DELETE to a membership's href to remove it, or an HTTP PATCH to the cardholder href to update it.

#### Building the group hierarchy.

1. `GET /api`.
2. Follow the link at `features.accessGroups.accessGroups.href` ↪. If you follow the efficiency tips in the cardholder section you will add `top` and `sort` parameters.
3. Record each group's href, name (if you intend to display the results), and `parent.href`, if it is there. An access group may have no parents or one parent, never more.
4. Follow the link at `next.href`, if there is one, and repeat.

You can now assemble the groups into a tree.

### Licensing

Reading access groups and managing access group memberships are enabled by the RESTCardholders licence. Creating, deleting, or modifying access group items is coming soon.

## Search access groups

> \
> This returns access groups matching your search criteria.\
> \
> The result will contain no more than 100 or 1000 groups depending on your version; you\
> should follow the \`next\` link, if it is present, to collect the next batch.\
> \
> When you have loaded all the access groups there will be no \`next\` link.\
> \
> If your result set is empty it means your operator does not have the privilege to view any\
> access groups.  Perhaps there are none in the divisions in which your operator has 'View\
> access groups' or 'Edit access groups', or your operator has no privileges at all.\
> \
> This request does not return the group's cardholders.  That would make the results unwieldy.\
> Instead, it provides a separate link.\
> \
> Adding, deleting, or modifying access groups between calls to this API will not affect the\
> pagination of its results if you sort by ID.\
> \
> You can find the URL for this call in the \`features.accessGroups.accessGroups.href\` field of\
> \`/api\`.  In the interest of forward compability, \[do not build it\
> yourself]\(forward-compatibility-hateoas).<br>

```json
{"openapi":"3.2.0","info":{"title":"Command Centre REST API","version":"2.0"},"tags":[{"name":"Access Groups","description":"\nThese methods give you access to the access groups in Command Centre.  You can search for\ngroups, see their lineage, and list their cardholder members. In 8.40 or later you can see how\nthey affect those members.  In 9.30 and later you can create, modify, and delete them.\n\nYour REST operator will need the 'View' or 'Edit Access Groups' operator privileges for the\nGETs, and 'Edit Access Groups' for the POST and PATCH.\n\nThese methods also provide the links you need to manage memberships.  Those links are hrefs to\ncardholders, to which you would send [PATCH](models#cardholderpatchexample) requests\ncontaining your updates.  Your REST operator will need 'Edit Cardholders' privilege on the\ncardholder for that.\n\n## Use cases\n\n### Finding members of an access group, and managing memberships.\n\n1. `GET /api`.\n2. Follow the link at `features.accessGroups.accessGroups.href`\n   [↪](access-groups#get-api-access_groups) adding search terms, and setting `top` high to save\n   pagination.\n3. Find your access group in the results.\n\n4. The link at `cardholders` [↪](access-groups#get-api-access_groups-id-cardholders) returns the\ncardholders who have *direct* membership of your group.  This is only a subset of the\ncardholders who are affected by that group, as the groups that list this group as their parent\ninherit its effects recursively.  If you are after every cardholder who has *effective*\nmembership of your group, follow the group's href to get its detail page, which includes its\nchild groups in an array called `children`.  In a depth-first traversal you would recurse down\nthrough the hrefs in that array before proceeding.\n\n5. Get the link at `cardholders` (which is the same on the search results and the details page),\nlook in that cardholder's `accessGroups` array, and manage each membership as you require.  Send\na DELETE to a membership's href to remove it, or an HTTP PATCH to the cardholder href to update\nit.\n\n### Building the group hierarchy.\n\n1. `GET /api`.\n2. Follow the link at `features.accessGroups.accessGroups.href`\n   [↪](access-groups#get-api-access_groups).  If you follow the efficiency tips in the cardholder\n   section you will add `top` and `sort` parameters.\n3. Record each group's href, name (if you intend to display the results), and `parent.href`,\n   if it is there.  An access group may have no parents or one parent, never more.\n4. Follow the link at `next.href`, if there is one, and repeat.\n\nYou can now assemble the groups into a tree.\n\n## Licensing\n\nReading access groups and managing access group memberships are enabled by the RESTCardholders\nlicence.  Creating, deleting, or modifying access group items is coming soon.\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":{"sort":{"name":"sort","in":"query","schema":{"type":"string","enum":["id","name","-id","-name"]},"required":false,"description":"Changes the sort field between database ID and name.\n\nIf you prefix `id` or `name` with a minus sign (ASCII 45), the sort order is reversed.\n\nThere are two very strong reasons to sort by ID:\n\n1. Sorting by name carries a risk of missing or duplicating objects if your result set spans\n   multiple pages and another operator is editing the database while your REST client is\n   enumerating them.  This is known as \"page drift.\"  Sorting by ID does not carry that risk.\n2. Following a `next` link is _dramatically_ quicker when sorting by ID.\n\nWe _strongly_ recommend sorting by ID.  In case you were still in doubt, we will do that by\ndefault in a future version of Command Centre.\n\nThe server silently ignores anything except the options listed here.\n"},"name":{"name":"name","in":"query","schema":{"type":"string"},"description":"Limits the returned items to those with a name that matches this string.  Without surrounding\nquotes or a percent sign or underscore, it is a substring match; surround the parameter with\ndouble quotes `\"...\"` for an exact match.  Without quotes, a percent sign `%` will match any\nsubstring and an underscore will match any single character.\n\nThe search is always case-insensitive.  Results are undefined if you do a substring search for\nthe empty string (`name=`).  You will receive no items if you search for those with no name\n(`name=\"\"`), as all items must have a name.\n\nSearch parameters are ANDed together.\n"},"division":{"name":"division","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":false,"description":"Limits the returned items to those that are in these divisions.\n\nThat includes all the items in those divisions' child divisions, because Command Centre treats\nitems as though they are also in their division's parent, and its parent, and so on up to the\nroot division.\n\nSeparate the IDs of the divisions in you are interested with commas.  Item IDs are short\nalphanumeric strings, not URLs.\n\nResults are undefined if you provide an ID that is not in the form of a division ID.\n\nSearch parameters are ANDed together.\n"},"directDivision":{"name":"directDivision","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":false,"description":"Restricts items to those whose division is in this list.\n\nUnlike `division=`, it does not follow ancestry.  That means it will limit the search to items\nthat are directly assigned to the divisions you list, whereas `division` (without the\n`direct`) will also include items that are assigned to their descendants.\n\nList the IDs of the divisions you are interested in separated by commas.  Item IDs are short\nalphanumeric strings, not URLs.\n\nBecause this is the first query parameter we added that contains a capital letter, this will\nbe the first time you have had to think about case sensitivity.  `directDivision` works,\n`directdivision` does not.\n\nResults are undefined if you provide an ID that is not in the form of a division ID.\n\nSearch parameters are ANDed together.\n\nAdded in 9.20.\n"},"description":{"name":"description","in":"query","required":false,"schema":{"type":"string"},"description":"Limits the returned items to those with a description that matches this string.  By default it\nis a substring match; surround it with double quotes `\"...\"` for an exact match.  A `_` will\nmatch any single character, and a `%` will match any substring.  With or without quotes,\nhaving either of these wildcards in the string will anchor it at both ends as though you had\nsurrounded it with `\"`.\n\nThe search is always case-insensitive.  Results are undefined if you search for the empty\nstring (`description=` or `description=\"\"`).\n\nSearch parameters are ANDed together.\n"},"pos":{"name":"pos","in":"query","required":false,"schema":{"type":"integer"},"description":"Reserved for internal use.  You may see it in URLs you receive from the server, but you must never add it yourself."},"skip":{"name":"skip","in":"query","required":false,"schema":{"type":"integer"},"description":"Reserved for internal use.  Do not add it to your queries."}},"schemas":{"AccessGroupSearch":{"title":"Access group search","description":"An array of access group summaries and a `next` link for more.\n","properties":{"results":{"type":"array","description":"An array of access group summaries.","items":{"$ref":"#/components/schemas/AccessGroupSummary"}},"next":{"type":"object","description":"The link to the next page.  Absent if you have retrieved them all.","properties":{"href":{"type":"string","format":"uri-reference"}}}}},"AccessGroupSummary":{"title":"Access group summary","description":"These are the fields in the access group summary.\n","allOf":[{"$ref":"#/components/schemas/AccessGroupCommonFields"},{"type":"object","properties":{"id":{"type":"string","description":"An alphanumeric identifier for this access group.  No API calls use access group\nIDs.\n","readOnly":true},"href":{"type":"string","format":"uri-reference","readOnly":true,"description":"A link to an [access group detail](models#accessgroupdetail) object for this\naccess group.\n"},"notes":{"type":"string"},"cardholders":{"type":"object","readOnly":true,"description":"Following this link lists the group's [direct\nmemberships](access-groups#get-api-access_groups-id-cardholders).\n\nIn v8.00 you will receive this field along with the ID and href in an access\ngroup's details page whether or not you specified it in the fields parameter, but\nif you send the fields parameter to 8.10 you will only get what you asked for.\n","properties":{"href":{"type":"string","format":"uri-reference"}}},"serverDisplayName":{"readOnly":true,"type":"string","description":"If you are running a multi-server installation and this item is homed on a remote server, this\nfield will contain the name of that server.  This field is missing from items that are held on\nthe machine that served the API request.  Added in 8.40.\n\nThis is a read-only field.  The server will ignore it if you send it.\n"}}}]},"AccessGroupCommonFields":{"title":"Access group common fields","description":"These are the fields common to the access group summary, details, POST, and PATCH.\n","type":"object","properties":{"name":{"type":"string","description":"All items have a name.  Command Centre makes one up for you if you omit it when creating\nan item.\n"},"description":{"type":"string"},"division":{"type":"object","description":"Mandatory when creating any access group.  In this example, we want the access group in\ndivision 352.\n"},"parent":{"type":"object","description":"A link to the group's parent.\n\nThis field is optional in a POST because unlike divisions, which must have a parent, an\naccess group can stand alone.  But should you wish it to be a member of another, link it\nhere.\n\nAn access group may be a member of only one other:  multiple inheritance is not possible.\n\nUse the blank string `\"\"` to clear a group's parent in a PATCH.\n"}}}}},"paths":{"/api/access_groups":{"get":{"tags":["Access Groups"],"summary":"Search access groups","description":"\nThis returns access groups matching your search criteria.\n\nThe result will contain no more than 100 or 1000 groups depending on your version; you\nshould follow the `next` link, if it is present, to collect the next batch.\n\nWhen you have loaded all the access groups there will be no `next` link.\n\nIf your result set is empty it means your operator does not have the privilege to view any\naccess groups.  Perhaps there are none in the divisions in which your operator has 'View\naccess groups' or 'Edit access groups', or your operator has no privileges at all.\n\nThis request does not return the group's cardholders.  That would make the results unwieldy.\nInstead, it provides a separate link.\n\nAdding, deleting, or modifying access groups between calls to this API will not affect the\npagination of its results if you sort by ID.\n\nYou can find the URL for this call in the `features.accessGroups.accessGroups.href` field of\n`/api`.  In the interest of forward compability, [do not build it\nyourself](forward-compatibility-hateoas).\n","parameters":[{"$ref":"#/components/parameters/sort"},{"name":"top","in":"query","description":"Sets the maximum number of access groups to return per page.  The default depends on your\nserver version;  you should set it appropriately for your application.\n","schema":{"minimum":1,"type":"integer"}},{"$ref":"#/components/parameters/name"},{"$ref":"#/components/parameters/division"},{"$ref":"#/components/parameters/directDivision"},{"$ref":"#/components/parameters/description"},{"name":"fields","in":"query","description":"Sets the list of fields to return in the search results.  The values you can list are the\nsame as the field names in the [details page](models#accessgroupdetail).  Using it\nyou can return everything on the search page that you would find on the details page.\nSeparate values with commas.\n\nUse the special value `defaults` to return the fields you would have received had you not\ngiven the parameter at all.  Add more after a comma.\n\nTreat the string matches as case sensitive.\n\nIn v8.00 you will receive the href and internal ID even if you didn't ask for them.  In\n8.10 you will not.  If you are going to send the fields parameter and need the href or ID,\ninclude them.\n","style":"form","explode":false,"schema":{"type":"array","default":["defaults"],"items":{"type":"string","enum":["href","id","name","description","parent","division","children","notes","personalDataDefinitions","cardholders","access","saltoAccess","alarmZones","...","defaults"]}}},{"$ref":"#/components/parameters/pos"},{"$ref":"#/components/parameters/skip"}],"responses":{"200":{"description":"Success.\n\nSee the note in the description about privileges if your result set is empty.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessGroupSearch"}}}},"403":{"description":"The site does not have the RESTCardholders licence."}}}}}}
```

## Create an access group

> Creates a new access group, setting its basic fields, parent, PDFs, and some membership\
> defaults.\
> \
> \[Do not code this URL]\(forward-compatibility-hateoas) into your application.  Take\
> it from the \`href\` field in the \`features.accessGroups.accessGroups.href\` field of \`GET\
> /api\`.\
> \
> The POST expects a document in the same format as \[the access group\
> detail]\(access-groups#get-api-access\_groups-id-).  All fields except \`division\` are optional.\
> \
> You will achieve better performance if you combine all you want to achieve into one POST,\
> rather than creating the access group bare with a POST then refining it with PATCHes later.\
> \
> When successful it returns a location header containing the address of the new access group.\
> \
> Note that you can only create one access group per POST.<br>

```json
{"openapi":"3.2.0","info":{"title":"Command Centre REST API","version":"2.0"},"tags":[{"name":"Access Groups","description":"\nThese methods give you access to the access groups in Command Centre.  You can search for\ngroups, see their lineage, and list their cardholder members. In 8.40 or later you can see how\nthey affect those members.  In 9.30 and later you can create, modify, and delete them.\n\nYour REST operator will need the 'View' or 'Edit Access Groups' operator privileges for the\nGETs, and 'Edit Access Groups' for the POST and PATCH.\n\nThese methods also provide the links you need to manage memberships.  Those links are hrefs to\ncardholders, to which you would send [PATCH](models#cardholderpatchexample) requests\ncontaining your updates.  Your REST operator will need 'Edit Cardholders' privilege on the\ncardholder for that.\n\n## Use cases\n\n### Finding members of an access group, and managing memberships.\n\n1. `GET /api`.\n2. Follow the link at `features.accessGroups.accessGroups.href`\n   [↪](access-groups#get-api-access_groups) adding search terms, and setting `top` high to save\n   pagination.\n3. Find your access group in the results.\n\n4. The link at `cardholders` [↪](access-groups#get-api-access_groups-id-cardholders) returns the\ncardholders who have *direct* membership of your group.  This is only a subset of the\ncardholders who are affected by that group, as the groups that list this group as their parent\ninherit its effects recursively.  If you are after every cardholder who has *effective*\nmembership of your group, follow the group's href to get its detail page, which includes its\nchild groups in an array called `children`.  In a depth-first traversal you would recurse down\nthrough the hrefs in that array before proceeding.\n\n5. Get the link at `cardholders` (which is the same on the search results and the details page),\nlook in that cardholder's `accessGroups` array, and manage each membership as you require.  Send\na DELETE to a membership's href to remove it, or an HTTP PATCH to the cardholder href to update\nit.\n\n### Building the group hierarchy.\n\n1. `GET /api`.\n2. Follow the link at `features.accessGroups.accessGroups.href`\n   [↪](access-groups#get-api-access_groups).  If you follow the efficiency tips in the cardholder\n   section you will add `top` and `sort` parameters.\n3. Record each group's href, name (if you intend to display the results), and `parent.href`,\n   if it is there.  An access group may have no parents or one parent, never more.\n4. Follow the link at `next.href`, if there is one, and repeat.\n\nYou can now assemble the groups into a tree.\n\n## Licensing\n\nReading access groups and managing access group memberships are enabled by the RESTCardholders\nlicence.  Creating, deleting, or modifying access group items is coming soon.\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"}},"requestBodies":{"AccessGroupPOST":{"description":"This is the POST body you would use to create an access group.  A `division` is mandatory.\n\nThis is the list of PDFs on an access group.  All the members of the access group will be\nable to have values for the PDFs in this array.\n\nEach element contains the href of a PDF definition.  To build the POST body you can take\nthose from the PDFs controller or other API routes, or copy it from the\n`personalDataDefinitions` block of another access group.\n\nThe GET returns the names of the PDFs, but the POST will ignore them.  If you need to change\nthe name of a PDF, use the PDF controller.\n","required":true,"content":{"application/json":{"schema":{"required":["division"],"allOf":[{"$ref":"#/components/schemas/AccessGroupWriteableFields"},{"type":"object","properties":{"personalDataDefinitions":{"type":"array","items":{"type":"object","properties":{"href":{"description":"The href of the definition of the PDF for the new access group.","type":"string","format":"uri-reference"}}}}}}]}}}}},"schemas":{"AccessGroupWriteableFields":{"title":"Access group writeable fields","description":"These are the fields common to the POST and PATCH.\n","allOf":[{"$ref":"#/components/schemas/AccessGroupCommonFields"},{"type":"object","properties":{"notes":{"type":"string"},"parent":{"type":"object","description":"A link to the group's parent.\n\nThis field is optional in a POST because unlike divisions, which must have a\nparent, an access group can stand alone.  But should you wish it to be a member of\nanother, link it here.\n\nAn access group may be a member of only one other:  multiple inheritance is not\npossible.\n\nUse the blank string `\"\"` to clear a group's parent in a PATCH.\n"},"membershipAutoRemoveExpired":{"type":"boolean","description":"If true, memberships will be removed when their `until` time passes.  If false,\nthey will remain on the cardholder, inactive.\n"},"membershipFromDefault":{"type":"string","description":"When a cardholder is granted membership of this access group without specifying a\n'from' time, this default will apply.  If left blank, such a membership will not\nhave a 'from' time.  It will be effective immediately, provided its 'until' time\nis blank or in the future.\n\nTo clear it, send the blank string `\"\"`.\n","format":"date-time"},"membershipUntilDefault":{"type":"string","description":"When a cardholder is granted membership of this access group without specifying an\n'until' time, this default will apply.  If blank, such a membership will not have\nan 'until' time.  It will be effective until removed.\n\nTo clear it, send the blank string `\"\"`.\n","format":"date-time"}}}]},"AccessGroupCommonFields":{"title":"Access group common fields","description":"These are the fields common to the access group summary, details, POST, and PATCH.\n","type":"object","properties":{"name":{"type":"string","description":"All items have a name.  Command Centre makes one up for you if you omit it when creating\nan item.\n"},"description":{"type":"string"},"division":{"type":"object","description":"Mandatory when creating any access group.  In this example, we want the access group in\ndivision 352.\n"},"parent":{"type":"object","description":"A link to the group's parent.\n\nThis field is optional in a POST because unlike divisions, which must have a parent, an\naccess group can stand alone.  But should you wish it to be a member of another, link it\nhere.\n\nAn access group may be a member of only one other:  multiple inheritance is not possible.\n\nUse the blank string `\"\"` to clear a group's parent in a PATCH.\n"}}}}},"paths":{"/api/access_groups":{"post":{"tags":["Access Groups"],"summary":"Create an access group","description":"Creates a new access group, setting its basic fields, parent, PDFs, and some membership\ndefaults.\n\n[Do not code this URL](forward-compatibility-hateoas) into your application.  Take\nit from the `href` field in the `features.accessGroups.accessGroups.href` field of `GET\n/api`.\n\nThe POST expects a document in the same format as [the access group\ndetail](access-groups#get-api-access_groups-id-).  All fields except `division` are optional.\n\nYou will achieve better performance if you combine all you want to achieve into one POST,\nrather than creating the access group bare with a POST then refining it with PATCHes later.\n\nWhen successful it returns a location header containing the address of the new access group.\n\nNote that you can only create one access group per POST.\n","requestBody":{"$ref":"#/components/requestBodies/AccessGroupPOST"},"responses":{"201":{"description":"Success.","headers":{"location":{"description":"The href of the new access group.","schema":{"type":"string","format":"uri-reference"}}}},"400":{"description":"The body of the POST did not describe a valid access group.\n\nIf you see 'Invalid Access Group JSON object', the server could not parse the JSON in\nthe body of your POST.  Remember to quote all strings, especially those that contain @\nsymbols.\n"},"403":{"description":"The operator does not have a privilege that allows creating access groups.\n"}}}}}}
```

## Get details of an access group

> In addition to the group's vitals and a link to the membership document in the access group\
> search results, this call lists the group's child groups.\
> \
> Note that you can obtain the same results by adding a \`fields\` query parameter to a\
> \[search]\(access-groups#get-api-access\_groups).\
> \
> You can find the URL for this call in the access group search results and in a cardholder's\
> \`accessGroups\` array.  In the interest of forward compability, \[do not build it\
> yourself]\(forward-compatibility-hateoas).<br>

```json
{"openapi":"3.2.0","info":{"title":"Command Centre REST API","version":"2.0"},"tags":[{"name":"Access Groups","description":"\nThese methods give you access to the access groups in Command Centre.  You can search for\ngroups, see their lineage, and list their cardholder members. In 8.40 or later you can see how\nthey affect those members.  In 9.30 and later you can create, modify, and delete them.\n\nYour REST operator will need the 'View' or 'Edit Access Groups' operator privileges for the\nGETs, and 'Edit Access Groups' for the POST and PATCH.\n\nThese methods also provide the links you need to manage memberships.  Those links are hrefs to\ncardholders, to which you would send [PATCH](models#cardholderpatchexample) requests\ncontaining your updates.  Your REST operator will need 'Edit Cardholders' privilege on the\ncardholder for that.\n\n## Use cases\n\n### Finding members of an access group, and managing memberships.\n\n1. `GET /api`.\n2. Follow the link at `features.accessGroups.accessGroups.href`\n   [↪](access-groups#get-api-access_groups) adding search terms, and setting `top` high to save\n   pagination.\n3. Find your access group in the results.\n\n4. The link at `cardholders` [↪](access-groups#get-api-access_groups-id-cardholders) returns the\ncardholders who have *direct* membership of your group.  This is only a subset of the\ncardholders who are affected by that group, as the groups that list this group as their parent\ninherit its effects recursively.  If you are after every cardholder who has *effective*\nmembership of your group, follow the group's href to get its detail page, which includes its\nchild groups in an array called `children`.  In a depth-first traversal you would recurse down\nthrough the hrefs in that array before proceeding.\n\n5. Get the link at `cardholders` (which is the same on the search results and the details page),\nlook in that cardholder's `accessGroups` array, and manage each membership as you require.  Send\na DELETE to a membership's href to remove it, or an HTTP PATCH to the cardholder href to update\nit.\n\n### Building the group hierarchy.\n\n1. `GET /api`.\n2. Follow the link at `features.accessGroups.accessGroups.href`\n   [↪](access-groups#get-api-access_groups).  If you follow the efficiency tips in the cardholder\n   section you will add `top` and `sort` parameters.\n3. Record each group's href, name (if you intend to display the results), and `parent.href`,\n   if it is there.  An access group may have no parents or one parent, never more.\n4. Follow the link at `next.href`, if there is one, and repeat.\n\nYou can now assemble the groups into a tree.\n\n## Licensing\n\nReading access groups and managing access group memberships are enabled by the RESTCardholders\nlicence.  Creating, deleting, or modifying access group items is coming soon.\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":{"AccessGroupDetail":{"title":"Access group detail","description":"[/api/access_groups/{id}](access-groups#get-api-access_groups-id-) returns one of\nthese.  In addition to the basic details, it lists the child groups, privileges, and access\nzones and Salto items to which the group grants access.\n\nThere are brief descriptions of those fields below.  If they fall short, the Configuration\nClient's online documentation is the authority, in particular the section 'Setting up Access\nGroups'.\n","allOf":[{"$ref":"#/components/schemas/AccessGroupSummary"},{"$ref":"#/components/schemas/AccessGroupPDFs"},{"type":"object","properties":{"children":{"type":"array","description":"Names and links for the groups that claim this one as a parent.  This array does not\ninclude the children's children.\n\n**Notice of breaking change**.  This field being present and empty when the group has\nno children is a break from the API's principle of omitting empty fields, and is\ntherefore a bug.  A future version of Command Centre will not return the `children`\narray if the group has no children.\n","items":{"type":"object","properties":{"href":{"description":"The href of the child access group.","type":"string","format":"uri-reference"},"name":{"description":"The name of the child access group.","type":"string"}}}},"visitor":{"description":"If true, members of an access group with the 'escortVisitors' privilege can\nescort members of this group through a door, provided both groups have access to the\nentry zone.\n\nA group with 'visitor' cannot also have 'escortVisitors', 'lockUnlockAccessZones', or\n'firstCardUnlock', because visitors are not allowed to do those things.\n\nNew to 8.40.\n","type":"boolean"},"escortVisitors":{"description":"If true, members of this group can escort members of a group with the 'visitor'\nprivilege through a door, provided both groups have access to the entry zone.\n\nA group cannot have both 'escortVisitors' and 'visitor'.\n\nNew to 8.40.\n","type":"boolean"},"lockUnlockAccessZones":{"description":"If true, members of this group can use a reader or terminal to change the access mode\nof this group's access zones.  They can do this by logging on, if the reader has a\nscreen and keypad, or by double-badging.\n\nA group cannot have both 'lockUnlockAccessZones' and 'visitor'.\n\nNew to 8.40.\n","type":"boolean"},"enterDuringLockdown":{"description":"If true, members of this group are not subject to lockdown restrictions when\nrequesting to enter its access zones.\n\nNew to 8.40.\n","type":"boolean"},"firstCardUnlock":{"description":"If true, members of this group will change an access zone from secure to free when\nentering it, unlocking all its doors.\n\nA group cannot have both 'firstCardUnlock' and 'visitor'.\n\nNew to 8.40.\n","type":"boolean"},"overrideAperioPrivacy":{"description":"Some Aperio locks have a 'privacy mode' button that room occupants can push when they\ndo not want anyone else coming in.  If this field is true, Aperio locks will ignore\nthat button when members of this group attempt to open them.\n\nThis field will not appear if your site is not licensed for Aperio.\n\nNew to 8.40.\n","type":"boolean"},"aperioOfflineAccess":{"description":"Aperio locks normally refuse to open when offline.  If this field is true, Aperio\nlocks that support it will make an exception for members of this group.\n\nObviously the lock needs to be online long enough to synchronise this setting and the\nmembers of the group before setting it will have an effect.\n\nThis field will not appear if your site is not licensed for Aperio.\n\nNew to 8.40.\n","type":"boolean"},"disarmAlarmZones":{"description":"If true, members of this group can use a reader or terminal to disarm the\ngroup's access zones' alarm zones, either by logging on or double-badging.\n\nNew to 8.40.\n","type":"boolean"},"armAlarmZones":{"description":"If true, members of this group can use a reader or terminal to arm the\ngroup's access zones' alarm zones.\n\nNew to 8.40.\n","type":"boolean"},"hvLfFenceZones":{"description":"If true, members of this group can use a reader or terminal to change the\ngroup's fence zones between 'high voltage' and 'low feel', which will in turn change\nthe exuberance of their energisers.  A group's fence zones are those that use the same\nalarm zones as the group's access zones.\n\nNew to 8.40.\n","type":"boolean"},"viewAlarms":{"description":"If true, members of this group can view alarms and inputs on remote arming\nterminals (\"RATs\") and HBUS terminals.\n\nNew to 8.40.\n","type":"boolean"},"shunt":{"description":"If true, members of this group can shunt (isolate) items using RATs and\nHBUS terminals.\n\nNew to 8.40.\n","type":"boolean"},"lockOutFenceZones":{"description":"If true, members of this group can lock out (de-energise, make safe) fence\nzones using RATs and HBUS terminals.  Like all other access group privileges, this\nonly works on the fence zones to which this group has access.\n\nNew to 8.40.\n","type":"boolean"},"cancelFenceZoneLockout":{"description":"Normally, only the cardholder who locked out a fence zone can cancel the lockout and\nre-energise the fence.  With this privilege, members of this group can\ncancel any lockout on the group's fence zones.\n\nNew to 8.40.\n","type":"boolean"},"ackAll":{"description":"If true, members of this group can acknowledge alarms at a RAT or HBUS\nterminal.\n\nAn access group cannot have both this privilege and 'ackBelowHigh'.\n\nNew to 8.40.\n","type":"boolean"},"ackBelowHigh":{"description":"If true, members of this group can acknowledge alarms at a RAT or HBUS\nterminal, provided the alarms are not at high, very high, or critical priority.\n\nAn access group cannot have both this privilege and 'ackAll'.\n\nNew to 8.40.\n","type":"boolean"},"selectAlarmZone":{"description":"If true, members of this group can choose from a list of the group's alarm zones when\nperforming overrides at RATs and HBUS terminals, rather than having it chosen for them\nby site configuration.\n\nA group can only have this privilege if it also has 'disarmAlarmZones' or\n'armAlarmZones'.  Without one of those there is no point in being able to select an\nalarm zone.\n\nNew to 8.40.\n","type":"boolean"},"armWhileAlarm":{"description":"Normally, a cardholder cannot arm an alarm zone if it has open unshunted inputs.\nWith this privilege, members of the group can force-arm the alarm zone from a RAT or\nHBUS terminal.  What happens then depends on an alarm zone setting.\n\nA group with this privilege will also have 'armAlarmZones' and will not have\n'armWhileActiveAlarm'.\n\nNew to 8.40.\n","type":"boolean"},"armWhileActiveAlarm":{"description":"Normally, a cardholder cannot arm an alarm zone when it has active alarms.  Members of\na group with this privilege can do so from an HBUS terminal, provided they also meet\nother criteria (detailed in the Configuration Client documentation).\n\nA group with this privilege will also have 'armAlarmZones' and will not have\n'armWhileAlarm'.\n\nNew to 8.40.\n","type":"boolean"},"isolateAlarmZones":{"description":"Members of a group with this privilege have the option of isolating open inputs from a\nRAT or HBUS terminal when they are preventing an alarm zone from arming.  Like all\nthese privileges, it only works for the alarm zones on the group's access zones.\n\nTo have this privilege, a group must also have 'armAlarmZones'.\n\nNew to 8.40.\n","type":"boolean"},"access":{"type":"array","readOnly":true,"items":{"type":"object","properties":{"accessZone":{"type":"object","properties":{"name":{"type":"string","readOnly":true},"href":{"type":"string","format":"uri-reference","description":"The API's identifier for an item."}}},"schedule":{"type":"object","properties":{"name":{"type":"string","readOnly":true},"href":{"type":"string","format":"uri-reference","description":"The API's identifier for an item."}}}}},"description":"Names and hrefs of the access zones to which this access group gives access, and the\nschedules that govern it.\n\nThis field is read-only:  you cannot yet change an access group's access via the API.\n\nYour operator needs 'View Schedules' to see schedule hrefs, and 'View Site', 'Edit\nSite', or 'Override' to see access zone hrefs.\n\nNew to 8.40.\n"},"saltoAccess":{"readOnly":true,"type":"array","description":"Types, names, and hrefs of the Salto doors and door groups (\"Salto Access Zones\") to\nwhich this access group gives access, and the schedules that govern it.\n\nWatch those definitions:  a 'Salto Access Zone' is a group of Salto doors, while\nCommand Centre's definition of an access zone is a space into which a cardholder moves\nafter passing through a door.\n\nTherefore if an access group gives access to a Salto Access Zone, it is giving access\nthrough any number of Salto doors.  If you don't have access to the Salto system\nitself you can see the Salto zone/door hierarchy in the Command Centre Configuration\nclient.\n\nNew to 8.40.\n","items":{"description":"Each element in the array contains three blocks:  the Salto item type, the item\nitself, and the controlling schedule.\n","type":"object","properties":{"saltoItemType":{"description":"This block tells you whether the Salto item is a Salto door or a Salto 'access\nzone'.\n","type":"object","properties":{"value":{"type":"string","enum":["saltoAccessZone","saltoDoor"]}}},"saltoItem":{"description":"The name and href of the Salto zone or Salto door to which this access group\ngives access.\n"},"schedule":{"type":"object","properties":{"name":{"type":"string","readOnly":true},"href":{"type":"string","format":"uri-reference","description":"The API's identifier for an item."}}}}}},"alarmZones":{"type":"array","items":{"type":"object","properties":{"alarmZone":{"type":"object","properties":{"name":{"type":"string","readOnly":true},"href":{"type":"string","format":"uri-reference","description":"The API's identifier for an item."}}}}},"description":"Names and hrefs of the alarm zones to which members of this access group have the\n20-odd management privileges listed above.\n\nEach connection between the access group and the alarm zone is in its own block called\n`alarmZone` to leave room for the addition of more fields later.\n\nAdded in 8.40.\n"}}}]},"AccessGroupSummary":{"title":"Access group summary","description":"These are the fields in the access group summary.\n","allOf":[{"$ref":"#/components/schemas/AccessGroupCommonFields"},{"type":"object","properties":{"id":{"type":"string","description":"An alphanumeric identifier for this access group.  No API calls use access group\nIDs.\n","readOnly":true},"href":{"type":"string","format":"uri-reference","readOnly":true,"description":"A link to an [access group detail](models#accessgroupdetail) object for this\naccess group.\n"},"notes":{"type":"string"},"cardholders":{"type":"object","readOnly":true,"description":"Following this link lists the group's [direct\nmemberships](access-groups#get-api-access_groups-id-cardholders).\n\nIn v8.00 you will receive this field along with the ID and href in an access\ngroup's details page whether or not you specified it in the fields parameter, but\nif you send the fields parameter to 8.10 you will only get what you asked for.\n","properties":{"href":{"type":"string","format":"uri-reference"}}},"serverDisplayName":{"readOnly":true,"type":"string","description":"If you are running a multi-server installation and this item is homed on a remote server, this\nfield will contain the name of that server.  This field is missing from items that are held on\nthe machine that served the API request.  Added in 8.40.\n\nThis is a read-only field.  The server will ignore it if you send it.\n"}}}]},"AccessGroupCommonFields":{"title":"Access group common fields","description":"These are the fields common to the access group summary, details, POST, and PATCH.\n","type":"object","properties":{"name":{"type":"string","description":"All items have a name.  Command Centre makes one up for you if you omit it when creating\nan item.\n"},"description":{"type":"string"},"division":{"type":"object","description":"Mandatory when creating any access group.  In this example, we want the access group in\ndivision 352.\n"},"parent":{"type":"object","description":"A link to the group's parent.\n\nThis field is optional in a POST because unlike divisions, which must have a parent, an\naccess group can stand alone.  But should you wish it to be a member of another, link it\nhere.\n\nAn access group may be a member of only one other:  multiple inheritance is not possible.\n\nUse the blank string `\"\"` to clear a group's parent in a PATCH.\n"}}},"AccessGroupPDFs":{"title":"Access group PDFs for GET/POST","description":"This is the list of PDFs on an access group.  All the members of the access group will be\nable to have values for the PDFs in this array.\n\nEach element contains the href of a PDF definition.  To build the POST body you can take\nthose from the PDFs controller or other API routes, or copy it from the\n`personalDataDefinitions` block of another access group.\n\nThe GET returns the names of the PDFs, but the POST will ignore them.  If you need to change\nthe name of a PDF, use the PDF controller.\n","properties":{"personalDataDefinitions":{"type":"array","items":{"type":"object","properties":{"name":{"description":"Read-only.","type":"string","readOnly":true},"href":{"description":"The href of the definition of the PDF for the access group.","type":"string","format":"uri-reference"}}}}}}}},"paths":{"/api/access_groups/{id}":{"get":{"tags":["Access Groups"],"summary":"Get details of an access group","description":"In addition to the group's vitals and a link to the membership document in the access group\nsearch results, this call lists the group's child groups.\n\nNote that you can obtain the same results by adding a `fields` query parameter to a\n[search](access-groups#get-api-access_groups).\n\nYou can find the URL for this call in the access group search results and in a cardholder's\n`accessGroups` array.  In the interest of forward compability, [do not build it\nyourself](forward-compatibility-hateoas).\n","parameters":[{"name":"fields","in":"query","explode":false,"required":false,"schema":{"type":"array","default":["defaults"],"items":{"type":"string","enum":["href","id","name","description","parent","division","children","notes","personalDataDefinitions","access","saltoAccess","alarmZones","...","defaults"]}},"description":"Sets the list of fields to return.  The values you can list are the same as the field\nnames in the [detail results](models#accessgroupdetail).  Use it to return less\ndata than normal.  Separate values with commas.\n\nTreat the string matches as case sensitive.\n\nIn v8.00 you will receive the href and internal ID even if you didn't ask for them.  In\n8.10 you will not.  If you are going to send the fields parameter and need the href or ID,\ninclude them.\n"}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessGroupDetail"}}}},"404":{"description":"That is not the URL of an access group, or the operator does not have a privilege that\nallows viewing it, such as 'Modify Access Control' or 'View Access Groups'.\n"}}}}}}
```

## Remove an access group

> This call removes an access group from Command Centre.\
> \
> You can find the URL for this call in the \[access group\
> search]\(access-groups#get-api-access\_groups) results and in a cardholder's \`accessGroups\`\
> array.  In the interest of forward compability, \[do not build it\
> yourself]\(forward-compatibility-hateoas).<br>

```json
{"openapi":"3.2.0","info":{"title":"Command Centre REST API","version":"2.0"},"tags":[{"name":"Access Groups","description":"\nThese methods give you access to the access groups in Command Centre.  You can search for\ngroups, see their lineage, and list their cardholder members. In 8.40 or later you can see how\nthey affect those members.  In 9.30 and later you can create, modify, and delete them.\n\nYour REST operator will need the 'View' or 'Edit Access Groups' operator privileges for the\nGETs, and 'Edit Access Groups' for the POST and PATCH.\n\nThese methods also provide the links you need to manage memberships.  Those links are hrefs to\ncardholders, to which you would send [PATCH](models#cardholderpatchexample) requests\ncontaining your updates.  Your REST operator will need 'Edit Cardholders' privilege on the\ncardholder for that.\n\n## Use cases\n\n### Finding members of an access group, and managing memberships.\n\n1. `GET /api`.\n2. Follow the link at `features.accessGroups.accessGroups.href`\n   [↪](access-groups#get-api-access_groups) adding search terms, and setting `top` high to save\n   pagination.\n3. Find your access group in the results.\n\n4. The link at `cardholders` [↪](access-groups#get-api-access_groups-id-cardholders) returns the\ncardholders who have *direct* membership of your group.  This is only a subset of the\ncardholders who are affected by that group, as the groups that list this group as their parent\ninherit its effects recursively.  If you are after every cardholder who has *effective*\nmembership of your group, follow the group's href to get its detail page, which includes its\nchild groups in an array called `children`.  In a depth-first traversal you would recurse down\nthrough the hrefs in that array before proceeding.\n\n5. Get the link at `cardholders` (which is the same on the search results and the details page),\nlook in that cardholder's `accessGroups` array, and manage each membership as you require.  Send\na DELETE to a membership's href to remove it, or an HTTP PATCH to the cardholder href to update\nit.\n\n### Building the group hierarchy.\n\n1. `GET /api`.\n2. Follow the link at `features.accessGroups.accessGroups.href`\n   [↪](access-groups#get-api-access_groups).  If you follow the efficiency tips in the cardholder\n   section you will add `top` and `sort` parameters.\n3. Record each group's href, name (if you intend to display the results), and `parent.href`,\n   if it is there.  An access group may have no parents or one parent, never more.\n4. Follow the link at `next.href`, if there is one, and repeat.\n\nYou can now assemble the groups into a tree.\n\n## Licensing\n\nReading access groups and managing access group memberships are enabled by the RESTCardholders\nlicence.  Creating, deleting, or modifying access group items is coming soon.\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"}}},"paths":{"/api/access_groups/{id}":{"delete":{"tags":["Access Groups"],"summary":"Remove an access group","description":"This call removes an access group from Command Centre.\n\nYou can find the URL for this call in the [access group\nsearch](access-groups#get-api-access_groups) results and in a cardholder's `accessGroups`\narray.  In the interest of forward compability, [do not build it\nyourself](forward-compatibility-hateoas).\n","responses":{"200":{"description":"Success."},"204":{"description":"Success."},"400":{"description":"Deleting the access group failed.  This happens when it still has members.\n"},"403":{"description":"The operator has the permission to view the item but not delete it.\n"},"404":{"description":"That is not the URL of an access group or the operator is not privileged to view it.\n"}}}}}}
```

## Update an access group

> This is the call you use to modify fields on an access group.\
> \
> The PATCH expects a document in the same format as the \[access group\
> detail]\(models#accessgroupdetail) but with fewer fields.  Note that you cannot change\
> everything on an access group that the API shows you, such as its membership, access, and\
> permissions.  You can change its basic fields, PDFs, and membership defaults.\
> \
> You can find the URL for this call in the \[access group\
> search]\(access-groups#get-api-access\_groups) results and in a cardholder's \`accessGroups\`\
> array.  In the interest of forward compability, \[do not build it\
> yourself]\(forward-compatibility-hateoas).<br>

```json
{"openapi":"3.2.0","info":{"title":"Command Centre REST API","version":"2.0"},"tags":[{"name":"Access Groups","description":"\nThese methods give you access to the access groups in Command Centre.  You can search for\ngroups, see their lineage, and list their cardholder members. In 8.40 or later you can see how\nthey affect those members.  In 9.30 and later you can create, modify, and delete them.\n\nYour REST operator will need the 'View' or 'Edit Access Groups' operator privileges for the\nGETs, and 'Edit Access Groups' for the POST and PATCH.\n\nThese methods also provide the links you need to manage memberships.  Those links are hrefs to\ncardholders, to which you would send [PATCH](models#cardholderpatchexample) requests\ncontaining your updates.  Your REST operator will need 'Edit Cardholders' privilege on the\ncardholder for that.\n\n## Use cases\n\n### Finding members of an access group, and managing memberships.\n\n1. `GET /api`.\n2. Follow the link at `features.accessGroups.accessGroups.href`\n   [↪](access-groups#get-api-access_groups) adding search terms, and setting `top` high to save\n   pagination.\n3. Find your access group in the results.\n\n4. The link at `cardholders` [↪](access-groups#get-api-access_groups-id-cardholders) returns the\ncardholders who have *direct* membership of your group.  This is only a subset of the\ncardholders who are affected by that group, as the groups that list this group as their parent\ninherit its effects recursively.  If you are after every cardholder who has *effective*\nmembership of your group, follow the group's href to get its detail page, which includes its\nchild groups in an array called `children`.  In a depth-first traversal you would recurse down\nthrough the hrefs in that array before proceeding.\n\n5. Get the link at `cardholders` (which is the same on the search results and the details page),\nlook in that cardholder's `accessGroups` array, and manage each membership as you require.  Send\na DELETE to a membership's href to remove it, or an HTTP PATCH to the cardholder href to update\nit.\n\n### Building the group hierarchy.\n\n1. `GET /api`.\n2. Follow the link at `features.accessGroups.accessGroups.href`\n   [↪](access-groups#get-api-access_groups).  If you follow the efficiency tips in the cardholder\n   section you will add `top` and `sort` parameters.\n3. Record each group's href, name (if you intend to display the results), and `parent.href`,\n   if it is there.  An access group may have no parents or one parent, never more.\n4. Follow the link at `next.href`, if there is one, and repeat.\n\nYou can now assemble the groups into a tree.\n\n## Licensing\n\nReading access groups and managing access group memberships are enabled by the RESTCardholders\nlicence.  Creating, deleting, or modifying access group items is coming soon.\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"}},"requestBodies":{"AccessGroupPATCH":{"description":"The body you would send to an access group PATCH has the same schema as an [access group\nPOST](access-groups#post-api-access_groups) apart from the `personalDataDefinitions`\nblock.\n","required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AccessGroupWriteableFields"},{"type":"object","properties":{"personalDataDefinitions":{"description":"This object can contain two arrays named `add` and `remove`.  Every element\nyou put in those arrays should contain a string called `href` giving the href\nof a PDF that you want to add to or remove from the access group.\n\nIn this example we are adding PDF 5516 and removing 9370.\n","type":"object","properties":{"add":{"type":"array","items":{"type":"object","properties":{"href":{"type":"string","format":"uri-reference"}}}},"remove":{"type":"array","items":{"type":"object","properties":{"href":{"type":"string","format":"uri-reference"}}}}}}}}]}}}}},"schemas":{"AccessGroupWriteableFields":{"title":"Access group writeable fields","description":"These are the fields common to the POST and PATCH.\n","allOf":[{"$ref":"#/components/schemas/AccessGroupCommonFields"},{"type":"object","properties":{"notes":{"type":"string"},"parent":{"type":"object","description":"A link to the group's parent.\n\nThis field is optional in a POST because unlike divisions, which must have a\nparent, an access group can stand alone.  But should you wish it to be a member of\nanother, link it here.\n\nAn access group may be a member of only one other:  multiple inheritance is not\npossible.\n\nUse the blank string `\"\"` to clear a group's parent in a PATCH.\n"},"membershipAutoRemoveExpired":{"type":"boolean","description":"If true, memberships will be removed when their `until` time passes.  If false,\nthey will remain on the cardholder, inactive.\n"},"membershipFromDefault":{"type":"string","description":"When a cardholder is granted membership of this access group without specifying a\n'from' time, this default will apply.  If left blank, such a membership will not\nhave a 'from' time.  It will be effective immediately, provided its 'until' time\nis blank or in the future.\n\nTo clear it, send the blank string `\"\"`.\n","format":"date-time"},"membershipUntilDefault":{"type":"string","description":"When a cardholder is granted membership of this access group without specifying an\n'until' time, this default will apply.  If blank, such a membership will not have\nan 'until' time.  It will be effective until removed.\n\nTo clear it, send the blank string `\"\"`.\n","format":"date-time"}}}]},"AccessGroupCommonFields":{"title":"Access group common fields","description":"These are the fields common to the access group summary, details, POST, and PATCH.\n","type":"object","properties":{"name":{"type":"string","description":"All items have a name.  Command Centre makes one up for you if you omit it when creating\nan item.\n"},"description":{"type":"string"},"division":{"type":"object","description":"Mandatory when creating any access group.  In this example, we want the access group in\ndivision 352.\n"},"parent":{"type":"object","description":"A link to the group's parent.\n\nThis field is optional in a POST because unlike divisions, which must have a parent, an\naccess group can stand alone.  But should you wish it to be a member of another, link it\nhere.\n\nAn access group may be a member of only one other:  multiple inheritance is not possible.\n\nUse the blank string `\"\"` to clear a group's parent in a PATCH.\n"}}}}},"paths":{"/api/access_groups/{id}":{"patch":{"tags":["Access Groups"],"summary":"Update an access group","description":"This is the call you use to modify fields on an access group.\n\nThe PATCH expects a document in the same format as the [access group\ndetail](models#accessgroupdetail) but with fewer fields.  Note that you cannot change\neverything on an access group that the API shows you, such as its membership, access, and\npermissions.  You can change its basic fields, PDFs, and membership defaults.\n\nYou can find the URL for this call in the [access group\nsearch](access-groups#get-api-access_groups) results and in a cardholder's `accessGroups`\narray.  In the interest of forward compability, [do not build it\nyourself](forward-compatibility-hateoas).\n","requestBody":{"$ref":"#/components/requestBodies/AccessGroupPATCH"},"responses":{"200":{"description":"Success.  Future versions will return feedback from the server about your PATCH.\n"},"204":{"description":"Success."},"400":{"description":"The body of the PATCH did not describe a valid access group.  See the body of the\nresponse for help on what went wrong.  It may be that you tried to use the name of\nanother access group:  no two items of the same type can have the same name.  Or you may\nhave tried to set the division to one that is not visible to you, or you may have\nattempted to create a loop in the access group hierarchy.\n"},"403":{"description":"The operator has a privilege that allows viewing the item but not modifying it, or you\ntried to set the division to one you cannot configure, or the server is missing the\nnecessary licence.\n\nYou need the 'Edit Access Groups' privilege on the item you are changing, which means you\nneed on it on the item's current division.  You also need it on the new division, if you\nare changing that.\n"},"404":{"description":"That is not the URL of an access group or your operator does not have the privilege to view\nit.  This probably means you have built the URL yourself instead of taking it from the\nresults of a [GET](access-groups#get-api-access_groups).\n"},"409":{"description":"The item is locked for editing by another operator.  The body of the response will\ntell you which operator is holding the lock.\n"}}}}}}
```

## Get membership of an access group

> \
> This lists all cardholders who are direct members of a particular group.  It does\
> not paginate the results, so there is no \`next\` link.  That can make for a large\
> document, so it omits the group's child groups and their cardholder members.  It\
> is not recursive, in other words.\
> \
> There may be more than one entry per cardholder, because any one cardholder can have many\
> memberships to a group, each with different from and until date-times.\
> \
> If your operator does not have the privilege to view a cardholder item you will receive its\
> name but not its href (since following it would 404).\
> \
> You can find the URL in the \`cardholders\` block of an access group's search results or\
> detail pages.  In the interest of forward compability, \[do not build it\
> yourself]\(forward-compatibility-hateoas).

```json
{"openapi":"3.2.0","info":{"title":"Command Centre REST API","version":"2.0"},"tags":[{"name":"Access Groups","description":"\nThese methods give you access to the access groups in Command Centre.  You can search for\ngroups, see their lineage, and list their cardholder members. In 8.40 or later you can see how\nthey affect those members.  In 9.30 and later you can create, modify, and delete them.\n\nYour REST operator will need the 'View' or 'Edit Access Groups' operator privileges for the\nGETs, and 'Edit Access Groups' for the POST and PATCH.\n\nThese methods also provide the links you need to manage memberships.  Those links are hrefs to\ncardholders, to which you would send [PATCH](models#cardholderpatchexample) requests\ncontaining your updates.  Your REST operator will need 'Edit Cardholders' privilege on the\ncardholder for that.\n\n## Use cases\n\n### Finding members of an access group, and managing memberships.\n\n1. `GET /api`.\n2. Follow the link at `features.accessGroups.accessGroups.href`\n   [↪](access-groups#get-api-access_groups) adding search terms, and setting `top` high to save\n   pagination.\n3. Find your access group in the results.\n\n4. The link at `cardholders` [↪](access-groups#get-api-access_groups-id-cardholders) returns the\ncardholders who have *direct* membership of your group.  This is only a subset of the\ncardholders who are affected by that group, as the groups that list this group as their parent\ninherit its effects recursively.  If you are after every cardholder who has *effective*\nmembership of your group, follow the group's href to get its detail page, which includes its\nchild groups in an array called `children`.  In a depth-first traversal you would recurse down\nthrough the hrefs in that array before proceeding.\n\n5. Get the link at `cardholders` (which is the same on the search results and the details page),\nlook in that cardholder's `accessGroups` array, and manage each membership as you require.  Send\na DELETE to a membership's href to remove it, or an HTTP PATCH to the cardholder href to update\nit.\n\n### Building the group hierarchy.\n\n1. `GET /api`.\n2. Follow the link at `features.accessGroups.accessGroups.href`\n   [↪](access-groups#get-api-access_groups).  If you follow the efficiency tips in the cardholder\n   section you will add `top` and `sort` parameters.\n3. Record each group's href, name (if you intend to display the results), and `parent.href`,\n   if it is there.  An access group may have no parents or one parent, never more.\n4. Follow the link at `next.href`, if there is one, and repeat.\n\nYou can now assemble the groups into a tree.\n\n## Licensing\n\nReading access groups and managing access group memberships are enabled by the RESTCardholders\nlicence.  Creating, deleting, or modifying access group items is coming soon.\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":{"AccessGroupMembership":{"title":"Access group membership","description":"Returned in an array by\n[/api/access_groups/{id}/cardholders](access-groups#get-api-access_groups-id-cardholders),\ncontaining cardholders who are direct members of a particular group.  The array does\nnot contain the group's child groups, or their cardholder members.\n\nEach item contains a cardholder and (possibly) two date-times.  The group membership is active\nif and only if the current time is between 'from' and 'until'.  If 'from' is absent, assume\nthe distant past.  If 'until' is absent, assume the far future.\n\nUse the href in the cardholder block to change the 'from' and 'until', or even the\ngroup, using [cardholder patch](cardholders#patch-api-cardholders-id-).\n\nEach also contains an href at the top level:  DELETE that to remove the membership.\n","properties":{"href":{"type":"string","format":"uri-reference","description":"DELETE this URL to remove the membership.  Do not specify this when creating or\nmodifying a cardholder.\n\nDELETE is the only verb you can use on this URL.  GET will always return a 404.\n"},"cardholder":{"type":"object","description":"The name and href of the member cardholder."},"from":{"type":"string","format":"time-stamp"},"until":{"type":"string","format":"time-stamp"}}}}},"paths":{"/api/access_groups/{id}/cardholders":{"get":{"tags":["Access Groups"],"summary":"Get membership of an access group","description":"\nThis lists all cardholders who are direct members of a particular group.  It does\nnot paginate the results, so there is no `next` link.  That can make for a large\ndocument, so it omits the group's child groups and their cardholder members.  It\nis not recursive, in other words.\n\nThere may be more than one entry per cardholder, because any one cardholder can have many\nmemberships to a group, each with different from and until date-times.\n\nIf your operator does not have the privilege to view a cardholder item you will receive its\nname but not its href (since following it would 404).\n\nYou can find the URL in the `cardholders` block of an access group's search results or\ndetail pages.  In the interest of forward compability, [do not build it\nyourself](forward-compatibility-hateoas).","responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"cardholders":{"type":"array","items":{"$ref":"#/components/schemas/AccessGroupMembership"}}}}}}},"404":{"description":"The ID is invalid, or it is valid but you do not have privileges for the access group.\nCheck the body of the result for a description of the problem.\n"}}}}}}
```


---

# 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/access-groups.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.
