Employees
Manage the employee records for your tenant. An employee is assigned to locations and uses a 6-digit access code to attest a manual verification. An employee is also the Verifier you name in verifiedBy on every verification.
Employee Enrollment
A POS pushes its staff without a kennitala: create the employee with your own externalId and a phoneNumber, and no ssn. The employee then enrolls once, from the terminal: POST /api/v1/employees/{id}/enrollment sends an eID request to their phone, and you poll GET /api/v1/employees/{id}/enrollment every 2 to 3 seconds until it is enrolled, rejected or timeout (after 5 minutes). Enrollment stays with the employee when you change their phone number; a manager who enrolled the wrong person resets it with DELETE /api/v1/employees/{id}/enrollment.
One person is at most one employee of your tenant: an eID that belongs to someone who is already another employee (enrolled, or entered with that kennitala) is rejected with reason: "identity_in_use", and one that does not match the kennitala the employee was entered with is rejected with reason: "identity_mismatch". Deleting an employee frees the person. Enrollment stores the kennitala only as a salted hash, never in plain text: matching a person needs only the hash, and a stored kennitala would be PII with no use to us.
Only enrolled employees may verify. Once this is enforced, verifiedBy is required on POST /api/v1/verifications and an unenrolled Verifier gets 403 with type https://api.aldursvottun.is/errors/verifier-not-enrolled.
Note: The SSN (kennitala) is hashed server-side and never stored or returned in plain text. The accessCode is returned once, in the POST response, and can't be read back through the API: whoever holds it can attest verifications as that employee.
The employee object
id,createdAt(ISO 8601),updatedAt(epoch ms)name,phoneNumberexternalId: your own identifier, unique among your tenant's live employees (deleting an employee frees it)origin:"api"for an employee a service client created; left out otherwiseenrollmentStatus:not_enrolled,pending,enrolled,rejectedortimeouteidName: the name the eID reported, once enrolledlocationIds: the locations the employee is assigned to. List responses also includelocations, the full location objects
Fields that aren't set are left out. locationIds and locations list only locations that haven't been deleted. Pagination, sorting and field formats follow the shared conventions.
/api/v1/employeesList the employees in your tenant. Callers: service client (Bearer) and device (DPoP). Sorted by createdAt descending unless you pass sortBy. Without limit, every employee is returned in one response; with limit, the response is a page with nextCursor and hasMore (nextCursor is null on the last page).
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Required | Bearer <access_token> (service client) or DPoP <access_token> (device). Requires employees:read. |
| DPoP | string | Optional | Device callers only: the DPoP proof for this request, including ath. |
AuthorizationstringRequiredBearer <access_token> (service client) or DPoP <access_token> (device). Requires employees:read.
DPoPstringOptionalDevice callers only: the DPoP proof for this request, including ath.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| locationId | string | Optional | Only employees assigned to this location. A malformed ID returns 400; an ID that matches nothing, or a deleted location, returns an empty list |
| name | string | Optional | Case-insensitive substring match on the name |
| externalId | string | Optional | Exact match on externalId |
| sortBy | string | Optional | "name" | "createdAt" | "updatedAt". Default "createdAt" |
| sortOrder | string | Optional | "asc" | "desc". Default "desc" |
| limit | integer | Optional | Page size, a positive integer |
| cursor | string | Optional | nextCursor from the previous page |
locationIdstringOptionalOnly employees assigned to this location. A malformed ID returns 400; an ID that matches nothing, or a deleted location, returns an empty list
namestringOptionalCase-insensitive substring match on the name
externalIdstringOptionalExact match on externalId
sortBystringOptional"name" | "createdAt" | "updatedAt". Default "createdAt"
sortOrderstringOptional"asc" | "desc". Default "desc"
limitintegerOptionalPage size, a positive integer
cursorstringOptionalnextCursor from the previous page
Examples
cURL
curl "https://abyrgverslun.is/api/v1/employees?locationId=jh72m4q9x1c8n3v5b6z0k2d7f4g9t1ra&sortBy=name&sortOrder=asc" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Response
{
"data": [
{
"id": "m17d4f6g8h2j3k5l7z9x1c3v5b7n9q2w",
"createdAt": "2026-04-11T13:02:45.906Z",
"name": "Guðrún Jónsdóttir",
"phoneNumber": "6912345",
"externalId": "HR-0042",
"locationIds": ["jh72m4q9x1c8n3v5b6z0k2d7f4g9t1ra"],
"updatedAt": 1778063472044,
"locations": [
{
"id": "jh72m4q9x1c8n3v5b6z0k2d7f4g9t1ra",
"createdAt": "2026-03-02T09:14:27.512Z",
"name": "Laugavegur",
"address": "Laugavegur 26",
"city": "Reykjavík",
"postcode": "101",
"updatedAt": 1772442867512
}
]
}
]
}Errors
400locationId is not a valid location ID.401Missing, invalid or expired token, or a device token sent as Bearer.403The token lacks employees:read.422A query parameter failed validation (limit, sortBy or sortOrder).
Response format: Errors.
/api/v1/employeesCreate an employee. Callers: service client (Bearer) only; a device (DPoP) call gets 403. externalId is required. Without ssn, the employee is created pending Employee Enrollment. Returns 201 with the new employee's ID and access code, not the full record. Store the access code now: it is not returned again.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Required | Bearer <access_token> (service client). Requires employees:write. |
| Content-Type | string | Required | application/json |
AuthorizationstringRequiredBearer <access_token> (service client). Requires employees:write.
Content-TypestringRequiredapplication/json
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | Required | Full name, 1-100 characters |
| externalId | string | Required | Your own identifier for the employee, 1-100 characters. Must be unique among your tenant's live employees (a duplicate returns 409); deleting an employee frees it |
| ssn | string | Optional | Kennitala, exactly 10 characters. Leave it out to have the employee enroll with eID instead. Hashed before it is stored. Must be unique among your tenant's active employees (a duplicate returns 409). If it belongs to a deleted employee, that employee is restored with the new details and keeps its ID |
| phoneNumber | string | Required | An Icelandic phone number: 7 digits, optionally after 354, 00354 or +354, in ASCII digits with optional spaces, "-", ".", "(" and ")"; at most 20 characters (trimmed). This is the phone part of the eID Identifier format (see eID verification). A kennitala, a foreign number or any other length fails validation (422) |
| accessCode | string | Optional | Exactly 6 digits. Generated if you leave it out. Must be unique among your tenant's active employees (a duplicate returns 409); a deleted employee's code is free to reuse |
| locationIds | string[] | Optional | Locations to assign the employee to. Each must be a location in your tenant that hasn't been deleted, or the call returns 400 |
namestringRequiredFull name, 1-100 characters
externalIdstringRequiredYour own identifier for the employee, 1-100 characters. Must be unique among your tenant's live employees (a duplicate returns 409); deleting an employee frees it
ssnstringOptionalKennitala, exactly 10 characters. Leave it out to have the employee enroll with eID instead. Hashed before it is stored. Must be unique among your tenant's active employees (a duplicate returns 409). If it belongs to a deleted employee, that employee is restored with the new details and keeps its ID
phoneNumberstringRequiredAn Icelandic phone number: 7 digits, optionally after 354, 00354 or +354, in ASCII digits with optional spaces, "-", ".", "(" and ")"; at most 20 characters (trimmed). This is the phone part of the eID Identifier format (see eID verification). A kennitala, a foreign number or any other length fails validation (422)
accessCodestringOptionalExactly 6 digits. Generated if you leave it out. Must be unique among your tenant's active employees (a duplicate returns 409); a deleted employee's code is free to reuse
locationIdsstring[]OptionalLocations to assign the employee to. Each must be a location in your tenant that hasn't been deleted, or the call returns 400
Examples
cURL
curl -X POST https://abyrgverslun.is/api/v1/employees \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Guðrún Jónsdóttir",
"externalId": "HR-0042",
"phoneNumber": "6912345",
"locationIds": ["jh72m4q9x1c8n3v5b6z0k2d7f4g9t1ra"]
}'Response
// 201 Created
{
"employeeId": "m17d4f6g8h2j3k5l7z9x1c3v5b7n9q2w",
"accessCode": "482913"
}
// 409 Conflict
{
"type": "https://api.aldursvottun.is/errors/conflict",
"title": "Conflict",
"status": 409,
"detail": "An employee with this externalId already exists"
}Errors
400Body is not valid JSON, or a locationIds entry is not a live location in your tenant.401Missing, invalid or expired token.403The token lacks employees:write, or the caller is a device.409The externalId, SSN or access code is already used by an active employee in your tenant.422The body failed validation, e.g. externalId was left out.
Response format: Errors.
/api/v1/employees/{id}Read one employee. Callers: service client (Bearer) and device (DPoP). Includes locationIds but not locations, and the enrollment status and eID name.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Required | Bearer <access_token> (service client) or DPoP <access_token> (device). Requires employees:read. |
| DPoP | string | Optional | Device callers only: the DPoP proof for this request, including ath. |
AuthorizationstringRequiredBearer <access_token> (service client) or DPoP <access_token> (device). Requires employees:read.
DPoPstringOptionalDevice callers only: the DPoP proof for this request, including ath.
Response
{
"data": {
"id": "m17d4f6g8h2j3k5l7z9x1c3v5b7n9q2w",
"createdAt": "2026-04-11T13:02:45.906Z",
"name": "Guðrún Jónsdóttir",
"phoneNumber": "6912345",
"externalId": "HR-0042",
"origin": "api",
"enrollmentStatus": "enrolled",
"eidName": "Guðrún Jónsdóttir",
"locationIds": ["jh72m4q9x1c8n3v5b6z0k2d7f4g9t1ra"],
"updatedAt": 1778063472044
}
}Errors
401Missing, invalid or expired token, or a device token sent as Bearer.403The token lacks employees:read.404No employee with this ID in your tenant: unknown, malformed, deleted, or another tenant's.
Response format: Errors.
/api/v1/employees/codeFind the employee who holds an access code, e.g. to show the employee's name on a device before a manual verification. Callers: service client (Bearer) and device (DPoP); dashboard user tokens get 403. Returns only id, name, updatedAt and createdAt.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Required | Bearer <access_token> (service client) or DPoP <access_token> (device). Requires employees:read. |
| DPoP | string | Optional | Device callers only: the DPoP proof for this request, including ath. |
AuthorizationstringRequiredBearer <access_token> (service client) or DPoP <access_token> (device). Requires employees:read.
DPoPstringOptionalDevice callers only: the DPoP proof for this request, including ath.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| code | string | Required | The employee's 6-digit access code |
codestringRequiredThe employee's 6-digit access code
Examples
cURL
curl "https://abyrgverslun.is/api/v1/employees/code?code=482913" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Response
{
"data": {
"id": "m17d4f6g8h2j3k5l7z9x1c3v5b7n9q2w",
"name": "Guðrún Jónsdóttir",
"updatedAt": 1778063472044,
"createdAt": "2026-04-11T13:02:45.906Z"
}
}Errors
401Missing, invalid or expired token, or a device token sent as Bearer.403The token lacks employees:read, or it is a dashboard user token.404No current employee in your tenant has this code.422code is missing or empty.
Response format: Errors.
/api/v1/employees/{id}Update an employee. Callers: service client (Bearer) only; a device (DPoP) call gets 403. Send only the fields you want to change; fields you leave out keep their values. The access code and location assignments can't be changed through this endpoint. Changing the phone number keeps the employee's enrollment. Returns the updated employee in the same shape as GET /api/v1/employees/{id}.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Required | Bearer <access_token> (service client). Requires employees:write. |
| Content-Type | string | Required | application/json |
AuthorizationstringRequiredBearer <access_token> (service client). Requires employees:write.
Content-TypestringRequiredapplication/json
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | Optional | 1-100 characters |
| phoneNumber | string | Optional | An Icelandic phone number: 7 digits, optionally after 354, 00354 or +354, in ASCII digits with optional spaces, "-", ".", "(" and ")"; at most 20 characters (trimmed). This is the phone part of the eID Identifier format (see eID verification). A kennitala, a foreign number or any other length fails validation (422) |
| externalId | string | Optional | Your own identifier, e.g. an HR system ID. Up to 100 characters. Must be unique among your tenant's live employees (a duplicate returns 409); deleting an employee frees it |
namestringOptional1-100 characters
phoneNumberstringOptionalAn Icelandic phone number: 7 digits, optionally after 354, 00354 or +354, in ASCII digits with optional spaces, "-", ".", "(" and ")"; at most 20 characters (trimmed). This is the phone part of the eID Identifier format (see eID verification). A kennitala, a foreign number or any other length fails validation (422)
externalIdstringOptionalYour own identifier, e.g. an HR system ID. Up to 100 characters. Must be unique among your tenant's live employees (a duplicate returns 409); deleting an employee frees it
Examples
cURL
curl -X PATCH https://abyrgverslun.is/api/v1/employees/m17d4f6g8h2j3k5l7z9x1c3v5b7n9q2w \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "externalId": "HR-0042" }'Response
{
"data": {
"id": "m17d4f6g8h2j3k5l7z9x1c3v5b7n9q2w",
"createdAt": "2026-04-11T13:02:45.906Z",
"name": "Guðrún Jónsdóttir",
"phoneNumber": "6912345",
"externalId": "HR-0042",
"locationIds": ["jh72m4q9x1c8n3v5b6z0k2d7f4g9t1ra"],
"updatedAt": 1778063472301
}
}Errors
400Body is not valid JSON, or on a test tenant phoneNumber is not a test eID identifier (see Test mode).401Missing, invalid or expired token.403The token lacks employees:write, the caller is a device, or the ID belongs to another tenant.404Unknown, malformed or deleted employee ID.409The externalId is already used by another employee in your tenant.422The body failed validation.
Response format: Errors.
/api/v1/employees/{id}Delete an employee. Callers: service client (Bearer) only; a device (DPoP) call gets 403. This is a soft delete: the employee disappears from lists and reads and can no longer attest manual verifications, but the location assignments are not removed. The deleted employee's access code and externalId are freed, and creating an employee with the same SSN restores the deleted one (same ID) instead of making a new one. Deleting the same employee again returns 404.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Required | Bearer <access_token> (service client). Requires employees:delete or employees:write. |
AuthorizationstringRequiredBearer <access_token> (service client). Requires employees:delete or employees:write.
Response
{ "deleted": true }Errors
401Missing, invalid or expired token.403The token lacks both employees:delete and employees:write, the caller is a device, or the ID belongs to another tenant.404Unknown, malformed or already deleted employee ID.
Response format: Errors.
/api/v1/employees/{id}/enrollmentStart Employee Enrollment: sends an eID request to the employee's phone. Callers: service client (Bearer). Show the returned code on the terminal so the employee can match it on their phone, then poll GET /api/v1/employees/{id}/enrollment. Starting again replaces a pending, rejected or timed-out request; an enrolled employee must be reset first (409). An employee entered with a kennitala whose person is already another employee of your tenant gets 409 enrollment-identity-in-use, and no eID request is sent.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Required | Bearer <access_token> (service client). Requires employees:write. |
| Content-Type | string | Required | application/json |
AuthorizationstringRequiredBearer <access_token> (service client). Requires employees:write.
Content-TypestringRequiredapplication/json
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
| phoneNumber | string | Required | The phone to send the eID request to. An Icelandic phone number: 7 digits, optionally after 354, 00354 or +354, in ASCII digits with optional spaces, "-", ".", "(" and ")"; at most 20 characters (trimmed). This is the phone part of the eID Identifier format (see eID verification). A kennitala, a foreign number or any other length fails validation (422) |
phoneNumberstringRequiredThe phone to send the eID request to. An Icelandic phone number: 7 digits, optionally after 354, 00354 or +354, in ASCII digits with optional spaces, "-", ".", "(" and ")"; at most 20 characters (trimmed). This is the phone part of the eID Identifier format (see eID verification). A kennitala, a foreign number or any other length fails validation (422)
Examples
cURL
curl -X POST https://abyrgverslun.is/api/v1/employees/m17d4f6g8h2j3k5l7z9x1c3v5b7n9q2w/enrollment \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "phoneNumber": "6912345" }'Response
{
"id": "m17d4f6g8h2j3k5l7z9x1c3v5b7n9q2w",
"status": "pending",
"code": "4821",
"livemode": true
}Errors
400Body is not valid JSON, or on a test tenant phoneNumber is not a test eID identifier (see Test mode).401Missing, invalid or expired token.403The token lacks employees:write, or the ID belongs to another tenant.404Unknown, malformed or deleted employee ID.409The employee is already enrolled (type conflict), or was entered with a kennitala whose person is already another employee of your tenant (type enrollment-identity-in-use).422phoneNumber is missing or invalid.500The eID Provider could not start the request.
Response format: Errors.
/api/v1/employees/{id}/enrollmentPoll Employee Enrollment every 2 to 3 seconds while status is pending. Callers: service client (Bearer). status is pending, enrolled, rejected or timeout (no answer within 5 minutes). A rejected eID that succeeded carries a reason: identity_mismatch (the eID belongs to someone other than the kennitala on file) or identity_in_use (the person is already another employee of your tenant); without a reason, the employee declined. Once enrolled, eidName is the name the eID reported; the kennitala itself is stored only hashed and is never returned.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Required | Bearer <access_token> (service client). Requires employees:write. |
AuthorizationstringRequiredBearer <access_token> (service client). Requires employees:write.
Response
// Pending
{ "id": "m17d4f6g8h2j3k5l7z9x1c3v5b7n9q2w", "status": "pending", "livemode": true }
// Enrolled
{
"id": "m17d4f6g8h2j3k5l7z9x1c3v5b7n9q2w",
"status": "enrolled",
"eidName": "Guðrún Jónsdóttir",
"livemode": true
}
// Already another employee
{
"id": "m17d4f6g8h2j3k5l7z9x1c3v5b7n9q2w",
"status": "rejected",
"reason": "identity_in_use",
"livemode": true
}Errors
401Missing, invalid or expired token.403The token lacks employees:write.404Unknown, malformed, deleted or another tenant's employee, or the employee has never started enrolling.
Response format: Errors.
/api/v1/employees/{id}/enrollmentReset Employee Enrollment, e.g. when the wrong person enrolled. Callers: service client (Bearer). The employee is no longer enrolled and can enroll again. Resetting an employee who is not enrolled also returns 204.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Required | Bearer <access_token> (service client). Requires employees:write. |
AuthorizationstringRequiredBearer <access_token> (service client). Requires employees:write.
Response
// 204 No ContentErrors
401Missing, invalid or expired token.403The token lacks employees:write, or the ID belongs to another tenant.404Unknown, malformed or deleted employee ID.
Response format: Errors.