Access Control
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.
On this page
- Overview
- Prerequisites
- List access-controlled doors
- Request parameters
- Response
- Remotely unlock a door
- Issue and assign a credential
- Create a Wiegand credential
- Assign an existing credential to a user
- Grant access with groups and schedules
- Create an access group and add users
- (Optional) Create a weekly schedule
- Create the access grant
- Activate a lockdown plan
- Find available lockdown plans
- Activate lockdown for a location
- Use cases
- Troubleshooting
- Next steps
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
Looking for touchless visitor entry? The 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
Before you begin, make sure you have:
- A Rhombus API key with access control permissions (generated in the Rhombus Console 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:
x-auth-scheme: api-token
x-auth-apikey: YOUR_API_KEY
Content-Type: application/jsonList 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.
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")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;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
Maximum number of doors to return in a single page.
Pagination cursor returned by a previous call. Omit it on the first request; supply it to fetch the next page.
Response
The list of access-controlled doors. Key fields per door:
Pagination cursor. When present, pass it back in the next request to retrieve additional doors.
If you only need lightweight door status rather than full configuration, use /api/component/findMinimalStateAccessControlledDoors, 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.
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 ERRORconst 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 ERRORcurl -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"}'The UUID of the door to unlock, from the door listing endpoint.
Outcome of the request, either SUCCESS or ERROR.
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
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')}")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}`);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
}'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.
Facility (site) code encoded on the card. Used by formats such as H10301.
Card number encoded on the card.
Site code, used by formats that encode one separately from the facility code.
Company ID, used by HID Corporate 1000 formats.
Raw credential value. Used by the WIEGAND_64BIT_RAW and CUSTOM formats.
The user the credential belongs to. When set, the credential is created already assigned to that user.
Start of the credential's validity window, in epoch seconds (inclusive).
End of the credential's validity window, in epoch seconds (exclusive).
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.
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())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());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"
}'The hex value of the credential to assign.
The user to assign the credential to.
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.
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
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"]
}
)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']
})
});# 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 of the access group.
Optional description of the group.
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.
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)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);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 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.
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"])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);
}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"
}
}'Human-readable name for the grant.
The location the grant applies to.
Grant mode, one of DEFAULT or GUEST_PASS_INDIVIDUAL. Use DEFAULT for standard employee access.
Access groups whose members receive access. Combine with userUuids to grant individual users directly.
Individual users to grant access to, in addition to any groups.
The doors this grant opens. You can also target doors by label with doorLabelIds.
Optional schedule that constrains when the grant is active. Omit for 24/7 access.
The created grant, including its generated uuid.
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
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')}")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}`);
}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
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"))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);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
}'The location to place into lockdown.
The lockdown plans to activate. Use UUIDs from findLockdownPlans.
The current lockdown state timestamp in epoch milliseconds, used for optimistic concurrency. Pass the current time when initiating a lockdown.
Outcome of the activation, one of SUCCESS, INVALID_LOCKDOWN_PLANS, or OPTIMISTIC_CONCURRENCY.
The location's resulting lockdown state, including state (STANDARD_SECURITY or LOCKED_DOWN) and the list of activeLockdownPlans.
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.
Use cases
Let front-desk software unlock a door on demand when a visitor is verified, with camera footage attached to every unlock.
Provision a new hire's badge and group membership from your HR system so their access is ready on day one.
Issue credentials with explicit start and end dates, and constrain access to business hours with a schedule.
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
Add touchless, camera-authenticated QR code entry for visitors and events (beta).
Receive real-time access events so your application can react the moment a door is used.
Explore complete request and response schemas for every access control endpoint.