Guides

People

Sync the employee directory, add and update people, manage departments and teams, and read HR records such as training, equipment, benefits and compensation through the API.

This guide covers the people side of the API: the directory, departments, teams and the HR records attached to each person. It explains common tasks and the rules that shape the answers. Every parameter and field is in the API Reference.

The examples use $BOOKYOURPTO_TOKEN for your token and the default base URL. If your organization uses a custom domain, read base_url from GET /organization and use that instead.

Scopes for this area

TaskScopeLowest owner role
Read the directoryusers:readEmployee
Read employment detailsusers.employment:readDepartment Head
Read personal detailsusers.personal:readAdministrator
Read government identifiersusers.govid:readExecutive
Add and update peopleusers:writeAdministrator
Read and change departmentsdepartments:read, departments:writeEmployee, Administrator
Read and change teamsteams:read, teams:writeEmployee, Administrator
Read and assign trainingtraining:read, training:writeEmployee, Department Head
Read certificationscertifications:readEmployee
Read and issue equipmentassets:read, assets:writeEmployee, Department Head
Read benefit enrollmentsbenefits:readAdministrator
Read compensationcompensation:readAdministrator
Read custom fieldscustom_fields:readEmployee
Read goalsgoals:readEmployee
Read onboarding and offboarding checklistsonboarding:readEmployee

Who appears in the directory

A token sees the people its owner sees in the app's directory:

  • Administrators and Executives see everyone.
  • If your organization's directory settings let a role see the whole directory, tokens owned by that role see everyone too.
  • Otherwise a Department Head sees the people in the departments they head or manage, and an Employee sees only themselves.

A person the owner cannot see answers 404 NOT_FOUND on GET /users/{id}, exactly like an id that does not exist.

Field tiers then decide which fields appear for the people the token can see. With only users:read you get directory fields: name, email, job title, division, work location, department, manager, role and status. Add users.employment:read for employment dates, employment type, probation, employee and payroll ids; probation dates appear only where the owner may see probation in the app. users.personal:read and users.govid:read add personal and government-id fields, and every record returned with them is written to the sensitive-data access log. See Field tiers.

Sync the directory

Walk GET /users page by page. Use the largest page size to keep the number of requests down:

curl "https://app.bookyourpto.com/api/v1/users?status=active&limit=100" \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN"
{
  "data": [
    {
      "id": "cmusr4k2h0000ex01lena0001",
      "first_name": "Lena",
      "last_name": "Fischer",
      "email": "lena.fischer@northwind.example",
      "job_title": "Operations Analyst",
      "department_id": "cmdep4k2h0000ex01ops00001",
      "manager_id": "cmusr4k2h0000ex01marc0001",
      "role": "EMPLOYEE",
      "is_active": true,
      "...": "more fields, depending on the token's scopes"
    }
  ],
  "meta": { "request_id": "...", "has_more": true, "next_cursor": "eyJpZCI6..." }
}

Then repeat with cursor set to meta.next_cursor until has_more is false (see Pagination). Filter with department_id, role or status.

status defaults to all, so a list without it includes people who have been deactivated or offboarded. Pass status=active for current staff, or keep is_active in your own records so you can mark leavers.

To keep a copy up to date without walking the whole directory, subscribe a webhook to user.created, user.updated, user.deactivated and user.reactivated (see Events) and run a full walk occasionally to reconcile.

Reference: List people, Get a person.

Add a person

POST /users adds someone the same way an administrator does in the app. The new person is emailed a link to set their password; the link is never returned by the API.

curl -X POST https://app.bookyourpto.com/api/v1/users \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7c1e9a52-3f0b-4d8e-b6a1-5e2f9c4d7a03" \
  -d '{
    "first_name": "Tomas",
    "last_name": "Silva",
    "email": "tomas.silva@northwind.example",
    "job_title": "Dispatch Coordinator",
    "department_id": "cmdep4k2h0000ex01ops00001",
    "employment_start_date": "2026-11-02",
    "probation_period_months": 3
  }'

The answer is 201 with the new person. Things to know:

  • first_name, last_name and email are required. role defaults to EMPLOYEE; only an Executive may create an Executive.
  • An email address already in use answers 409 CONFLICT. Search your own records first, or treat a 409 as "already exists".
  • When your plan has no free seat the answer is 403 FORBIDDEN. Free a seat or change the plan, then retry.
  • employment_start_date is a calendar day, YYYY-MM-DD. probation_period_months is 3, 6 or null.
  • Send an Idempotency-Key, so a retried request after a network failure cannot create the person twice.

Reference: Add a person.

Update a person

PATCH /users/{id} changes only the fields you send:

curl -X PATCH https://app.bookyourpto.com/api/v1/users/cmusr4k2h0000ex01lena0001 \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "job_title": "Senior Operations Analyst", "manager_id": "cmusr4k2h0000ex01marc0001" }'

The rules are the app's:

  • Only an Executive edits an Executive or promotes someone to Executive, and nobody changes their own role.
  • Employment fields (employment_type, employee_id, payroll_id, employment dates, probation) are for Administrators and Executives.
  • department_id and manager_id must belong to your organization.
  • email and is_active cannot be changed here. People leave through offboarding in the app, which also revokes their API tokens and turns off webhook endpoints they own; there is no deactivate endpoint.

Reference: Update a person.

Departments and teams

# Active departments (add include_inactive=true for all of them)
curl "https://app.bookyourpto.com/api/v1/departments" \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN"

# Create a department with a head
curl -X POST https://app.bookyourpto.com/api/v1/departments \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Customer Success", "head_id": "cmusr4k2h0000ex01marc0001" }'
  • A department's code is generated from its name when you leave it out. head_id must be an active person in your organization; head_id: null leaves the department without a head.
  • Team names are unique within the organization; a duplicate answers 409 CONFLICT.
  • GET /teams/{id} lists the team's members that the owner can see in the directory. Membership itself is managed in the app; PATCH /teams/{id} changes the team's name, description, department and status only.
  • Department changes raise department.created, department.updated and department.deleted webhook events.

Reference: Departments, Teams.

HR records

The records attached to a person live under /users/{id}/.... Each is a paged list for one person.

RecordEndpointWho the owner can read it for
TrainingGET /users/{id}/trainingThemselves; anyone for Administrators and Executives; people in their department scope for a Department Head
CertificationsGET /users/{id}/certificationsAs for training
EquipmentGET /users/{id}/assetsAs for training
GoalsGET /users/{id}/goalsAs for training
Custom fieldsGET /users/{id}/custom-fieldsTheir own values; anyone's for Administrators and Executives. Other roles see only values on active tabs visible to their role
Benefit enrollmentsGET /users/{id}/benefitsAdministrators and Executives
CompensationGET /users/{id}/compensationAdministrators and Executives. Every record returned is written to the sensitive-data access log

A person the owner may not read records for answers 404 NOT_FOUND.

Assign training

curl -X POST https://app.bookyourpto.com/api/v1/users/cmusr4k2h0000ex01lena0001/training \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "course_id": "cmcrs0000000000000000004", "due_date": "2026-12-15" }'
  • Needs training:write, and an owner who is an Administrator or Executive, or the person's Department Head. Nobody assigns training to themselves.
  • A course that is already assigned to the person answers 409 CONFLICT.
  • To record training that has already been completed, send "status": "COMPLETED". completed_date then defaults to today on the person's calendar.
  • There is no endpoint that lists courses. Take course_id from an existing assignment (GET /users/{id}/training returns it) or from the course in the app.

Issue equipment

curl -X POST https://app.bookyourpto.com/api/v1/users/cmusr4k2h0000ex01lena0001/assets \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "description": "Laptop, 14-inch", "serial_number": "C02FK3ZPMD6T", "category_name": "Laptops", "date_assigned": "2026-11-02" }'

Give category_id, or category_name to use a category by name and create it if it does not exist. Use PATCH /users/{id}/assets/{asset_id} to record a return (date_returned, "status": "AVAILABLE") or a loss. The same people who may assign training may issue equipment, and nobody issues equipment to themselves.

Reference: People records.

Onboarding and offboarding checklists

GET /onboarding lists checklists with their tasks. Filter with user_id, type (ONBOARDING or OFFBOARDING) and status.

  • Administrators and Executives see every checklist.
  • A Department Head sees their own, those of people in their department scope, and those with a task assigned to them.
  • Anyone else sees their own and those with a task assigned to them.
  • On someone else's checklist, only the tasks assigned to the token's owner are listed, unless they administer it.

Reference: Onboarding.

Gotchas

  • Visibility is the owner's, not the token's. Two tokens with the same scopes can return different people. If a sync looks incomplete, check who owns the token.
  • Calendar days are not timestamps. employment_start_date, due_date and similar fields are YYYY-MM-DD days. Do not convert them through your local timezone. See Dates and times.
  • Every page of a people list is recorded as an export in the organization's audit log, with the record count. Do not walk the directory more often than you need to; webhooks tell you what changed.
  • Removing someone is an app action. Offboarding in the app deactivates the account and revokes the person's API tokens; the API cannot deactivate anyone.