People
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
| Task | Scope | Lowest owner role |
|---|---|---|
| Read the directory | users:read | Employee |
| Read employment details | users.employment:read | Department Head |
| Read personal details | users.personal:read | Administrator |
| Read government identifiers | users.govid:read | Executive |
| Add and update people | users:write | Administrator |
| Read and change departments | departments:read, departments:write | Employee, Administrator |
| Read and change teams | teams:read, teams:write | Employee, Administrator |
| Read and assign training | training:read, training:write | Employee, Department Head |
| Read certifications | certifications:read | Employee |
| Read and issue equipment | assets:read, assets:write | Employee, Department Head |
| Read benefit enrollments | benefits:read | Administrator |
| Read compensation | compensation:read | Administrator |
| Read custom fields | custom_fields:read | Employee |
| Read goals | goals:read | Employee |
| Read onboarding and offboarding checklists | onboarding:read | Employee |
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_nameandemailare required.roledefaults toEMPLOYEE; only an Executive may create an Executive.- An email address already in use answers
409 CONFLICT. Search your own records first, or treat a409as "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_dateis a calendar day,YYYY-MM-DD.probation_period_monthsis3,6ornull.- 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_idandmanager_idmust belong to your organization.emailandis_activecannot 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
codeis generated from its name when you leave it out.head_idmust be an active person in your organization;head_id: nullleaves 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.updatedanddepartment.deletedwebhook events.
Reference: Departments, Teams.
HR records
The records attached to a person live under /users/{id}/.... Each is a paged list for one person.
| Record | Endpoint | Who the owner can read it for |
|---|---|---|
| Training | GET /users/{id}/training | Themselves; anyone for Administrators and Executives; people in their department scope for a Department Head |
| Certifications | GET /users/{id}/certifications | As for training |
| Equipment | GET /users/{id}/assets | As for training |
| Goals | GET /users/{id}/goals | As for training |
| Custom fields | GET /users/{id}/custom-fields | Their own values; anyone's for Administrators and Executives. Other roles see only values on active tabs visible to their role |
| Benefit enrollments | GET /users/{id}/benefits | Administrators and Executives |
| Compensation | GET /users/{id}/compensation | Administrators 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_datethen defaults to today on the person's calendar. - There is no endpoint that lists courses. Take
course_idfrom an existing assignment (GET /users/{id}/trainingreturns 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_dateand similar fields areYYYY-MM-DDdays. 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.
Rate Limits
The request limits per token, per organization and per address, the RateLimit and Retry-After headers, the failed-authentication lockout, and how to back off.
Leave
Read leave types, requests, balances, public holidays and locked dates, book and cancel leave, and approve or reject requests through the API, with the visibility rules that apply.