Employees

For HR administrators

Employees are the people on your roster: current employees and former employees. Use these endpoints to keep Jadiroon's employee records in sync with your ERP or HR system. Candidates have their own endpoints (see Candidates).

All endpoints sit under /api/v1 and need an API key (Authorization: Bearer jdr_live_…) created by your Workspace Admin in Settings → Integrations.

Endpoints

Method and pathWhat it doesPermission
GET /api/v1/employeesList employees, current and former (cursor pagination, updatedSince, external-id lookup)people.view
POST /api/v1/employeesCreate an employeepeople.act
GET /api/v1/employees/{id}Get one employeepeople.view
PATCH /api/v1/employees/{id}Update an employee; omitted fields stay unchangedpeople.act
DELETE /api/v1/employees/{id}Offboard an employee: the status becomes FORMER_EMPLOYEE and the record stayspeople.act
POST /api/v1/employees/{id}/archiveArchive an employeepeople.act
PUT /api/v1/employees/by-external/{system}/{externalId}Create or update by your own system's idpeople.act
POST /api/v1/employees/bulkUpsert up to 1,000 employees by external id, async (see Bulk upsert)people.act

people.act includes people.view. An id that belongs to a candidate, or to another workspace, returns 404 not_found.

The employee object

FieldTypeNotes
idstringJadiroon id. Ids differ between Jadiroon environments; link your records with externalRefs.
statusstringEMPLOYEE or FORMER_EMPLOYEE.
firstName, lastNamestring
email, phonestring or nullContact details. Employees' contact details are not masked.
nationalitystring or nullISO 3166-1 alpha-2 code, for example SA.
nationalIdstring or nullNational ID or Iqama number.
employeeNumberstring or nullYour employee number. A business field; link records with externalRefs.
genderstring or nullMALE or FEMALE.
birthDate, startDateISO 8601 or null
managerIdstring or nullThe employee's manager (another employee).
currentPositionIdstring or nullThe position the employee holds (see Positions).
managementLevelstring or nullSENIOR_MANAGEMENT or INDIVIDUAL_CONTRIBUTOR.
specialization, educationstring or null
yearsExperienceinteger or nullTotal years of experience.
govExperienceYears, civilServiceExperienceYears, entityExperienceYearsinteger or nullGovernment, civil-service and in-entity experience.
archivedAtISO 8601 or nullSet when the employee is archived.
externalRefsarray[{ system, externalId }] links to your systems.
createdAt, updatedAtISO 8601

Creating and updating

POST needs firstName and lastName; every other field is optional. status defaults to EMPLOYEE; send FORMER_EMPLOYEE to load a past employee. Unknown fields are rejected with 422 validation_failed.

manager and currentPosition name the record by Jadiroon id or by your own id, and null clears them:

{
  "manager": { "externalSystem": "oracle-hcm", "externalId": "EMP-1001" },
  "currentPosition": { "id": "cmv…" }
}

The manager must be an employee (current or former) of your workspace and the position must belong to your workspace; otherwise the response is 422 unresolved_reference. Other checks follow the app's rules:

  • 409 conflict with details.reason position_full when the position has no free seat.
  • 409 conflict with details.reason duplicate_person when another active person in the workspace has the same email, national ID / Iqama or employee number (on create).
  • 422 validation_failed with details.reason, for example self_manager (an employee can't manage themselves) or invalid_nationality.

Upsert by external id

PUT /api/v1/employees/by-external/oracle-hcm/EMP-1001 looks up the employee linked to oracle-hcm / EMP-1001:

  • Linked employee found: the body is applied like a PATCH and the response is 200.
  • No linked employee: an employee is created from the body (send at least firstName and lastName) and linked to the external id, and the response is 201.

If the linked employee was deleted in the app, the old link is dropped and the call creates a new employee with a new link. To find an employee by your id without changing them, call GET /api/v1/employees?externalSystem=oracle-hcm&externalId=EMP-1001 (send both parameters).

Offboarding, archiving and deleting

DELETE /api/v1/employees/{id} offboards the employee: status becomes FORMER_EMPLOYEE, the record and its history stay, and the response is the updated employee. Offboarding a former employee changes nothing. To bring someone back, PATCH { "status": "EMPLOYEE" }.

POST /api/v1/employees/{id}/archive sets archivedAt. Archiving an archived employee changes nothing and returns it as is.

The API never deletes a person. When a person is deleted in the app (on the People page or through the data editor), the deletion appears in GET /api/v1/deleted?resource=employee for 180 days, with the external links the person had.

Webhook events

EventWhendata.object
employee.createdAn employee is added one at a time (in the app or through the API), a candidate is hired (with application.hired; the candidate's externalRefs move to the employee, except a link another employee already holds), or a candidate is turned into an employee in the People editorThe employee
employee.updatedAn employee changes, including being assigned to a position on the org chart, or a former employee losing their position when it is deleted (changedFields: ["currentPositionId"]); data.changedFields lists the fields when knownThe employee
employee.offboardedAn employee is offboarded (through DELETE, in the app, or by setting status to FORMER_EMPLOYEE, which also sends employee.updated)The employee
employee.archivedAn employee is archivedThe employee
employee.deletedAn employee is deleted on the People page, or made a candidate in the People editor{ id, externalRefs }
employee.bulk_changedEmployees were imported (file or AI import), changed or deleted in the data editor, or many changed at once{ resource: "employee" }

Imports and the data editor don't send one event per employee: they send employee.bulk_changed, and employees deleted in the data editor appear only in GET /api/v1/deleted.

After employee.bulk_changed, re-read the list with updatedSince set to the event's occurredAt, and read GET /api/v1/deleted?resource=employee&since=… for removed employees.

Errors

Status and codeMeaning
403 forbiddenThe key lacks the permission in the table above.
404 not_foundNo employee with that id in your workspace.
409 conflictThe position is full, a duplicate person exists, or the external id is already linked to another employee.
422 validation_failedThe body is invalid; details explains why.
422 unresolved_referencemanager or currentPosition could not be found in your workspace.

Example

curl -X PUT https://jadiroon.com/api/v1/employees/by-external/oracle-hcm/EMP-1042 \
  -H "Authorization: Bearer $JADIROON_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Sara",
    "lastName": "Alharbi",
    "email": "sara.alharbi@example.sa",
    "employeeNumber": "1042",
    "startDate": "2026-01-15",
    "manager": { "externalSystem": "oracle-hcm", "externalId": "EMP-1001" },
    "currentPosition": { "externalSystem": "oracle-hcm", "externalId": "POS-310" }
  }'

The first call creates and links the employee and answers 201 Created; repeating it updates the same employee and answers 200 OK with the same body shape:

{
  "id": "cmvk2a8d10007kn5c3e9h1xyz",
  "status": "EMPLOYEE",
  "firstName": "Sara",
  "lastName": "Alharbi",
  "email": "sara.alharbi@example.sa",
  "phone": null,
  "nationality": null,
  "nationalId": null,
  "gender": null,
  "birthDate": null,
  "yearsExperience": null,
  "specialization": null,
  "education": null,
  "archivedAt": null,
  "externalRefs": [{ "system": "oracle-hcm", "externalId": "EMP-1042" }],
  "createdAt": "2026-10-22T15:02:11.204Z",
  "updatedAt": "2026-10-22T15:02:11.204Z",
  "employeeNumber": "1042",
  "startDate": "2026-01-15T00:00:00.000Z",
  "managerId": "cmvjx0h1t0003kn3o1b2c3def",
  "currentPositionId": "cmvk1q2w30004kn8x7d1f0abc",
  "managementLevel": null,
  "govExperienceYears": null,
  "civilServiceExperienceYears": null,
  "entityExperienceYears": null
}