> ## Documentation index
> Fetch the complete documentation index at: https://developer.rhombus.com/llms.txt
> Use it to discover all available pages before exploring further.

# Access Control

> Manage Rhombus access control through the API — list access-controlled doors, remotely unlock, issue and assign credentials, build access groups and grants, and activate lockdown plans.

## Overview

Rhombus access control lets you manage physical entry across your facilities from a single API. Access-controlled doors are backed by Rhombus door controllers and readers, and every unlock, credential, and grant is tied to the same platform that records your camera footage — so each entry event has visual context.

Through the API, you can:

- **List access-controlled doors** and inspect their configuration and live state
- **Remotely unlock** a door for a momentary entry
- **Issue credentials** (such as Wiegand cards) and assign them to users
- **Build access groups and grants** that tie users, doors, and schedules together
- **Activate lockdown plans** to secure a location during an emergency

> **Note**: Looking for touchless visitor entry? The [QR Code Access Control](https://developer.rhombus.com/implementations/qr-code-access-control) guide (currently in beta) covers generating time-bound QR codes that a Rhombus camera reads to unlock a door. This guide covers the broader, generally available access control surface.

## Prerequisites

> **Note**: Before you begin, make sure you have:
>
> - A **Rhombus API key** with access control permissions (generated in the [Rhombus Console](https://console.rhombussystems.com/settings/integrations/api-tokens/) under **Settings → Integrations & Developer Resources → API Tokens**)
> - At least one **access-controlled door** configured with a Rhombus door controller and reader
> - The **UUIDs** of the users, doors, and locations you plan to work with (you can discover door UUIDs with the door listing endpoint below)

All requests are `POST`, target the base URL `https://api2.rhombussystems.com`, and require these headers:

```bash
x-auth-scheme: api-token
x-auth-apikey: YOUR_API_KEY
Content-Type: application/json
```

## List access-controlled doors

Retrieve the access-controlled doors in your organization. The response is paginated: pass an empty body for the first page, then send the returned `lastEvaluatedKey` on subsequent requests until it comes back empty.

```python Python
import requests

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

response = requests.post(
    "https://api2.rhombussystems.com/api/component/findAccessControlledDoors",
    headers=headers,
    json={
        "maxPageSize": 100
    }
)

data = response.json()
for door in data.get("accessControlledDoors", []):
    print(f"{door['name']} ({door['uuid']}) - default state: {door.get('defaultState')}")

# Paginate if more doors remain
next_key = data.get("lastEvaluatedKey")
```

```javascript JavaScript
const response = await fetch('https://api2.rhombussystems.com/api/component/findAccessControlledDoors', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-auth-scheme': 'api-token',
    'x-auth-apikey': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    maxPageSize: 100
  })
});

const data = await response.json();
for (const door of data.accessControlledDoors || []) {
  console.log(`${door.name} (${door.uuid}) - default state: ${door.defaultState}`);
}

const nextKey = data.lastEvaluatedKey;
```

```bash cURL
curl -X POST https://api2.rhombussystems.com/api/component/findAccessControlledDoors \
  -H "Content-Type: application/json" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_API_KEY" \
  -d '{"maxPageSize": 100}'
```

### Request parameters

- **`maxPageSize` (path, integer)**: Maximum number of doors to return in a single page.
- **`lastEvaluatedKey` (path, string)**: Pagination cursor returned by a previous call. Omit it on the first request; supply it to fetch the next page.

### Response

- **`accessControlledDoors` (array)**: The list of access-controlled doors. Key fields per door:

  **door fields**
  - **`uuid` (string)**: Unique identifier for the door. Use this value wherever an `accessControlledDoorUuid` is required.
  - **`name` (string)**: Display name of the door (for example, "Main Entrance").
  - **`locationUuid` (string)**: The location the door belongs to.
  - **`defaultState` (string)**: Baseline access mode, one of `ACCESS_CONTROLLED` or `UNLOCKED`.
  - **`remoteUnlockEnabled` (boolean)**: Whether the door accepts remote unlock requests through the API.
  - **`unlockTimeSec` (integer)**: How long the door stays unlocked after a standard unlock, in seconds.
- **`lastEvaluatedKey` (string)**: Pagination cursor. When present, pass it back in the next request to retrieve additional doors.

> **Tip**: If you only need lightweight door status rather than full configuration, use [`/api/component/findMinimalStateAccessControlledDoors`](https://developer.rhombus.com/api-reference/component-webservice/find-minimal-state-access-controlled-doors-within-the-org), which returns each door plus a compact state shadow.

## Remotely unlock a door

Trigger a momentary unlock on an access-controlled door. The door relocks automatically after its configured unlock time. Remote unlock only works when `remoteUnlockEnabled` is `true` for the target door.

```python Python
import requests

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

response = requests.post(
    "https://api2.rhombussystems.com/api/accesscontrol/unlockAccessControlledDoor",
    headers=headers,
    json={
        "accessControlledDoorUuid": "YOUR_DOOR_UUID"
    }
)

result = response.json()
print(result.get("type"))  # SUCCESS or ERROR
```

```javascript JavaScript
const response = await fetch('https://api2.rhombussystems.com/api/accesscontrol/unlockAccessControlledDoor', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-auth-scheme': 'api-token',
    'x-auth-apikey': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    accessControlledDoorUuid: 'YOUR_DOOR_UUID'
  })
});

const result = await response.json();
console.log(result.type); // SUCCESS or ERROR
```

```bash cURL
curl -X POST https://api2.rhombussystems.com/api/accesscontrol/unlockAccessControlledDoor \
  -H "Content-Type: application/json" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_API_KEY" \
  -d '{"accessControlledDoorUuid": "YOUR_DOOR_UUID"}'
```

- **`accessControlledDoorUuid` (path, string, required)**: The UUID of the door to unlock, from the door listing endpoint.
- **`type` (string)**: Outcome of the request, either `SUCCESS` or `ERROR`.

> **Note**: Every remote unlock is recorded as an access event with footage from the door's associated cameras, giving you a complete audit trail.

## Issue and assign a credential

Credentials are the physical cards or fobs that a reader accepts. This example creates a Wiegand credential and assigns it to a user. Rhombus supports several credential formats — the `createWiegandCredential` endpoint takes a `wiegandFormat` and the fields relevant to that format.

### Create a Wiegand credential

```python Python
import requests
import time

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

now_sec = int(time.time())
one_year_sec = 365 * 24 * 60 * 60

response = requests.post(
    "https://api2.rhombussystems.com/api/accesscontrol/createWiegandCredential",
    headers=headers,
    json={
        "wiegandFormat": "H10301",
        "facilityCode": 42,
        "cardNumber": 10537,
        "userUuid": "YOUR_USER_UUID",
        "startDateEpochSecInclusive": now_sec,
        "endDateEpochSecExclusive": now_sec + one_year_sec
    }
)

credential = response.json().get("credential", {})
print(f"Created credential {credential.get('uuid')} - status {credential.get('workflowStatus')}")
```

```javascript JavaScript
const nowSec = Math.floor(Date.now() / 1000);
const oneYearSec = 365 * 24 * 60 * 60;

const response = await fetch('https://api2.rhombussystems.com/api/accesscontrol/createWiegandCredential', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-auth-scheme': 'api-token',
    'x-auth-apikey': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    wiegandFormat: 'H10301',
    facilityCode: 42,
    cardNumber: 10537,
    userUuid: 'YOUR_USER_UUID',
    startDateEpochSecInclusive: nowSec,
    endDateEpochSecExclusive: nowSec + oneYearSec
  })
});

const { credential } = await response.json();
console.log(`Created credential ${credential.uuid} - status ${credential.workflowStatus}`);
```

```bash cURL
curl -X POST https://api2.rhombussystems.com/api/accesscontrol/createWiegandCredential \
  -H "Content-Type: application/json" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_API_KEY" \
  -d '{
    "wiegandFormat": "H10301",
    "facilityCode": 42,
    "cardNumber": 10537,
    "userUuid": "YOUR_USER_UUID",
    "startDateEpochSecInclusive": 1712620800,
    "endDateEpochSecExclusive": 1744156800
  }'
```

- **`wiegandFormat` (path, string, required)**: The Wiegand card format. One of `H10301`, `D10202`, `H10304`, `HID_CORP1000_STD_35`, `HID_CORP1000_STD_48`, `WIEGAND_64BIT_RAW`, or `CUSTOM`. The fields you populate depend on the format — for the standard 26-bit `H10301` format, supply `facilityCode` and `cardNumber`.
- **`facilityCode` (path, integer)**: Facility (site) code encoded on the card. Used by formats such as `H10301`.
- **`cardNumber` (path, integer)**: Card number encoded on the card.
- **`siteCode` (path, integer)**: Site code, used by formats that encode one separately from the facility code.
- **`companyId` (path, integer)**: Company ID, used by HID Corporate 1000 formats.
- **`value` (path, string)**: Raw credential value. Used by the `WIEGAND_64BIT_RAW` and `CUSTOM` formats.
- **`userUuid` (path, string)**: The user the credential belongs to. When set, the credential is created already assigned to that user.
- **`startDateEpochSecInclusive` (path, integer)**: Start of the credential's validity window, in epoch **seconds** (inclusive).
- **`endDateEpochSecExclusive` (path, integer)**: End of the credential's validity window, in epoch **seconds** (exclusive).

> **Warning**: Credential validity dates are expressed in epoch **seconds**, not milliseconds. Most other Rhombus endpoints use epoch milliseconds, so convert carefully.

The response returns the created `credential` object, including its `uuid`, `lowercaseHexValue`, and `workflowStatus` (`ACTIVE`, `UNASSIGNED`, `SUSPENDED`, or `REVOKED`).

### Assign an existing credential to a user

If a credential already exists (for example, it was created unassigned), assign it to a user by its hex value.

```python Python
import requests

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

response = requests.post(
    "https://api2.rhombussystems.com/api/accesscontrol/assignAccessControlCredential",
    headers=headers,
    json={
        "credentialHexValue": "002a2929",
        "userUuid": "YOUR_USER_UUID"
    }
)
print(response.json())
```

```javascript JavaScript
const response = await fetch('https://api2.rhombussystems.com/api/accesscontrol/assignAccessControlCredential', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-auth-scheme': 'api-token',
    'x-auth-apikey': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    credentialHexValue: '002a2929',
    userUuid: 'YOUR_USER_UUID'
  })
});
console.log(await response.json());
```

```bash cURL
curl -X POST https://api2.rhombussystems.com/api/accesscontrol/assignAccessControlCredential \
  -H "Content-Type: application/json" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_API_KEY" \
  -d '{
    "credentialHexValue": "002a2929",
    "userUuid": "YOUR_USER_UUID"
  }'
```

- **`credentialHexValue` (path, string, required)**: The hex value of the credential to assign.
- **`userUuid` (path, string, required)**: The user to assign the credential to.

> **Tip**: Manage a credential's lifecycle with [`/api/accesscontrol/suspendAccessControlCredential`](https://developer.rhombus.com/api-reference/access-control-webservice/suspend-access-control-credential), [`/api/accesscontrol/unsuspendAccessControlCredential`](https://developer.rhombus.com/api-reference/access-control-webservice/unsuspend-access-control-credential), and [`/api/accesscontrol/revokeAccessControlCredential`](https://developer.rhombus.com/api-reference/access-control-webservice/revoke-access-control-credential). To review a user's credentials, call [`/api/accesscontrol/findAccessControlCredentialByUser`](https://developer.rhombus.com/api-reference/access-control-webservice/find-access-control-credentials-by-user) with their `userUuid`.

## Grant access with groups and schedules

Rhombus models "who can open which doors, and when" as an **access grant**. A grant links a set of users (directly or through **access groups**) to a set of doors, optionally constrained by a **schedule**. The typical flow is: create a group, add users, then create a grant that ties the group to doors and a schedule.

### Create an access group and add users

```python Python
import requests

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

# Create the group
create = requests.post(
    "https://api2.rhombussystems.com/api/accesscontrol/createAccessControlGroup",
    headers=headers,
    json={
        "name": "Warehouse Staff",
        "description": "Employees allowed into the warehouse"
    }
)
group_uuid = create.json()["group"]["uuid"]

# Add users to it
requests.post(
    "https://api2.rhombussystems.com/api/accesscontrol/addUsersToAccessControlGroup",
    headers=headers,
    json={
        "groupUuid": group_uuid,
        "userUuids": ["USER_UUID_1", "USER_UUID_2"]
    }
)
```

```javascript JavaScript
const headers = {
  'Content-Type': 'application/json',
  'x-auth-scheme': 'api-token',
  'x-auth-apikey': 'YOUR_API_KEY'
};

// Create the group
const create = await fetch('https://api2.rhombussystems.com/api/accesscontrol/createAccessControlGroup', {
  method: 'POST',
  headers,
  body: JSON.stringify({
    name: 'Warehouse Staff',
    description: 'Employees allowed into the warehouse'
  })
});
const groupUuid = (await create.json()).group.uuid;

// Add users to it
await fetch('https://api2.rhombussystems.com/api/accesscontrol/addUsersToAccessControlGroup', {
  method: 'POST',
  headers,
  body: JSON.stringify({
    groupUuid,
    userUuids: ['USER_UUID_1', 'USER_UUID_2']
  })
});
```

```bash cURL
# 1. Create the group
curl -X POST https://api2.rhombussystems.com/api/accesscontrol/createAccessControlGroup \
  -H "Content-Type: application/json" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_API_KEY" \
  -d '{"name": "Warehouse Staff", "description": "Employees allowed into the warehouse"}'

# 2. Add users (use the group uuid from the response above)
curl -X POST https://api2.rhombussystems.com/api/accesscontrol/addUsersToAccessControlGroup \
  -H "Content-Type: application/json" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_API_KEY" \
  -d '{"groupUuid": "GROUP_UUID", "userUuids": ["USER_UUID_1", "USER_UUID_2"]}'
```

- **`name` (path, string, required)**: Name of the access group.
- **`description` (path, string)**: Optional description of the group.
- **`userUuids` (path, array)**: Optional list of user UUIDs to seed the group with at creation time. You can also add members later with `addUsersToAccessControlGroup`.

### (Optional) Create a weekly schedule

To restrict a grant to specific hours, first create a schedule and reference its UUID in the grant. Weekly schedules use the `WEEKLY_REPEATING_MINUTES` strategy.

```python Python
import requests

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

response = requests.post(
    "https://api2.rhombussystems.com/api/schedule/createWeeklySchedule",
    headers=headers,
    json={
        "schedule": {
            "name": "Business Hours",
            "strategy": "WEEKLY_REPEATING_MINUTES"
        }
    }
)
schedule_uuid = response.json().get("scheduleUuid")
print(schedule_uuid)
```

```javascript JavaScript
const response = await fetch('https://api2.rhombussystems.com/api/schedule/createWeeklySchedule', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-auth-scheme': 'api-token',
    'x-auth-apikey': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    schedule: {
      name: 'Business Hours',
      strategy: 'WEEKLY_REPEATING_MINUTES'
    }
  })
});
const { scheduleUuid } = await response.json();
console.log(scheduleUuid);
```

```bash cURL
curl -X POST https://api2.rhombussystems.com/api/schedule/createWeeklySchedule \
  -H "Content-Type: application/json" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_API_KEY" \
  -d '{"schedule": {"name": "Business Hours", "strategy": "WEEKLY_REPEATING_MINUTES"}}'
```

The response returns a `scheduleUuid`. Use [`/api/schedule/getSchedules`](https://developer.rhombus.com/api-reference/schedule-webservice/get-schedules) and [`/api/schedule/getScheduleDataV2`](https://developer.rhombus.com/api-reference/schedule-webservice/get-schedule-data-v2) to review schedules, and manage the detailed weekly time intervals in the Rhombus Console.

### Create the access grant

Tie the group, doors, and (optionally) a schedule together. Use mode `DEFAULT` for a standard access grant.

```python Python
import requests

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

response = requests.post(
    "https://api2.rhombussystems.com/api/accesscontrol/createAccessGrant",
    headers=headers,
    json={
        "accessGrant": {
            "name": "Warehouse Staff - Business Hours",
            "locationUuid": "YOUR_LOCATION_UUID",
            "mode": "DEFAULT",
            "groupUuids": ["GROUP_UUID"],
            "accessControlledDoorUuids": ["DOOR_UUID_1", "DOOR_UUID_2"],
            "scheduleUuid": "SCHEDULE_UUID"
        }
    }
)

data = response.json()
if data.get("error"):
    print("Error:", data.get("errorMsg"))
else:
    print("Created grant:", data["accessGrant"]["uuid"])
```

```javascript JavaScript
const response = await fetch('https://api2.rhombussystems.com/api/accesscontrol/createAccessGrant', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-auth-scheme': 'api-token',
    'x-auth-apikey': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    accessGrant: {
      name: 'Warehouse Staff - Business Hours',
      locationUuid: 'YOUR_LOCATION_UUID',
      mode: 'DEFAULT',
      groupUuids: ['GROUP_UUID'],
      accessControlledDoorUuids: ['DOOR_UUID_1', 'DOOR_UUID_2'],
      scheduleUuid: 'SCHEDULE_UUID'
    }
  })
});

const data = await response.json();
if (data.error) {
  console.error('Error:', data.errorMsg);
} else {
  console.log('Created grant:', data.accessGrant.uuid);
}
```

```bash cURL
curl -X POST https://api2.rhombussystems.com/api/accesscontrol/createAccessGrant \
  -H "Content-Type: application/json" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_API_KEY" \
  -d '{
    "accessGrant": {
      "name": "Warehouse Staff - Business Hours",
      "locationUuid": "YOUR_LOCATION_UUID",
      "mode": "DEFAULT",
      "groupUuids": ["GROUP_UUID"],
      "accessControlledDoorUuids": ["DOOR_UUID_1", "DOOR_UUID_2"],
      "scheduleUuid": "SCHEDULE_UUID"
    }
  }'
```

- **`accessGrant.name` (path, string)**: Human-readable name for the grant.
- **`accessGrant.locationUuid` (path, string)**: The location the grant applies to.
- **`accessGrant.mode` (path, string)**: Grant mode, one of `DEFAULT` or `GUEST_PASS_INDIVIDUAL`. Use `DEFAULT` for standard employee access.
- **`accessGrant.groupUuids` (path, array)**: Access groups whose members receive access. Combine with `userUuids` to grant individual users directly.
- **`accessGrant.userUuids` (path, array)**: Individual users to grant access to, in addition to any groups.
- **`accessGrant.accessControlledDoorUuids` (path, array)**: The doors this grant opens. You can also target doors by label with `doorLabelIds`.
- **`accessGrant.scheduleUuid` (path, string)**: Optional schedule that constrains when the grant is active. Omit for 24/7 access.
- **`accessGrant` (object)**: The created grant, including its generated `uuid`.
- **`error` (boolean)**: `true` if the grant could not be created. Check `errorMsg` for details and `warningMsg` for non-fatal notes.

## Activate a lockdown plan

Lockdown plans let you instantly change the access state of many doors at a location during an emergency. First list the plans configured for your organization, then activate one or more for a location.

### Find available lockdown plans

```python Python
import requests

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

response = requests.post(
    "https://api2.rhombussystems.com/api/accesscontrol/lockdownPlan/findLockdownPlans",
    headers=headers,
    json={}
)
for plan in response.json().get("lockdownPlans", []):
    print(f"{plan.get('name')}: {plan.get('uuid')}")
```

```javascript JavaScript
const response = await fetch('https://api2.rhombussystems.com/api/accesscontrol/lockdownPlan/findLockdownPlans', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-auth-scheme': 'api-token',
    'x-auth-apikey': 'YOUR_API_KEY'
  },
  body: JSON.stringify({})
});
for (const plan of (await response.json()).lockdownPlans || []) {
  console.log(`${plan.name}: ${plan.uuid}`);
}
```

```bash cURL
curl -X POST https://api2.rhombussystems.com/api/accesscontrol/lockdownPlan/findLockdownPlans \
  -H "Content-Type: application/json" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_API_KEY" \
  -d '{}'
```

### Activate lockdown for a location

```python Python
import requests
import time

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_API_KEY",
    "Content-Type": "application/json"
}

response = requests.post(
    "https://api2.rhombussystems.com/api/accesscontrol/lockdownPlan/activateLockdownForLocation",
    headers=headers,
    json={
        "locationUuid": "YOUR_LOCATION_UUID",
        "lockdownPlanUuids": ["LOCKDOWN_PLAN_UUID"],
        "stateUpdatedAtMillis": int(time.time() * 1000)
    }
)

data = response.json()
print("Result:", data.get("result"))
print("Location state:", data.get("state", {}).get("state"))
```

```javascript JavaScript
const response = await fetch('https://api2.rhombussystems.com/api/accesscontrol/lockdownPlan/activateLockdownForLocation', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-auth-scheme': 'api-token',
    'x-auth-apikey': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    locationUuid: 'YOUR_LOCATION_UUID',
    lockdownPlanUuids: ['LOCKDOWN_PLAN_UUID'],
    stateUpdatedAtMillis: Date.now()
  })
});

const data = await response.json();
console.log('Result:', data.result);
console.log('Location state:', data.state?.state);
```

```bash cURL
curl -X POST https://api2.rhombussystems.com/api/accesscontrol/lockdownPlan/activateLockdownForLocation \
  -H "Content-Type: application/json" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_API_KEY" \
  -d '{
    "locationUuid": "YOUR_LOCATION_UUID",
    "lockdownPlanUuids": ["LOCKDOWN_PLAN_UUID"],
    "stateUpdatedAtMillis": 1712707200000
  }'
```

- **`locationUuid` (path, string, required)**: The location to place into lockdown.
- **`lockdownPlanUuids` (path, array, required)**: The lockdown plans to activate. Use UUIDs from `findLockdownPlans`.
- **`stateUpdatedAtMillis` (path, integer, required)**: The current lockdown state timestamp in epoch milliseconds, used for optimistic concurrency. Pass the current time when initiating a lockdown.
- **`result` (string)**: Outcome of the activation, one of `SUCCESS`, `INVALID_LOCKDOWN_PLANS`, or `OPTIMISTIC_CONCURRENCY`.
- **`state` (object)**: The location's resulting lockdown state, including `state` (`STANDARD_SECURITY` or `LOCKED_DOWN`) and the list of `activeLockdownPlans`.

> **Warning**: Activating a lockdown changes physical access at the location immediately. Test your integration with [`/api/accesscontrol/lockdownPlan/enableLockdownTestModeForLocation`](https://developer.rhombus.com/api-reference/lockdown-plan-webservice/enable-test-mode-of-lockdown-for-the-specified-location) before using it in production, and end a lockdown with [`/api/accesscontrol/lockdownPlan/deactivateLockdownForLocation`](https://developer.rhombus.com/api-reference/lockdown-plan-webservice/deactivate-lockdown-for-the-specified-location).

## Use cases

- **Remote entry for visitors**: Let front-desk software unlock a door on demand when a visitor is verified, with camera footage attached to every unlock.
- **Automated onboarding**: Provision a new hire's badge and group membership from your HR system so their access is ready on day one.
- **Contractor time windows**: Issue credentials with explicit start and end dates, and constrain access to business hours with a schedule.
- **Emergency lockdown**: Wire a panic button or safety system to activate a lockdown plan across a location in a single API call.

## Troubleshooting

**Remote unlock returns ERROR**

Confirm the door has `remoteUnlockEnabled` set to `true` in the door listing response, that the `accessControlledDoorUuid` is correct, and that your API key has access control permissions. Doors that are offline cannot be unlocked remotely.

**Credential is created but access is denied**

Creating and assigning a credential is not enough on its own — the user must also fall under an access grant that covers the target door. Verify a `DEFAULT` grant links the user (directly or via a group) to the door, and that any attached schedule is currently active. Also confirm the credential's `workflowStatus` is `ACTIVE` and the current time falls within its start/end window.

**Credential validity dates behave unexpectedly**

`startDateEpochSecInclusive` and `endDateEpochSecExclusive` use epoch **seconds**, not milliseconds. If a credential expires immediately or never activates, check that you did not pass a millisecond value.

**Lockdown activation returns OPTIMISTIC_CONCURRENCY**

The location's lockdown state changed between your read and your write. Re-fetch the current state (for example, with `getOrCreateLocationLockdownState`), then retry the activation with an updated `stateUpdatedAtMillis`.

**Access grant response has error set to true**

Inspect `errorMsg` in the response. Common causes are referencing a door that has no available access control license (see `unassignedACDLicensesDoorUuids` and `expiredACDLicensesDoorUuids` in the response) or an invalid `locationUuid`.

## Next steps

- **[QR Code Access Control](https://developer.rhombus.com/implementations/qr-code-access-control)**: Add touchless, camera-authenticated QR code entry for visitors and events (beta).
- **[Webhook notifications](https://developer.rhombus.com/webhooks)**: Receive real-time access events so your application can react the moment a door is used.
- **[API reference](https://developer.rhombus.com/api-reference/component-webservice/find-access-controlled-doors-within-the-org)**: Explore complete request and response schemas for every access control endpoint.
