Holders
Introduction
Holders (i.e. credential holders) represent end users of the access control system. In pdk.io, holders are referred to as people.
The holder object
{
"id": "8b37106e-fb08-4700-b14d-70a3967b5086",
"firstName": "John",
"lastName": "Wiegand",
"email": "john@example.com",
"photoUrl": "http://systems.pdk.io/images/b7c96600-6310-11ee-90fc-598e4a89e620",
"partition": "619cceb0-ac58-4b15-a8ec-32efcb0476ba",
"enabled": true,
"activeDate": "2023-10-04T00:00:00",
"expireDate": "2025-10-04T00:00:00",
"pin": "1234",
"duressPin": "91234",
"customFields": {
"test_custom_field": "1234567"
},
"groups": [
{
"id": "65ebe88c-865b-40c9-9d79-0c8c0d206bba",
"name": "Test Group",
"partition": "619cceb0-ac58-4b15-a8ec-32efcb0476ba"
}
],
"credentials": [
{
"id": "7500d9fb-9fe6-4a28-9cef-80850e857b83",
"holderId": "8b37106e-fb08-4700-b14d-70a3967b5086",
"credentialNumber": 1234567,
"facilityCode": null,
"description": null,
"types": ["card"]
},
{
"id": "1a936e12-f609-4dc4-8b91-d7690e5c690c",
"holderId": "8b37106e-fb08-4700-b14d-70a3967b5086",
"credentialNumber": null,
"facilityCode": null,
"description": null,
"types": ["touch", "token"]
}
]
}
Property | Type | Description |
---|---|---|
id | String | The holder ID. |
firstName | String | The holder's first name. |
lastName | String | The holder's last name. |
email | String | The holder's email address. |
photoUrl | String | The URL of the holder's photo. |
partition | String | The ID of the partition that this holder is associated with. |
enabled | Boolean | Whether rules will be processed for this holder. |
activeDate | String | The date rules will start processing for this holder. This is formatted as YYYY-MM-DDTHH:mm:ss . |
expireDate | String | The date rules will stop processing for this holder. This is formatted as YYYY-MM-DDTHH:mm:ss . |
pin | String | The holder's PIN code. |
duressPin | String | The holder's duress PIN code. |
customFields | Object | An object containing custom field values for this holder. |
groups | Object[] | An array of group objects representing the groups this holder is assigned to. |
credentials | Object[] | An array of credential objects representing the credentials issued to this holder. |
Basic Endpoints
Create a holder
Request
POST https://systems.pdk.io/{{system_id}}/holders HTTP/1.1
Authorization: Bearer {{system_token}}
Content-Type: application/json
{
"firstName": "John",
"lastName": "Wiegand"
}
Parameter | Location | Type | Required | Description |
---|---|---|---|---|
system_id | Path | String | Yes | The system ID. |
system_token | Header | String | Yes | A valid system token. |
firstName | Body | String | Yes | The holder's first name. The maximum length is 35 characters. |
lastName | Body | String | Yes | The holder's last name. The maximum length is 35 characters. |
email | Body | String | No | The holder's email address. |
partition | Body | String | No | The ID of the partition that this holder should be associated with. |
enabled | Body | Boolean | No | Whether rules should be processed for this holder. The default value is true . |
activeDate | Body | String | No | The date to start processing rules for this holder. This is formatted as YYYY-MM-DDTHH:mm:ss . |
expireDate | Body | String | No | The date to stop processing rules for this holder. This is formatted as YYYY-MM-DDTHH:mm:ss . |
pin | Body | String | No | The holder's PIN code. Possible values include a string of digits or null . |
duressPin | Body | String | No | The holder's duress PIN code. Possible values include a string of digits or null . |
customFields | Body | Object | No | An object containing custom field values for this holder. |
Response
The response contains the ID of the newly created holder object.
HTTP/1.1 201 OK
Content-Type: application/json
{
"id": "8b37106e-fb08-4700-b14d-70a3967b5086"
}
Retrieve a holder
Request
GET https://systems.pdk.io/{{system_id}}/holders/{{holder_id}} HTTP/1.1
Authorization: Bearer {{system_token}}
Parameter | Location | Type | Required | Description |
---|---|---|---|---|
system_id | Path | String | Yes | The system ID. |
holder_id | Path | String | Yes | The holder ID. |
system_token | Header | String | Yes | A valid system token. |
If you need to retrieve a holder by a field other than the holder ID (e.g. email address), you can preview a holder report using the desired field as a filter.
Response
The response contains a holder object.
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "8b37106e-fb08-4700-b14d-70a3967b5086",
"firstName": "John",
"lastName": "Wiegand",
"email": "john@example.com",
"photoUrl": "http://systems.pdk.io/images/b7c96600-6310-11ee-90fc-598e4a89e620",
"partition": "619cceb0-ac58-4b15-a8ec-32efcb0476ba",
"enabled": true,
"activeDate": "2023-10-04T00:00:00",
"expireDate": "2025-10-04T00:00:00",
"pin": "1234",
"duressPin": "91234",
"customFields": {
"test_custom_field": "1234567"
},
"groups": [
{
"id": "65ebe88c-865b-40c9-9d79-0c8c0d206bba",
"name": "Test Group",
"partition": "619cceb0-ac58-4b15-a8ec-32efcb0476ba"
}
],
"credentials": [
{
"id": "7500d9fb-9fe6-4a28-9cef-80850e857b83",
"holderId": "8b37106e-fb08-4700-b14d-70a3967b5086",
"credentialNumber": 1234567,
"facilityCode": null,
"description": null,
"types": ["card"]
},
{
"id": "1a936e12-f609-4dc4-8b91-d7690e5c690c",
"holderId": "8b37106e-fb08-4700-b14d-70a3967b5086",
"credentialNumber": null,
"facilityCode": null,
"description": null,
"types": ["touch", "token"]
}
]
}
Update a holder
Request
PUT https://systems.pdk.io/{{system_id}}/holders/{{holder_id}} HTTP/1.1
Authorization: Bearer {{system_token}}
Content-Type: application/json
{
"firstName": "John",
"lastName": "Wiegand",
"partition": "619cceb0-ac58-4b15-a8ec-32efcb0476ba",
"enabled": true,
"activeDate": null,
"expireDate": null,
"pin": null,
"duressPin": null
}
Parameter | Location | Type | Required | Description |
---|---|---|---|---|
system_id | Path | String | Yes | The system ID. |
holder_id | Path | String | Yes | The holder ID. |
system_token | Header | String | Yes | A valid system token. |
firstName | Body | String | Yes | The holder's first name. The maximum length is 35 characters. |
lastName | Body | String | Yes | The holder's last name. The maximum length is 35 characters. |
email | Body | String | No | The holder's email address. |
partition | Body | String | Yes | The ID of the partition that this holder should be associated with. |
enabled | Body | Boolean | Yes | Whether rules should be processed for this holder. The default value is true . |
activeDate | Body | String | Yes | The date to start processing rules for this holder. This is formatted as YYYY-MM-DDTHH:mm:ss . |
expireDate | Body | String | Yes | The date to stop processing rules for this holder. This is formatted as YYYY-MM-DDTHH:mm:ss . |
pin | Body | String | Yes | The holder's PIN code. Possible values include a string of digits or null . |
duressPin | Body | String | Yes | The holder's duress PIN code. Possible values include a string of digits or null . |
customFields | Body | Object | No | An object containing custom field values for this holder. |
Response
HTTP/1.1 204 No Content
Delete a holder
Request
DELETE https://systems.pdk.io/{{system_id}}/holders/{{holder_id}} HTTP/1.1
Authorization: Bearer {{system_token}}
Parameter | Location | Type | Required | Description |
---|---|---|---|---|
system_id | Path | String | Yes | The system ID. |
holder_id | Path | String | Yes | The holder ID. |
system_token | Header | String | Yes | A valid system token. |
Response
HTTP/1.1 204 No Content
List all holders
Request
GET https://systems.pdk.io/{{system_id}}/holders HTTP/1.1
Authorization: Bearer {{system_token}}
Parameter | Location | Type | Required | Description |
---|---|---|---|---|
system_id | Path | String | Yes | The system ID. |
include | Query | String | No | A comma-delimited list of additional properties to include in the response. Available properties include credentials , groups , partition , and rules . |
page | Query | Integer | No | The zero-based page number used for pagination. The default value is 0. |
per_page | Query | Integer | No | The number of items per page used for pagination. The default value is 10 and the maximum value is 100. |
system_token | Header | String | Yes | A valid system token. |
Response
The response contains an array of holder objects.
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"id": "8b37106e-fb08-4700-b14d-70a3967b5086",
"firstName": "John",
"lastName": "Wiegand",
"email": "john@example.com",
"photoUrl": "http://systems.pdk.io/images/b7c96600-6310-11ee-90fc-598e4a89e620",
"partition": "619cceb0-ac58-4b15-a8ec-32efcb0476ba",
"enabled": true,
"activeDate": "2023-10-04T00:00:00",
"expireDate": "2025-10-04T00:00:00",
"pin": "1234",
"duressPin": "91234",
"customFields": {
"test_custom_field": "1234567"
},
"groups": [
{
"id": "65ebe88c-865b-40c9-9d79-0c8c0d206bba",
"name": "Test Group",
"partition": "619cceb0-ac58-4b15-a8ec-32efcb0476ba"
}
],
"credentials": [
{
"id": "7500d9fb-9fe6-4a28-9cef-80850e857b83",
"holderId": "8b37106e-fb08-4700-b14d-70a3967b5086",
"credentialNumber": 1234567,
"facilityCode": null,
"description": null,
"types": ["card"]
},
{
"id": "1a936e12-f609-4dc4-8b91-d7690e5c690c",
"holderId": "8b37106e-fb08-4700-b14d-70a3967b5086",
"credentialNumber": null,
"facilityCode": null,
"description": null,
"types": ["touch", "token"]
}
]
}
]
List all holders in a group
Request
GET https://systems.pdk.io/{{system_id}}/groups/{{group_id}}/holders HTTP/1.1
Authorization: Bearer {{system_token}}
Parameter | Location | Type | Required | Description |
---|---|---|---|---|
system_id | Path | String | Yes | The system ID. |
group_id | Path | String | Yes | The group ID. |
page | Query | String | No | The zero-based page number used for pagination. The default value is 0. |
per_page | Query | Integer | No | The number of items per page used for pagination. The default value is 10 and the maximum value is 100. |
system_token | Header | String | Yes | A valid system token. |
Response
The response contains an array of holder objects.
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"id": "8b37106e-fb08-4700-b14d-70a3967b5086",
"firstName": "John",
"lastName": "Wiegand",
"email": "john@example.com",
"photoUrl": "http://systems.pdk.io/images/b7c96600-6310-11ee-90fc-598e4a89e620",
"partition": "619cceb0-ac58-4b15-a8ec-32efcb0476ba",
"enabled": true,
"activeDate": "2023-10-04T00:00:00",
"expireDate": "2025-10-04T00:00:00",
"pin": "1234",
"duressPin": "91234",
"customFields": {
"test_custom_field": "1234567"
},
"groups": [
{
"id": "65ebe88c-865b-40c9-9d79-0c8c0d206bba",
"name": "Test Group",
"partition": "619cceb0-ac58-4b15-a8ec-32efcb0476ba"
}
],
"credentials": [
{
"id": "7500d9fb-9fe6-4a28-9cef-80850e857b83",
"holderId": "8b37106e-fb08-4700-b14d-70a3967b5086",
"credentialNumber": 1234567,
"facilityCode": null,
"description": null,
"types": ["card"]
},
{
"id": "1a936e12-f609-4dc4-8b91-d7690e5c690c",
"holderId": "8b37106e-fb08-4700-b14d-70a3967b5086",
"credentialNumber": null,
"facilityCode": null,
"description": null,
"types": ["touch", "token"]
}
]
}
]
Update a holder's photo
Request
PUT https://systems.pdk.io/{{system_id}}/holders/{{holder_id}}/photo HTTP/1.1
Authorization: Bearer {{system_token}}
Content-Type: application/json
{
"base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAB4CAAAAAAcD2kOAAABZklEQVR4Ae3XAYnDMBTG8RqogBqIgRqogBiYgRiogBqYgRiIgBh4Bj5Rd13yIAs5uHHrGwffH2DNI+MH3cLWCR+KMGHChAkTJkz4tQgTJkyYMGHChAkTJkyYcIqDZDAXlOQevqtLiYPSr+B1GhQH84iztOnaHQDiNGi9AA7txCUrWF1tsYJ7JvwFvq2PlvqeUlJ4qYMyq5/vFoI7X2dBWktTu/v2wnHSm9jfiYAmKXvu53X29aI0dbvfC8enG5kTbGEHzRiednNY9BQd+XJ4DaUDZ27S3C5Xwv3RvLcjL3YwfDubkx2M0MtWMHJYmul1sB/8xKbgVM4mx6m1Kx2tYcjyIRjeFJZtU8qZwar5fF4d5TzhGrj/I7DXQxT0a+0vg9tinrvJnG1g6UcHbGBgn5v1fMAMhuxOlz7jLXCOj6D9+AiTyxMMnitbMp8WCRMmTJgwYcKECRMmTJgwYcKECRMmTPhfwV9kH2srWmFAYQAAAABJRU5ErkJggg=="
}
Parameter | Location | Type | Required | Description |
---|---|---|---|---|
system_id | Path | String | Yes | The system ID. |
holder_id | Path | String | Yes | The holder ID. |
system_token | Header | String | Yes | A valid system token. |
base64 | Body | String | Yes | The photo encoded as a data URL. |
Response
HTTP/1.1 204 No Content
Preview a holder file import
Request
POST https://systems.pdk.io/{{system_id}}/holders/import/preview HTTP/1.1
Authorization: Bearer {{system_token}}
Content-Type: application/json
Want-Digest: sha-265
{
"csv": "First Name,Last Name\nJohn, Wiegand\nJames, Maxwell\nMichael, Faraday"
}
Parameter | Location | Type | Required | Description |
---|---|---|---|---|
system_id | Path | String | Yes | The system ID. |
system_token | Header | String | Yes | A valid system token. |
csv | Body | String | Yes | A CSV string containing a list of holders to be imported. A CSV template can be downloaded here. |
partition | Body | String | No | The partition ID. |
upsert | Body | Boolean | No | Whether the import should update or delete existing records. |
Including the Want-Digest
header in the request will produce a Digest
header in the response. The value provided in the Digest
header will be required if conflicts need to be resolved when importing holders from a file.
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"toBeCreated": 3,
"toBeUpdated": 0,
"toBeDeleted": 0,
"conflicts": [
{
"line": 2,
"firstName": "John",
"lastName": "Wiegand",
"matches": [
{
"id": "8b37106e-fb08-4700-b14d-70a3967b5086",
"firstName": "John",
"lastName": "Wiegand"
}
]
}
]
}
Property | Type | Description |
---|---|---|
toBeCreated | Integer | The number of holders that would be created by this import. |
toBeUpdated | Integer | The number of holders that would be updated by this import. |
toBeDeleted | Integer | The number of holders that would be deleted by this import. |
conflicts | Object[] | A list of conflicts that will need to be resolved when executing this import. |
conflicts.line | Integer | The line number of the conflict. |
conflicts.id | String | The ID of the holder associated with the conflict. |
conflicts.firstName | String | The first name of the holder associated with the conflict. |
conflicts.lastName | String | The last name of the holder associated with the conflict. |
conflicts.matches | Object[] | An array of conflicting holder objects. Note that only the id , firstName , and lastName properties are included. |
Import holders from a file
This endpoint is intended for one-time import operations (e.g. importing records from an old access control system). Ongoing data synchronization should be implemented using individual requests, which are more efficient and allow for more granular error handling.
Request
POST https://systems.pdk.io/{{system_id}}/holders/import HTTP/1.1
Authorization: Bearer {{system_token}}
Digest: {{digest}}
Content-Type: application/json
{
"csv": "First Name,Last Name\nJohn, Wiegand\nJames, Maxwell\nMichael, Faraday",
"resolutions": [
{
"line": 2,
"decision": "skip"
}
]
}
Parameter | Location | Type | Required | Description |
---|---|---|---|---|
system_id | Path | String | Yes | The system ID. |
system_token | Header | String | Yes | A valid system token. |
digest | Header | String | Sometimes | The digest value obtained from the Digest header in the response of the preview a holder file import endpoint. This is required if the import has conflicts that need to be resolved. |
csv | Body | String | Yes | A CSV string containing a list of holders to be imported. A CSV template can be downloaded here. |
resolutions | Body | Object[] | Sometimes | An array of objects describing how individual conflicts should be handled. This is required if the import has conflicts that need to be resolved. |
resolutions.line | Body | Integer | Yes | The line number of the conflict. |
resolutions.decision | Body | String | Yes | How the conflict should be handled. Possible values include create , update , delete , and skip . |
partition | Body | String | No | The partition ID. |
upsert | Body | Boolean | No | Whether the import should update or delete existing records. |
Response
The response contains an array of holder objects representing the holders that were created or updated.
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"id": "8b37106e-fb08-4700-b14d-70a3967b5086",
"email": null,
"firstName": "John",
"lastName": "Wiegand",
"groups": [],
"credentials": [],
"enabled": true,
"partition": "619cceb0-ac58-4b15-a8ec-32efcb0476ba",
"cards": []
},
{
"id": "069f32ab-13f3-41e5-9a3f-7ab728d8184f",
"email": null,
"firstName": "James",
"lastName": "Maxwell",
"groups": [],
"credentials": [],
"enabled": true,
"partition": "619cceb0-ac58-4b15-a8ec-32efcb0476ba",
"cards": []
},
{
"id": "8cd9992c-cb9c-4d07-ac3a-5c5e8165266a",
"email": null,
"firstName": "Michael",
"lastName": "Faraday",
"groups": [],
"credentials": [],
"enabled": true,
"partition": "619cceb0-ac58-4b15-a8ec-32efcb0476ba",
"cards": []
}
]
Delete many holders
Request
POST https://systems.pdk.io/{{system_id}}/holders/bulk-delete HTTP/1.1
Authorization: Bearer {{system_token}}
Content-Type: application/json
{
"holders": [
"8b37106e-fb08-4700-b14d-70a3967b5086",
"069f32ab-13f3-41e5-9a3f-7ab728d8184f",
"8cd9992c-cb9c-4d07-ac3a-5c5e8165266a"
]
}
Parameter | Location | Type | Required | Description |
---|---|---|---|---|
system_id | Path | String | Yes | The system ID. |
system_token | Header | String | Yes | A valid system token. |
holders | Body | String[] | Yes | A list of holder IDs representing holders who should be deleted. |
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"deleted": [
"8b37106e-fb08-4700-b14d-70a3967b5086",
"069f32ab-13f3-41e5-9a3f-7ab728d8184f",
"8cd9992c-cb9c-4d07-ac3a-5c5e8165266a"
]
}
Property | Type | Description |
---|---|---|
deleted | String[] | A list of holder IDs representing holders who were deleted. |