Skip to main content

Partner API: Employees & Groups

Create, update, terminate and bulk-import employees, and manage the groups used to assign handbooks.

Employees

All employee endpoints are under /organizations/{orgId}/employees and require an access token.

The employee resource

{
"id": "123…",
"employeeId": "R-10482",
"firstName": "Sam",
"lastName": "Okafor",
"email": "sam.okafor@acme.com",
"jobTitle": "Account Executive",
"department": "Sales",
"teamName": "EMEA Sales",
"location": "Lisbon",
"country": "PT",
"managerEmployeeId": "R-10021",
"hireDate": "2025-03-01",
"status": "active",
"terminatedDate": null,
"groups": ["Sales", "Lisbon Office"],
"activatedAt": "2025-03-02T09:14:00.000Z",
"createdAt": "2025-03-01T08:00:00.000Z",
"updatedAt": "2026-01-12T10:30:00.000Z"
}

status is one of invited (created, not yet activated), active, or terminated.

List employees

GET /organizations/{orgId}/employees

Optional filters: status, email, group (group name), updatedSince (ISO timestamp). Without a status filter the list returns every employee, terminated ones included; pass status=active or status=invited (or both calls) to exclude them.

Get an employee

GET /organizations/{orgId}/employees/{employeeRef}

employeeRef is the AirMason id or ext:<employeeId>.

Create an employee

POST /organizations/{orgId}/employees

{
"employeeId": "R-10482",
"firstName": "Sam",
"lastName": "Okafor",
"email": "sam.okafor@acme.com",
"jobTitle": "Account Executive",
"department": "Sales",
"location": "Lisbon",
"country": "PT",
"managerEmployeeId": "R-10021",
"hireDate": "2025-03-01",
"groups": ["Sales", "Lisbon Office"],
"sendWelcomeEmail": true
}

employeeId, email, firstName and lastName are required. employeeId and email must be unique among the organization's non-terminated employees (409 conflict otherwise). Groups named in groups are created if they don't exist.

Posting the employeeId of a terminated employee does not return 409: it rehires that employee. The existing row keeps its AirMason id, its fields are overwritten with the request, and its status goes back to invited.

Set sendWelcomeEmail: false if you deliver the activation link yourself via the employee.created webhook. The link is single-use and valid for 7 days; treat activationLinkExpiresAt in the event payload as the authoritative expiry.

Update an employee

PATCH /organizations/{orgId}/employees/{employeeRef}

Any field from the create request except employeeId. Passing null or an empty string clears an optional field.

Passing groups replaces the employee's full group membership; omit it to leave groups unchanged.

A PATCH against a terminated employee returns 409 conflict (Employee is terminated); reactivate first.

Terminate an employee

POST /organizations/{orgId}/employees/{employeeRef}/terminate

{ "terminatedDate": "2026-02-28" }

terminatedDate defaults to today. Terminated employees lose portal access immediately, stop receiving reminders, are excluded from employeeCount and signature-completion percentages, and are preserved (with their signature history) for audit purposes. Terminating is idempotent: a second call does not move terminatedDate. To bring someone back, POST …/{employeeRef}/reactivate.

Bulk import

PUT /organizations/{orgId}/employees/import — multipart/form-data with a file field (CSV, up to 100 MB)

Creates or updates employees in bulk, matching on employeeId. The import runs asynchronously: the response is 202 with a job you can poll at GET /organizations/{orgId}/employees/import/{jobId}. status goes from pending to completed.

{
"jobId": "imp_01J8…",
"status": "completed",
"totalRows": 412,
"createdCount": 20,
"updatedCount": 392,
"deactivatedCount": 0,
"startedAt": "2026-01-16T09:00:00.000Z",
"completedAt": "2026-01-16T09:00:41.000Z",
"error": null,
"errorInRows": []
}

deactivatedCount is always 0: an import never terminates employees. Only one import can run per organization at a time (409 conflict otherwise).

Send complete rows. The update half of the import replaces the whole employee row, so any column absent from the CSV is cleared on existing employees (for example an employee loses teamName, location, country and managerEmployeeId after a six-column import).

Accepted CSV headers: email, employee_id, first_name, last_name, dob, team_name, job_title (also jobTitle / JobTitle), location, state, country, department, division, manager_name, manager_email, manager_id, cost_center, hire_date, employee_type, pay_type, company, leave_status, username, code, source_id, source.

The import does not validate email format. Imported employees receive no welcome email, so their employee.created event carries no activationLink (null).

Groups

Groups are how you assign handbooks to sets of employees. All under /organizations/{orgId}/groups, access token. Requests that take group names (employee groups, handbook assignments) accept at most 50 names.

Method & path

Description

GET /groups

List groups with employeeCount

POST /groups

Create
body { "name": "Lisbon Office" } — a duplicate name returns 409 conflict

PATCH /groups/{groupId}

Rename
body { "name": "Lisbon Office" }

DELETE /groups/{groupId}

Delete. The group is removed from every employee's groups (employees themselves are not affected) and the name is freed for reuse.


Partner API documentation:

Did this answer your question?