Org units

For HR administrators

Org units are the nodes of your Organizational Structure: the entity, sectors, agencies, general administrations, administrations, sections and units, each with one parent. Use these endpoints to keep the tree in Jadiroon in sync with your ERP or HR system.

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/org-unitsList units (cursor pagination, updatedSince, external-id lookup)structure.org.view
POST /api/v1/org-unitsCreate a unitstructure.org.act
GET /api/v1/org-units/{id}Get one unitstructure.org.view
PATCH /api/v1/org-units/{id}Update a unit; omitted fields stay unchangedstructure.org.act
DELETE /api/v1/org-units/{id}Delete a unit that has no child unitsstructure.org.act
PUT /api/v1/org-units/by-external/{system}/{externalId}Create or update by your own system's idstructure.org.act
POST /api/v1/org-units/bulkUpsert up to 1,000 org units by external id, async (see Bulk upsert)structure.org.act

structure.org.act includes structure.org.view.

The org unit object

FieldTypeNotes
idstringJadiroon id. Ids differ between Jadiroon environments; link your records with externalRefs.
name{ ar, en }name.ar is required.
typestringENTITY, SECTOR, AGENCY, BRANCH, GENERAL_ADMIN, ADMIN, SECTION or UNIT.
parentIdstring or nullnull for a root unit.
function{ ar, en }The unit's function or specialization.
headName, headRolestring or nullWho heads the unit and their title.
headcountintegerCurrent headcount (0 or more).
ssoCodestring or nullSaudi Unified Classification code, read-only.
statusstringDRAFT or APPROVED.
sortOrderinteger or nullDisplay order, read-only.
externalRefsarray[{ system, externalId }] links to your systems.
createdAt, updatedAtISO 8601updatedAt also moves when the unit's data changes through the app.

Creating and updating

POST takes name, type and optionally parent, function, headName, headRole, headcount and status (new units are DRAFT unless you send status). Unknown fields are rejected.

parent names the parent unit either by Jadiroon id or by your own id:

{ "parent": { "id": "cmv…" } }
{ "parent": { "externalSystem": "oracle-hcm", "externalId": "ORG-100" } }
{ "parent": null }

null moves the unit to the root. A parent that can't be found in your workspace returns 422 unresolved_reference. Moving a unit under itself or under one of its own descendants returns 422 validation_failed with details.reason self_parent or cycle.

Upsert by external id

PUT /api/v1/org-units/by-external/oracle-hcm/ORG-200 looks up the unit linked to oracle-hcm / ORG-200:

  • Linked unit found: the body is applied like a PATCH and the response is 200.
  • No linked unit: a unit is created from the body (send at least name.ar and type) and linked to the external id, and the response is 201.

system is up to 64 characters, externalId up to 128. To find a unit by your id without changing it, call GET /api/v1/org-units?externalSystem=oracle-hcm&externalId=ORG-200 (send both parameters; one alone returns 422 validation_failed).

Deleting

DELETE only removes a unit with no child units. Otherwise it returns 409 has_children with details.childCount: move or delete the children first.

When a unit is deleted:

  • Positions placed in it stay, but become unplaced (no org unit). Their updatedAt moves, and a position.updated event is sent for each, up to 500 positions; above that, one position.bulk_changed covers the rest.
  • Workload tasks of the unit are deleted with it.
  • Its external links are removed, and the deletion appears in GET /api/v1/deleted?resource=org_unit for 180 days.

Webhook events

EventWhendata.object
org_unit.createdA unit is created (app or API)The org unit
org_unit.updatedA unit changes; data.changedFields lists the fieldsThe org unit
org_unit.deletedA unit is deleted{ id, externalRefs }
org_unit.bulk_changedThe structure was imported (file, template, URL) or replaced in the app{ resource: "org_unit" }

After org_unit.bulk_changed, re-read the list with updatedSince set to the event's occurredAt, and read GET /api/v1/deleted?resource=org_unit&since=… for removed units. A URL import that also creates positions or people sends position.bulk_changed / employee.bulk_changed as well.

Errors

Status and codeMeaning
403 forbiddenThe key lacks the permission in the table above.
404 not_foundNo unit with that id in your workspace.
409 has_childrenThe unit still has child units.
409 conflictThe external id is already linked to another unit.
422 validation_failedThe body is invalid; details explains why.
422 unresolved_referenceparent could not be found.

Example

curl -X PUT https://jadiroon.com/api/v1/org-units/by-external/oracle-hcm/ORG-200 \
  -H "Authorization: Bearer $JADIROON_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": { "ar": "إدارة الموارد البشرية", "en": "Human Resources" },
    "type": "ADMIN",
    "parent": { "externalSystem": "oracle-hcm", "externalId": "ORG-100" },
    "headcount": 12
  }'

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

{
  "id": "cmvjmf15k0008kn4q404rqwgw",
  "name": { "ar": "إدارة الموارد البشرية", "en": "Human Resources" },
  "type": "ADMIN",
  "parentId": "cmvjmeq4p0002kn4qq820gqll",
  "function": { "ar": null, "en": null },
  "headName": null,
  "headRole": null,
  "headcount": 12,
  "ssoCode": null,
  "status": "DRAFT",
  "sortOrder": null,
  "externalRefs": [{ "system": "oracle-hcm", "externalId": "ORG-200" }],
  "createdAt": "2026-10-22T14:12:52.761Z",
  "updatedAt": "2026-10-22T14:12:52.761Z"
}