Skip to main content
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.

Attributes

Email uniqueness is global: creating a person — or changing an email — with an address already registered to another SkillsDB company returns a 409 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.
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.

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 confers, and the relationship recording a 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.
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.
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.