> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.rhombus.community/llms.txt
> Use this file 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](/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.
</Note>

## Prerequisites

<Note>
  Before you begin, make sure you have:

  * A **Rhombus API key** with access control permissions (generated in the Rhombus Console under Settings > API)
  * 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)
</Note>

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

```bash theme={null}
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.

<CodeGroup>
  ```python Python theme={null}
  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 theme={null}
  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 theme={null}
  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}'
  ```
</CodeGroup>

### Request parameters

<ParamField path="maxPageSize" type="integer">
  Maximum number of doors to return in a single page.
</ParamField>

<ParamField path="lastEvaluatedKey" type="string">
  Pagination cursor returned by a previous call. Omit it on the first request; supply it to fetch the next page.
</ParamField>

### Response

<ResponseField name="accessControlledDoors" type="array">
  The list of access-controlled doors. Key fields per door:

  <Expandable title="door fields">
    <ResponseField name="uuid" type="string">
      Unique identifier for the door. Use this value wherever an `accessControlledDoorUuid` is required.
    </ResponseField>

    <ResponseField name="name" type="string">
      Display name of the door (for example, "Main Entrance").
    </ResponseField>

    <ResponseField name="locationUuid" type="string">
      The location the door belongs to.
    </ResponseField>

    <ResponseField name="defaultState" type="string">
      Baseline access mode, one of `ACCESS_CONTROLLED` or `UNLOCKED`.
    </ResponseField>

    <ResponseField name="remoteUnlockEnabled" type="boolean">
      Whether the door accepts remote unlock requests through the API.
    </ResponseField>

    <ResponseField name="unlockTimeSec" type="integer">
      How long the door stays unlocked after a standard unlock, in seconds.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="lastEvaluatedKey" type="string">
  Pagination cursor. When present, pass it back in the next request to retrieve additional doors.
</ResponseField>

<Tip>
  If you only need lightweight door status rather than full configuration, use `/api/component/findMinimalStateAccessControlledDoors`, which returns each door plus a compact state shadow.
</Tip>

## 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.

<CodeGroup>
  ```python Python theme={null}
  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 theme={null}
  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 theme={null}
  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"}'
  ```
</CodeGroup>

<ParamField path="accessControlledDoorUuid" type="string" required>
  The UUID of the door to unlock, from the door listing endpoint.
</ParamField>

<ResponseField name="type" type="string">
  Outcome of the request, either `SUCCESS` or `ERROR`.
</ResponseField>

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

## 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

<CodeGroup>
  ```python Python theme={null}
  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 theme={null}
  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 theme={null}
  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
    }'
  ```
</CodeGroup>

<ParamField path="wiegandFormat" type="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`.
</ParamField>

<ParamField path="facilityCode" type="integer">
  Facility (site) code encoded on the card. Used by formats such as `H10301`.
</ParamField>

<ParamField path="cardNumber" type="integer">
  Card number encoded on the card.
</ParamField>

<ParamField path="siteCode" type="integer">
  Site code, used by formats that encode one separately from the facility code.
</ParamField>

<ParamField path="companyId" type="integer">
  Company ID, used by HID Corporate 1000 formats.
</ParamField>

<ParamField path="value" type="string">
  Raw credential value. Used by the `WIEGAND_64BIT_RAW` and `CUSTOM` formats.
</ParamField>

<ParamField path="userUuid" type="string">
  The user the credential belongs to. When set, the credential is created already assigned to that user.
</ParamField>

<ParamField path="startDateEpochSecInclusive" type="integer">
  Start of the credential's validity window, in epoch **seconds** (inclusive).
</ParamField>

<ParamField path="endDateEpochSecExclusive" type="integer">
  End of the credential's validity window, in epoch **seconds** (exclusive).
</ParamField>

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

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.

<CodeGroup>
  ```python Python theme={null}
  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 theme={null}
  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 theme={null}
  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"
    }'
  ```
</CodeGroup>

<ParamField path="credentialHexValue" type="string" required>
  The hex value of the credential to assign.
</ParamField>

<ParamField path="userUuid" type="string" required>
  The user to assign the credential to.
</ParamField>

<Tip>
  Manage a credential's lifecycle with `/api/accesscontrol/suspendAccessControlCredential`, `/api/accesscontrol/unsuspendAccessControlCredential`, and `/api/accesscontrol/revokeAccessControlCredential`. To review a user's credentials, call `/api/accesscontrol/findAccessControlCredentialByUser` with their `userUuid`.
</Tip>

## 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

<CodeGroup>
  ```python Python theme={null}
  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 theme={null}
  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 theme={null}
  # 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"]}'
  ```
</CodeGroup>

<ParamField path="name" type="string" required>
  Name of the access group.
</ParamField>

<ParamField path="description" type="string">
  Optional description of the group.
</ParamField>

<ParamField path="userUuids" type="array">
  Optional list of user UUIDs to seed the group with at creation time. You can also add members later with `addUsersToAccessControlGroup`.
</ParamField>

### (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.

<CodeGroup>
  ```python Python theme={null}
  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 theme={null}
  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 theme={null}
  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"}}'
  ```
</CodeGroup>

The response returns a `scheduleUuid`. Use `/api/schedule/getSchedules` and `/api/schedule/getScheduleDataV2` 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.

<CodeGroup>
  ```python Python theme={null}
  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 theme={null}
  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 theme={null}
  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"
      }
    }'
  ```
</CodeGroup>

<ParamField path="accessGrant.name" type="string">
  Human-readable name for the grant.
</ParamField>

<ParamField path="accessGrant.locationUuid" type="string">
  The location the grant applies to.
</ParamField>

<ParamField path="accessGrant.mode" type="string">
  Grant mode, one of `DEFAULT` or `GUEST_PASS_INDIVIDUAL`. Use `DEFAULT` for standard employee access.
</ParamField>

<ParamField path="accessGrant.groupUuids" type="array">
  Access groups whose members receive access. Combine with `userUuids` to grant individual users directly.
</ParamField>

<ParamField path="accessGrant.userUuids" type="array">
  Individual users to grant access to, in addition to any groups.
</ParamField>

<ParamField path="accessGrant.accessControlledDoorUuids" type="array">
  The doors this grant opens. You can also target doors by label with `doorLabelIds`.
</ParamField>

<ParamField path="accessGrant.scheduleUuid" type="string">
  Optional schedule that constrains when the grant is active. Omit for 24/7 access.
</ParamField>

<ResponseField name="accessGrant" type="object">
  The created grant, including its generated `uuid`.
</ResponseField>

<ResponseField name="error" type="boolean">
  `true` if the grant could not be created. Check `errorMsg` for details and `warningMsg` for non-fatal notes.
</ResponseField>

## 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

<CodeGroup>
  ```python Python theme={null}
  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 theme={null}
  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 theme={null}
  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 '{}'
  ```
</CodeGroup>

### Activate lockdown for a location

<CodeGroup>
  ```python Python theme={null}
  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 theme={null}
  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 theme={null}
  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
    }'
  ```
</CodeGroup>

<ParamField path="locationUuid" type="string" required>
  The location to place into lockdown.
</ParamField>

<ParamField path="lockdownPlanUuids" type="array" required>
  The lockdown plans to activate. Use UUIDs from `findLockdownPlans`.
</ParamField>

<ParamField path="stateUpdatedAtMillis" type="integer" required>
  The current lockdown state timestamp in epoch milliseconds, used for optimistic concurrency. Pass the current time when initiating a lockdown.
</ParamField>

<ResponseField name="result" type="string">
  Outcome of the activation, one of `SUCCESS`, `INVALID_LOCKDOWN_PLANS`, or `OPTIMISTIC_CONCURRENCY`.
</ResponseField>

<ResponseField name="state" type="object">
  The location's resulting lockdown state, including `state` (`STANDARD_SECURITY` or `LOCKED_DOWN`) and the list of `activeLockdownPlans`.
</ResponseField>

<Warning>
  Activating a lockdown changes physical access at the location immediately. Test your integration with `/api/accesscontrol/lockdownPlan/enableLockdownTestModeForLocation` before using it in production, and end a lockdown with `/api/accesscontrol/lockdownPlan/deactivateLockdownForLocation`.
</Warning>

## Use cases

<CardGroup cols={2}>
  <Card title="Remote entry for visitors" icon="bell-concierge">
    Let front-desk software unlock a door on demand when a visitor is verified, with camera footage attached to every unlock.
  </Card>

  <Card title="Automated onboarding" icon="user-plus">
    Provision a new hire's badge and group membership from your HR system so their access is ready on day one.
  </Card>

  <Card title="Contractor time windows" icon="user-clock">
    Issue credentials with explicit start and end dates, and constrain access to business hours with a schedule.
  </Card>

  <Card title="Emergency lockdown" icon="shield-halved">
    Wire a panic button or safety system to activate a lockdown plan across a location in a single API call.
  </Card>
</CardGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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`.
  </Accordion>

  <Accordion title="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`.
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="QR Code Access Control" icon="qrcode" href="/implementations/qr-code-access-control">
    Add touchless, camera-authenticated QR code entry for visitors and events (beta).
  </Card>

  <Card title="Webhook notifications" icon="webhook" href="/webhooks">
    Receive real-time access events so your application can react the moment a door is used.
  </Card>

  <Card title="API reference" icon="code" href="/api-reference/overview">
    Explore complete request and response schemas for every access control endpoint.
  </Card>
</CardGroup>
