# Workers and watches

> How the API identifies each person and their watch: company identifier, optional name by contract, battery, whether it’s being worn and last connection.

Page: https://safeonuba.com/en/developers/concepts/workers-and-watches · SafeOnuba API v1 (`api_version: "2026-09-24"`), in preview: the contract may change.

Every person wears a watch. The API exposes them separately —workers and watches— and links them to each other. Both require the `workers:read` scope.

## Workers

`GET /v1/workers` and `GET /v1/workers/{id}`.

| Field | What it is |
| --- | --- |
| `id` | The worker’s UUID in SafeOnuba. |
| `external_id` | Their code in your company, the one from your personnel system. `null` if none has been given. |
| `name` | Full name. **Only if the contract includes it**; otherwise the property doesn’t appear. |
| `contractor` | The contractor they work for, or `null`. |
| `role` | Their job, or `null`. |
| `is_active` | Whether they are registered. |
| `device` | The watch assigned to them. |
| `date_last_seen` | The more recent of their last position and the watch’s last contact. |

### No names

Workers’ names are optional by contract. Without them, the API identifies each person by their `external_id`, the same code your company already uses. To cross-reference with your personnel or access control system, use that field, which doesn’t depend on the contract including names.

The same approach applies everywhere: in `worker` inside an alert, in the list of who is missing and in positions.

### What your client sees

The API sees the same as a person in the dashboard with those permissions, including the scope by contractor. A worker your identity can’t see responds `404`, as if they didn’t exist.

## Watches

`GET /v1/devices` returns the watches with their status.

| Field | What it is |
| --- | --- |
| `id`, `serial` | Identifier and serial number. |
| `model` | Model, or `null`. |
| `status` | The watch’s status in the inventory. |
| `battery` | Battery as a percentage, or `null`. |
| `worn` | Whether it is being worn. `null` if unknown, because the watch has no wrist sensor. |
| `date_last_seen` | Last contact. |
| `worker` | Who it is assigned to. |

| status | What it means |
| --- | --- |
| `active` | In use. |
| `inactive` | Out of use. |
| `maintenance` | Under maintenance. |
| `lost` | Lost. |

A watch that stops communicating or runs out of battery generates an alert (`device_offline`, `low_battery`). You don’t need to poll this list in a loop to find out: they arrive by webhook like any other alert.

## There are never vital signs

Neither the worker nor the watch carries pulse, temperature or any other vital sign, individually or aggregated. See [Privacy and security](https://safeonuba.com/en/developers/privacy-and-security).
