> ## Documentation Index
> Fetch the complete documentation index at: https://help.skillsdb.com/llms.txt
> Use this file to discover all available pages before exploring further.

# The Person object

> A person in the company: identity, contact details, access level, manager, org schema placement and lifecycle

<Info>
  **Quick Summary:** People are the company's workforce records. What a caller can see and change is always bounded by the acting identity behind the credential — a manager's credential sees their span of control, an admin's their departments.
</Info>

## Attributes

| Field                                                     | Type           | Description                                                                                                                     |
| --------------------------------------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `id`                                                      | string         | Opaque person id                                                                                                                |
| `externalId`                                              | string \| null | The customer's own identifier — **the field an integration should key on**. Customer-supplied and not guaranteed unique         |
| `firstName` / `lastName`                                  | string         | Mandatory                                                                                                                       |
| `email`                                                   | string \| null | Unique across **all of SkillsDB**, not just your company; changed only through its own operation                                |
| `accessLevel`                                             | object \| null | `{ slug, name, isAssignable }` — never the stored integer, which does not rank                                                  |
| `manager`                                                 | object \| null | Reference `{ id, name }` to another person                                                                                      |
| `jobTitle`                                                | object \| null | Reference to a company job title                                                                                                |
| `peopleType`                                              | object \| null | Reference to a company people type, plus `expiresAt`                                                                            |
| `orgSchema`                                               | object         | Memberships across eleven independent dimensions, each a list of references                                                     |
| Contact fields                                            | string \| null | `businessPhone`, `mobilePhone`, `homePhone`, `address`, `city`, `stateProvince`, `postalCode`, `country` (reference), `webPage` |
| `externalCompanyName`                                     | string \| null | Free-text third-party company name — never a tenant reference                                                                   |
| `nextAvailableDate`                                       | string \| null | ISO 8601 UTC                                                                                                                    |
| `isActive`                                                | boolean        | Always explicit — legacy rows with no stored value read as active                                                               |
| `inactiveAt`                                              | string \| null | Stamped on deactivation                                                                                                         |
| `createdAt` / `createdById` / `updatedAt` / `updatedById` | —              | Read-only audit fields                                                                                                          |

Email uniqueness is global: creating a person — or changing an email — with an address already registered to **another** SkillsDB company returns a 409 [conflict](/api-docs/errors/conflict) whose message never names the holder.

## Access levels

Four levels are assignable — `basic`, `manager`, `admin`, `fullaccess` — and three are legacy (`executive`, `globaladmin`, `director`): readable on people who hold them, never writable. `GET /api/v1/access-levels` publishes the full set.

<Warning>
  **The grant cap:** the API refuses (403) any attempt to grant an access level above the acting identity's own. A credential can never mint a person who exceeds its own acting person.
</Warning>

## Updates are truly partial

`PATCH /api/v1/people/{id}` is field-presence based: **absent means unchanged, explicit null means clear.** Email, access level, manager, job title, people type and active status each move through their own operation (`/email`, `/access-level`, `/manager`, `/job-title`, `/people-type`, `/activate`, `/deactivate`) — updating a phone number never requires knowing or restating anything else.

## Reporting structure

* `GET /people/{id}/direct-reports` — one level only.
* `GET /people/{id}/span-of-control` — the whole subtree, paginated, each entry carrying `level`. **The subject is included at level 0**, so a headcount over the rows is off by one if that is forgotten.
* `PATCH /people/{id}/manager` refuses a reporting loop with a 409 carrying `managerPersonId`, `managerName` and `reportDepth`; `GET /people/managers?excludeSubtreeOf={id}` prevents selecting one in the first place.

## Org schema

Eleven independent many-to-many dimensions: businessUnits, divisions, businessRegions, countries, states, cities, sites, buildings, departments, teams, shifts.

* `POST /people/{id}/org-schema` is **additive only** — it never removes a membership, and ids already held are ignored.
* `DELETE /people/{id}/org-schema` removes named memberships.
* `PUT /people/{id}/org-schema/{dimension}` **replaces** one dimension with exactly the supplied list — the shape an HRIS sync needs.

## Additional skills

A person's directly-assigned skills — distinct from the ones a [career](/api-docs/resources/career) confers, and the relationship [recording a training](/api-docs/resources/training) requires:

* `GET /api/v1/people/{personId}/skills` — the direct assignments, each with `id`, `name`, `description` and `isCertification`.
* `POST /api/v1/people/{personId}/skills` with `{ "skillIds": ["512"] }` — assigns existing catalogue skills. Already-assigned skills are skipped, never re-graded; the response reports `affected` and `skipped`.
* `DELETE /api/v1/people/{personId}/skills` with the same body — removes direct assignments (with their grades and flags), writing history first. Career-conferred skills are managed through the career, not here.

These operations carry the `skills:read` / `skills:write` scopes — the assigned object's scope governs, the same convention career assignment uses. Who may assign follows the app's own rule: a key acting as the person assigns to themselves, a manager within their span, an admin anywhere in the company.

## No delete

Deleting a person does not exist on the API, deliberately: the product's delete is an irreversible hard delete across roughly fifty tables. `POST /people/{id}/deactivate` is the lifecycle operation — it retains the person and their history.

<Note>
  **SCIM and this API are alternatives, not layers.** If your identity provider provisions people through SkillsDB's SCIM integration, do not also sync people through this API against the same tenant.
</Note>

<Warning>
  **Department-scoped admin identities:** the internal column that scopes a site admin's visibility is filled only by CSV import and SCIM, never by this API. A person created here is returned to their creator, but a department-scoped admin credential will not see them in reads until an import or SCIM sync places them in a department. Bind integration credentials to a global-admin or full-access identity to avoid this.
</Warning>
