This chapter is the endpoint reference for the people your system knows about and the credentials that identify them at a reader: persons (personnel), users (people who can log in and host visitors), groups, credentials and watchlists.
If you have never integrated with the product before, read the model first:
- A person is a personnel record. Contractors, employees and suppliers are persons. A person cannot log in.
- A user is a login account. Hosts, receptionists, guards and administrators are users. A user can host visitors and can own credentials of their own.
- A credential is what a reader actually sees: an RFID card number, a PIN, a face template, a licence plate. A credential belongs to exactly one person or one user, and it opens nothing until access control lists are assigned to it.
- A group is a simple label used to bucket users and persons (for example “Contractors”). Groups are also referenced when creating people, so create them first.
- A watchlist is a named list of identities and vehicles you want flagged. Reception and checkpoint screens check arrivals against every enabled watchlist.
The reference-data resources these records point at (locations, departments, organisations, roles, cost centers) are documented in Reference Data API.
Authentication
Every endpoint on this page requires an API key. Send the key in the Authorization request header. The Bearer prefix is optional and is stripped if present, so both of these are accepted:
Authorization: <api-key-token>
Authorization: Bearer <api-key-token>
A token shorter than 64 characters or longer than 256 characters is rejected before anything else happens. Create keys and grant their read and write permissions under Configuration > System Settings > Web Service API; see API Key Configuration.
Each resource below names the two permissions it checks. A key that authenticates but lacks the permission gets 403, never a partial result.
Scoping
An API key belongs to exactly one system. Every endpoint on this page resolves the calling system from the key and filters on it, so a key can only ever read, change or delete records belonging to its own system. There is no parameter to widen that scope and no way to reach another system’s data by guessing a UUID: a UUID that exists elsewhere returns 404.
Rate limiting
Requests are metered per API key. When the bucket is empty the response is 429 and the standard Retry-After response header gives the number of seconds to wait before retrying. Buckets are per server node and this deployment is not session-pinned, so treat the value as a lower bound and a hint rather than a cluster-wide guarantee: honour it, then back off further if you are throttled again. Write operations on credentials cost more than reads.
Conventions used on this page
- Identifiers are always UUIDs. Every path parameter, every reference between records and every identifier in a response body is a UUID. Internal numeric identifiers are never accepted and never returned.
- Timestamps are ISO 8601 with an explicit offset, for example
2026-02-02T12:40:57.000+0000. Values are stored and returned in UTC. - Successful writes return an acknowledgement, not the changed record:
{"code": 201, "message": "success", "uuid": "57fa54a4-d6a5-4a04-a559-b97d6043dccf"}
Re-read the record with its GET endpoint if you need the stored values back.
- Errors return
{"code": <status>, "reason": "<explanation>"}. Field-level validation failures return422and list the offending fields inreason. uuidin a request body is ignored on update. The UUID in the URL identifies the record.- Common status codes, unless a section says otherwise:
400malformed or missing body,401missing or invalid key,403key lacks the permission,404unknown UUID,409duplicate,422field validation failed,429rate limited.
Persons
A person is a personnel record: staff, contractors, suppliers. Persons are the usual holders of long-lived badges. There is no “list all persons” endpoint by design, because listing personnel exposes personal data in a URL; use the search endpoint, which takes its criteria in the request body.
Permissions: Read Personnel for the search and read endpoints, Write Personnel for create, update and delete.
The equivalent admin screens are Add Personnel and Edit Personnel.
POST /api/ws/v1/persons/search
Returns a page of persons. Read-only.
Request body, all fields optional:
| Field | Type | Notes |
|---|---|---|
start | integer | Zero-based index of the first row. Minimum 0. Defaults to 0. |
limit | integer | Rows to return. Must be between 100 and 1000. Defaults to 500. A value outside the range returns 422. |
firstName | string, max 100 | Case-insensitive “contains” match. |
lastName | string, max 100 | Case-insensitive “contains” match. |
email | string, max 100 | Case-insensitive “contains” match. |
mobileNumber | string, max 100 | Case-insensitive “contains” match. |
identityNr | string, max 100 | Case-insensitive “contains” match against the identity number. |
Supplying several text fields narrows the result: a row must match all of them.
Response:
{
"entries": [
{
"uuid": "21bf9d3b-8c8f-4eec-a398-c9650d0dc2c0",
"firstName": "Alexander",
"lastName": "Grant",
"email": "alexander.grant@evtrack.com",
"mobile": "+12125680012"
}
],
"startIndex": 0,
"countReturned": 1,
"totalCount": 248
}
The identity number can be searched on but is never returned in a search row. Read the person to see the rest of the record.
Status codes: 200, 400 (no body at all), 401, 403, 422, 429.
curl -X POST 'https://service.evtrack.com/api/ws/v1/persons/search' \
-H 'Authorization: Bearer <api-key-token>' \
-H 'Content-Type: application/json' \
-d '{"start": 0, "limit": 100, "lastName": "Grant"}'
GET /api/ws/v1/persons/{uuid}
Reads one person. Read-only.
Path parameter: uuid, the person UUID.
Returns the full person record: names, contact numbers, identity documents, the three address blocks, employment dates, the medical and induction validity windows, the referenced location, department, organisation, group and cost center (each as a UUID), and hasPhoto telling you whether a badge photo is stored.
Status codes: 200, 400, 401, 403, 404, 429.
POST /api/ws/v1/persons
Creates a person. Returns 201.
Only firstName is required. Everything else is optional.
| Field | Type | Constraint |
|---|---|---|
firstName | string | Required. Max 50 characters. |
lastName, middleName, nickName | string | Max 50 characters each. |
title, suffix | string | Max 20 characters. |
personType | enum | One of CONTRACTOR, EMPLOYEE_FULL_TIME, EMPLOYEE_PART_TIME, INTERN, TEMP, OTHER, SUPPLIER, VISITOR. |
status | enum | One of ACTIVE, INACTIVE, ON_LEAVE, RETIRED, TERMINATED. |
dateOfBirth, hiredDate, terminationDate | string | Calendar dates in yyyy-MM-dd form. |
email, emailAlternative | string | Must be a valid address. Max 100 characters. |
mobile, telephoneOffice, telephoneHome, telephoneOther | string | International notation, for example +12125680012. Max 50 characters. |
telephoneExtension, fax | string | Max 50 characters. |
identityNumber, passportNumber, driversLicenceNumber, staffIdNumber | string | Max 50 characters each. |
occupation | string | Max 50 characters. |
notes, comments | string | Max 10000 characters each. |
enable | boolean | Whether the record is active. |
homeAddressLine1 … homeAddressCountry | string | Max 50 characters per address field. The same seven fields exist as workAddress* and otherAddress*. |
location, department, organisation, group, costCenter | UUID | Must already exist. An unknown UUID returns 422 naming which one. |
activeDate, expiryDate | timestamp | The validity window of the personnel record. |
medicalActiveDate, medicalExpiryDate | timestamp | Medical clearance window. |
inductionActiveDate, inductionExpiryDate | timestamp | Site induction window. |
firstNations, peopleOfDetermination | boolean | Optional classification flags. |
photoUuid | UUID | Identifier returned by the file upload endpoint. Write-only. An identifier that has expired or was never issued returns 422. |
hasPhoto is read-only and is ignored if you send it.
Status codes: 201, 400, 401, 403, 409 (duplicate person), 422, 429.
curl -X POST 'https://service.evtrack.com/api/ws/v1/persons' \
-H 'Authorization: Bearer <api-key-token>' \
-H 'Content-Type: application/json' \
-d '{
"firstName": "Alexander",
"lastName": "Grant",
"email": "alexander.grant@evtrack.com",
"mobile": "+12125680012",
"personType": "CONTRACTOR",
"staffIdNumber": "EVL-4471",
"department": "f1ff3418-ef26-41a9-842e-e4874beecdc2",
"activeDate": "2026-02-02T00:00:00.000+0000",
"expiryDate": "2027-02-02T00:00:00.000+0000"
}'
PUT /api/ws/v1/persons/{uuid}
Replaces a person. Returns 200.
The body is the same object as create, with the same constraints, and firstName is still required.
This is a full replacement, not a merge. The stored record is rebuilt from the payload, so any field you leave out is cleared. Read the person first, change what you need, and send the whole object back.
Status codes: 200, 400, 401, 403, 404, 409, 422, 429.
DELETE /api/ws/v1/persons/{uuid}
Deletes a person. Returns 200.
This is a hard delete. The personnel record is removed. Before the row goes, the system unlinks every credential the person held, withdraws their entry from the phonebooks of any connected access control hardware, and deletes their personnel QR code. The credentials themselves survive as unassigned records; they no longer identify anybody.
Status codes: 200, 400, 401, 403, 404, 429.
Users
A user is a login account. Hosts, receptionists, guards and administrators are all users. Users own their own credentials, and they are the people visitor invitations are attributed to.
Permissions: Read Users for the list, search, read, invites and pre-registrations endpoints, Write Users for create, update, delete, enable and disable.
The equivalent admin screens are Add a User and Edit a User.
GET /api/ws/v1/users (deprecated)
Lists and searches users using query parameters: start, limit (100 to 1000, default 500), first_name, last_name, mobile, email, identity_nr.
Use POST /api/ws/v1/users/search instead. The query-parameter form puts names, email addresses and phone numbers into the URL, where they end up in proxy logs and browser history. This endpoint is kept only so existing integrations keep working.
POST /api/ws/v1/users/search
Returns a page of users. Read-only. Takes the same criteria object as the person search, in the request body.
| Field | Type | Notes |
|---|---|---|
start | integer | Zero-based. Minimum 0. Defaults to 0. |
limit | integer | Between 100 and 1000. Defaults to 500. Outside the range returns 422. |
firstName, lastName, email, mobileNumber, identityNr | string, max 100 each | Partial, case-insensitive matches. |
Response:
{
"entries": [
{
"uuid": "21bf9d3b-8c8f-4eec-a398-c9650d0dc2c0",
"firstName": "Alexander",
"lastName": "Grant",
"email": "alexander.grant@evtrack.com",
"mobile": "+12125680012"
}
],
"startIndex": 0,
"countReturned": 1,
"totalCount": 50
}
Status codes: 200, 400, 401, 403, 422, 429.
curl -X POST 'https://service.evtrack.com/api/ws/v1/users/search' \
-H 'Authorization: Bearer <api-key-token>' \
-H 'Content-Type: application/json' \
-d '{"start": 0, "limit": 500, "mobileNumber": "+12125680012"}'
GET /api/ws/v1/users/{uuid}
Reads one user. Read-only.
Returns the full account: username, enabled, the assigned role UUID, names, contact numbers, identity number, address, comments, the referenced location, group, organisation and department as UUIDs, accountActiveDate, accountExpiryDate and hasPhoto. The password field is always returned empty.
Status codes: 200, 400, 401, 403, 404, 429.
POST /api/ws/v1/users
Creates a user. Returns 201.
| Field | Type | Constraint |
|---|---|---|
email | string | Required. Must be a valid address, max 100 characters. |
username | string | 2 to 50 characters. If omitted, a random username is generated, and the account can then only be used through single sign-on or the API. |
password | string | If supplied: 8 to 30 characters with at least one upper-case letter, one lower-case letter, one digit and one symbol, and no spaces. |
enabled | boolean | Whether the account may log in. |
sendOnBoardingMessage | boolean | Sends the welcome email. If it is true and no password was supplied, one is generated for the email. |
role | UUID | Permission role. If omitted, the system default role is assigned. An unknown UUID returns 422. |
title | string | Max 20 characters. |
firstName, middleName, lastName | string | Max 50 characters each. |
identityNumber | string | Max 50 characters. |
address | string | Max 50 characters. |
mobile, telephoneOffice, telephoneHome | string | International notation, max 50 characters. |
telephoneExtension | string | Max 50 characters. |
comments | string | Max 5000 characters. |
location, group, organisation, department | UUID | Must already exist. An unknown UUID returns 422 naming which one. |
accountActiveDate, accountExpiryDate | timestamp | Account validity window. |
photoUuid | UUID | Identifier returned by the file upload endpoint. Write-only. |
Status codes: 201, 400, 401, 403, 409 (email or username already in use), 422, 429.
curl -X POST 'https://service.evtrack.com/api/ws/v1/users' \
-H 'Authorization: Bearer <api-key-token>' \
-H 'Content-Type: application/json' \
-d '{
"username": "alexander.grant",
"email": "alexander.grant@evtrack.com",
"firstName": "Alexander",
"lastName": "Grant",
"mobile": "+12125680012",
"enabled": true,
"sendOnBoardingMessage": true,
"role": "ed8dbd8c-67e5-4654-81d7-2b47d311e3a8"
}'
PUT /api/ws/v1/users/{uuid}
Replaces a user. Returns 200. Same body and same constraints as create.
This is a full replacement, not a merge, and two omissions are destructive:
- Leaving out
rolereassigns the account to the system default role. - Leaving out
usernamereplaces the username with a generated one, which locks the person out of password login.
Always read the user first and send the complete object back.
Status codes: 200, 400, 401, 403, 404, 409, 422, 429.
DELETE /api/ws/v1/users/{uuid}
Deletes a user. Returns 200.
This is a hard delete and it cascades: every active invitation the user is hosting is cancelled, every credential they held is unlinked, their personnel QR code is removed, and any session or token they hold stops working on the next request.
Status codes: 200, 400, 401, 403, 404, 429.
PUT /api/ws/v1/users/{uuid}/enable
Enables the account. No request body. Returns 200.
Status codes: 200, 401, 403, 404, 409, 429.
PUT /api/ws/v1/users/{uuid}/disable
Disables the account. No request body. Returns 200. The record and its credentials remain in place; the person simply cannot log in.
Status codes: 200, 401, 403, 404, 409, 429.
GET /api/ws/v1/users/{uuid}/invites
Lists the invitations this user is hosting. Read-only. Covers the window from 62 days ago to 365 days ahead.
Each entry carries registrationId, visitorId, firstName, lastName, activation, expiry, the credential type, the accessCode (the PIN when the invite issues a PIN, otherwise the credential identifier), qrCodeUrl, inviteLink and inviteTextMessage.
Status codes: 200, 400, 401, 403, 404, 429.
GET /api/ws/v1/users/{uuid}/registrations
Lists the pre-registrations attached to this user, from the host’s point of view. Read-only.
Query parameters:
| Parameter | Type | Notes |
|---|---|---|
start | integer | Zero-based. Minimum 0. Defaults to 0. |
limit | integer | Between 1 and 500. Defaults to 100. |
status | string | ALL (default), FINALISED (approved or completed), APPROVE (waiting for this host to approve), WAITING (pending compliance review). An unrecognised value falls back to ALL. |
Returns the usual paged envelope with entries, startIndex, countReturned and totalCount.
Status codes: 200, 400, 401, 403, 404, 429.
Groups
A group is a plain label used to bucket users and persons, for example “Contractors” or “Night Shift”. Groups carry no permissions of their own; they exist so that people can be filtered and reported on together, and so that other records can reference them.
Permissions: Read Groups for the two read endpoints, Write Groups for create, update and delete.
Create the groups you need before creating persons or users that reference them.
GET /api/ws/v1/groups
Lists every group. Read-only. No parameters, no pagination.
[{"uuid": "426fdf56-776e-476c-a979-95766ef004c0", "name": "Contractors"}]
Status codes: 200, 400, 401, 403, 429.
GET /api/ws/v1/groups/{uuid}
Reads one group. Read-only. Returns the same object as a list row.
Status codes: 200, 400, 401, 403, 404, 429.
POST /api/ws/v1/groups
Creates a group. Returns 201.
| Field | Type | Constraint |
|---|---|---|
name | string | Required. 2 to 100 characters. |
Status codes: 201, 400, 401, 403, 409 (a group with that name exists), 422, 429.
curl -X POST 'https://service.evtrack.com/api/ws/v1/groups' \
-H 'Authorization: Bearer <api-key-token>' \
-H 'Content-Type: application/json' \
-d '{"name": "Contractors"}'
PUT /api/ws/v1/groups/{uuid}
Renames a group. Returns 200. Body as for create; the uuid field in the body is ignored.
Status codes: 200, 400, 401, 403, 404, 409, 422, 429.
DELETE /api/ws/v1/groups/{uuid}
Deletes a group. Returns 200. Hard delete. People who referenced the group simply lose the label.
Status codes: 200, 400, 401, 403, 404, 429.
Credentials
A credential is what a reader recognises: a card number, a PIN, a face, a licence plate. It belongs to exactly one person or one user, it has a validity window, and it opens nothing until access control lists are assigned to it. Creating a credential with no lists produces something that identifies its owner and grants no access anywhere, which is almost never what you want.
Permissions: Read Credentials for the read endpoints, Write Credentials for create, update and delete. Credential writes are metered more heavily than reads, because each one is pushed out to connected hardware.
The equivalent admin screens are RFID Card Credentials (Personnel), Face Credentials (Personnel), RFID Card Credentials (Users) and Face Credentials (Users). Access control lists are managed under Access Control Lists and can be read through the API from Reference Data API.
There is deliberately no “list all credentials” endpoint. Credentials are always fetched by their own UUID or through their holder.
Reader types (readerType): CONTACTLESS_CARD (RFID card), PIN, LPR (licence plate), MVL, IDENTITY, QR_CODE, MOBILE, FACE, WATCHLIST_THREAT, plus the combined types MVL_ID, LPR_MVL_ID, PIN_LPR, PIN_ID, PIN_MVL, PIN_MVL_ID, PIN_ID_LPR, PIN_MVL_LPR, PIN_MVL_ID_LPR and DRIVER_LICENCE_CARD. The combined and driver-licence types are legacy and should not be used for new integrations.
Statuses (status): VALID, ACTIVE, EXPIRED, DISABLED, DELETED, LOST, STOLEN, DESTROYED. A credential whose window has not opened yet is VALID; the system flips it to ACTIVE when the window opens. Only ACTIVE credentials are pushed to hardware.
Credential types (type, read-only in responses): PERSONNEL, USER, VISITOR, TEMPORARY, UNKNOWN. This is derived from the holder, not something you set.
GET /api/ws/v1/credentials/{uuid}
Reads one credential. Read-only.
{
"uuid": "7aaee0e2-6884-4fd7-ba63-21d76723dce2",
"readerType": "CONTACTLESS_CARD",
"status": "ACTIVE",
"type": "PERSONNEL",
"uniqueIdentifier": "0123456789",
"holderFirstName": "Alexander",
"holderLastName": "Grant",
"holderUuid": "21bf9d3b-8c8f-4eec-a398-c9650d0dc2c0",
"activeDate": "2026-02-02T00:00:00Z",
"expiryDate": "2027-02-02T00:00:00Z"
}
holderUuid is the UUID of the person or user who holds the credential.
Status codes: 200, 400, 401, 403, 404, 429.
POST /api/ws/v1/credentials
Creates a credential. Returns 201.
| Field | Type | Constraint |
|---|---|---|
readerType | enum | Required. See the reader types above. |
personUuid | UUID | The holder, if the credential belongs to a person. |
userUuid | UUID | The holder, if the credential belongs to a user. |
uniqueIdentifier | string | Max 255 characters. The card number, plate or template reference. |
pin | integer | Between 1000 and 999999. |
status | enum | Defaults to the normal lifecycle status if omitted. |
enabled | boolean | Whether the credential is live. |
useLimit | integer | Number of admissions before the credential stops working. Omit for unlimited. |
activeDate, expiryDate | timestamp | Validity window. |
accessControlListUuids | array of UUID | Up to 50 entries. Each must exist. An unknown UUID returns 422. |
comments | string | Max 10000 characters. |
data | string | Free-form JSON payload for driver-specific values. Max 10000 characters. |
Exactly one of personUuid or userUuid must be present. Sending neither, or both, returns 422.
Status codes: 201, 400, 401, 403, 404 (holder UUID not found), 409 (that identifier is already issued), 422, 429.
curl -X POST 'https://service.evtrack.com/api/ws/v1/credentials' \
-H 'Authorization: Bearer <api-key-token>' \
-H 'Content-Type: application/json' \
-d '{
"readerType": "CONTACTLESS_CARD",
"uniqueIdentifier": "0A1B2C3D",
"personUuid": "21bf9d3b-8c8f-4eec-a398-c9650d0dc2c0",
"activeDate": "2026-02-02T00:00:00.000+0000",
"expiryDate": "2027-02-02T00:00:00.000+0000",
"accessControlListUuids": ["b203486c-5ac3-41a6-8eb3-e79d64649128"]
}'
PUT /api/ws/v1/credentials/{uuid}
Updates a credential. Returns 200.
Unlike persons and users, this is not a full replacement. The update path handles three things: the validity window, the assigned access control lists, and a status change.
| Field | Effect |
|---|---|
activeDate, expiryDate | Set the new validity window. Extending an expired window puts the credential back on the normal lifecycle. |
useLimit | Sets the remaining admissions. |
accessControlListUuids | Replaces the assigned lists with exactly this set. Sending an empty array removes all access. Omitting the field leaves the current assignment alone. |
comments | Replaces the comment. |
status | DISABLED disables the credential and removes it from connected hardware. DELETED marks it deleted, with the same removal. Any other value is applied as part of the validity update. |
readerType cannot be changed after creation. It is accepted in the body and ignored, so you can safely send a record you just read back.
Status codes: 200, 400, 401, 403, 404, 409, 422, 429.
curl -X PUT 'https://service.evtrack.com/api/ws/v1/credentials/7aaee0e2-6884-4fd7-ba63-21d76723dce2' \
-H 'Authorization: Bearer <api-key-token>' \
-H 'Content-Type: application/json' \
-d '{
"expiryDate": "2028-02-02T00:00:00.000+0000",
"accessControlListUuids": ["b203486c-5ac3-41a6-8eb3-e79d64649128"]
}'
DELETE /api/ws/v1/credentials/{uuid}
Retires a credential. Returns 200.
This is a soft delete. The credential is marked DELETED and removed from every connected reader, but the record itself remains for audit purposes and the card number remains reserved. Read it back afterwards and you will still get the record, with status DELETED.
Status codes: 200, 400, 401, 403, 404, 429.
GET /api/ws/v1/credentials/by-person/{personUuid}
Lists every credential held by a person. Read-only. Returns an array of the same objects as the single read.
Status codes: 200, 400, 401, 403, 404, 429.
GET /api/ws/v1/credentials/by-user/{userUuid}
Lists every credential held by a user, in every status. Read-only. Returns an array of the same objects as the single read.
Status codes: 200, 400, 401, 403, 404, 429.
Watchlists
A watchlist is a named list of identities and vehicles you want flagged on arrival. Every enabled watchlist is consulted when a visitor is registered or checked in, and a match raises an alert instead of a quiet admission. A watchlist has a name and an enabled flag; the identities live in it as entries.
Permissions: Read Watchlists for the read endpoints and the match check, Write Watchlists for create, update and delete of both watchlists and their entries.
The equivalent admin screen is Watchlist.
Every watchlist write is attributed in the audit trail to the API key by name, so use one key per consuming application.
GET /api/ws/v1/watchlists
Lists every watchlist. Read-only. No parameters.
[{"uuid": "7aaee0e2-6884-4fd7-ba63-21d76723dce2", "name": "Banned Visitors", "enabled": true, "entryCount": 42}]
Status codes: 200, 400, 401, 403, 429.
GET /api/ws/v1/watchlists/{uuid}
Reads one watchlist. Read-only. Returns the same object as a list row.
Status codes: 200, 400, 401, 403, 404, 429.
POST /api/ws/v1/watchlists
Creates a watchlist. Returns 201.
| Field | Type | Constraint |
|---|---|---|
name | string | Required. 5 to 100 characters. |
enabled | boolean | Defaults to true. A disabled watchlist is not consulted on arrival. |
Status codes: 201, 400, 401, 403, 409, 422, 429.
curl -X POST 'https://service.evtrack.com/api/ws/v1/watchlists' \
-H 'Authorization: Bearer <api-key-token>' \
-H 'Content-Type: application/json' \
-d '{"name": "Banned Visitors", "enabled": true}'
PUT /api/ws/v1/watchlists/{uuid}
Updates a watchlist name or enabled flag. Returns 200. Body as for create.
Status codes: 200, 400, 401, 403, 404, 409, 422, 429.
DELETE /api/ws/v1/watchlists/{uuid}
Deletes a watchlist. Returns 200.
This is a hard delete. The watchlist and all of its entries are removed, and any flags they placed on connected hardware are withdrawn first.
Status codes: 200, 400, 401, 403, 404, 429.
GET /api/ws/v1/watchlists/{watchlistUuid}/entries
Lists the entries in one watchlist, paged. Read-only.
| Parameter | Type | Notes |
|---|---|---|
start | integer | Zero-based. Must be 0 or greater. Defaults to 0. |
limit | integer | Between 1 and 1000. Defaults to 500. |
Response:
{
"entries": [
{
"uuid": "8175be3a-461a-4608-90d5-1168b4d06126",
"watchlistUuid": "7aaee0e2-6884-4fd7-ba63-21d76723dce2",
"identityNumber": "9001015009087",
"passportNr": "A032734565",
"firstName": "Alexander",
"lastName": "Grant",
"mobileNumber": "+12125680012",
"vehicleLicensePlate": "ABC123GP",
"vehicleVin": "1HGBH41JXMN109186",
"reason": "Access withdrawn"
}
],
"startIndex": 0,
"countReturned": 1,
"totalCount": 42
}
Status codes: 200, 400, 401, 403, 404, 422 (bad paging values), 429.
GET /api/ws/v1/watchlists/{watchlistUuid}/entries/{entryUuid}
Reads one entry. Read-only. The entry must belong to the watchlist in the path; if it does not, the response is 404.
Status codes: 200, 400, 401, 403, 404, 429.
POST /api/ws/v1/watchlists/{watchlistUuid}/entries
Adds an entry. Returns 201.
| Field | Type | Constraint |
|---|---|---|
identityNumber | string | Max 100 characters. |
passportNr | string | Max 100 characters. |
firstName | string | Max 100 characters. |
lastName | string | Max 100 characters. |
mobileNumber | string | Max 100 characters. |
vehicleLicensePlate | string | Max 50 characters. |
vehicleVin | string | Max 50 characters. |
reason | string | Max 2000 characters. Shown to the operator when the entry matches. |
Every field is individually optional, but at least one identifying field is required: identityNumber, passportNr, firstName, lastName, mobileNumber, vehicleLicensePlate or vehicleVin. An entry with only a reason returns 422.
Status codes: 201, 400, 401, 403, 404 (unknown watchlist), 409, 422, 429.
curl -X POST 'https://service.evtrack.com/api/ws/v1/watchlists/7aaee0e2-6884-4fd7-ba63-21d76723dce2/entries' \
-H 'Authorization: Bearer <api-key-token>' \
-H 'Content-Type: application/json' \
-d '{
"firstName": "Alexander",
"lastName": "Grant",
"identityNumber": "9001015009087",
"reason": "Access withdrawn"
}'
PUT /api/ws/v1/watchlists/{watchlistUuid}/entries/{entryUuid}
Updates an entry. Returns 200. Same body and same “at least one identifying field” rule as create. The entry must belong to the watchlist in the path.
Status codes: 200, 400, 401, 403, 404, 409, 422, 429.
DELETE /api/ws/v1/watchlists/{watchlistUuid}/entries/{entryUuid}
Removes an entry. Returns 200. Hard delete. The entry must belong to the watchlist in the path.
Status codes: 200, 400, 401, 403, 404, 429.
POST /api/ws/v1/watchlists/match
Checks an identity or a vehicle against every enabled watchlist. Read-only: nothing is written and no alert is raised. This is the endpoint to call from your own booking or gatehouse front end before you commit a registration.
Request body, all fields optional but at least one required:
| Field | Type | Constraint |
|---|---|---|
identityNumber | string | Max 100 characters. |
passportNr | string | Max 100 characters. |
firstName | string | Max 100 characters. |
lastName | string | Max 100 characters. |
mobileNumber | string | Max 100 characters. |
vehicleLicensePlate | string | Max 50 characters. |
vehicleVin | string | Max 50 characters. |
Identity fields and vehicle fields are matched separately and the results are merged, so one request can return both an identity match and a vehicle match. Duplicate hits on the same entry are collapsed.
Response:
{
"matched": true,
"matches": [
{
"watchlistUuid": "7aaee0e2-6884-4fd7-ba63-21d76723dce2",
"entryUuid": "8175be3a-461a-4608-90d5-1168b4d06126",
"matchType": "identity"
}
]
}
matched is false and matches is empty when nothing was found. matchType says which kind of field triggered the hit.
Status codes: 200, 400, 401, 403, 422 (no field supplied), 429.
curl -X POST 'https://service.evtrack.com/api/ws/v1/watchlists/match' \
-H 'Authorization: Bearer <api-key-token>' \
-H 'Content-Type: application/json' \
-d '{"identityNumber": "9001015009087", "vehicleLicensePlate": "ABC123GP"}'
GET /api/ws/v1/watchlists/{watchlistUuid}/entries/visitors
Lists the visitors already on record who match any entry in this watchlist. Read-only. Use it to see who a newly added watchlist would have caught.
| Parameter | Type | Notes |
|---|---|---|
start | integer | Zero-based. Must be 0 or greater. Defaults to 0. |
limit | integer | Between 1 and 1000. Defaults to 500. |
Returns an array of {uuid, firstName, lastName}.
Status codes: 200, 400, 401, 403, 404, 422, 429.
GET /api/ws/v1/watchlists/{watchlistUuid}/entries/{entryUuid}/visitors
Lists the visitors on record who match one specific entry. Read-only. Returns the same array shape. The entry must belong to the watchlist in the path.
Status codes: 200, 400, 401, 403, 404, 429.