Functional Structure

For HR administrators

The Functional Structure is the part of the job taxonomy your workspace uses: its sector, the sub-sectors you selected, and the job families under them (job descriptions have their own page). These endpoints are read-only: the Functional Structure is set up in the app, and your ERP or HR system reads it to map its own job catalog.

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/sectorsList your workspace's sectorsstructure.functional.view
GET /api/v1/sub-sectorsList the sub-sectors selected in your Functional Structurestructure.functional.view
GET /api/v1/job-familiesList the job families your workspace usesstructure.functional.view
GET /api/v1/job-families/{jobFamilyId}Get one job familystructure.functional.view

Every list takes limit (1–100, default 50) and cursor and returns { data, nextCursor }. updatedSince (ISO 8601) returns only rows changed since then, archived rows included. ?externalSystem=&externalId= (both together) finds the row linked to your own id.

What each list contains

  • Sectors: the sector your workspace operates in, plus any sector your workspace created.
  • Sub-sectors: only the sub-sectors selected in your Functional Structure.
  • Job families: only the families your workspace has added (shared catalog families and your own). Families other workspaces created are never listed, even when they sit under the same sub-sector.

Archived rows still in use are returned with archivedAt set.

Mapping across environments: slug

Shared catalog rows (sectors, sub-sectors, job families and skills from the Jadiroon catalog) return a slug, for example healthcare-services. The slug never changes and is the same in every Jadiroon environment, so map catalog rows by slug. Rows your workspace created return slug: null; map those by externalRefs.

Ids differ between Jadiroon environments and can change when sample data is re-seeded: never copy ids from one environment to another.

The sector object

FieldTypeNotes
idstringJadiroon id.
slugstring or nullStable key of a catalog sector; null for your own.
name{ ar, en }
archivedAtISO 8601 or null
externalRefsarray[{ system, externalId }].
createdAt, updatedAtISO 8601

The sub-sector object

FieldTypeNotes
idstringJadiroon id.
slugstring or nullStable key of a catalog sub-sector; null for your own.
sectorIdstringThe sector it belongs to.
name{ ar, en }
sortOrderintegerYour display order (lower first).
archivedAtISO 8601 or null
externalRefsarray[{ system, externalId }].
createdAt, updatedAtISO 8601updatedAt also moves when you select or reorder the sub-sector.

The job family object

A job family is keyed by its family id. Your workspace can use the same family more than once, under different mandates; each use is an instance.

FieldTypeNotes
idstringThe job family id.
slugstring or nullStable key of a catalog family; null for your own.
name{ ar, en }
archivedAtISO 8601 or null
instancesarrayYour workspace's instances, see below.
externalRefsarray[{ system, externalId }].
createdAt, updatedAtISO 8601updatedAt is the latest change to the family or any of its instances, including removing one of its instances.

Each instance has:

FieldTypeNotes
idstringThe instance id (job descriptions point at it as workspaceJobFamilyId).
mandatestringREGULATORY, EXECUTIVE or INTERNAL.
subSectorsarray[{ id, sortOrder }]: your selected sub-sectors the family sits under, and the family's position in each (null until reordered).
skillsobject{ technical: [...], general: [...] }, the skills chosen for this instance, each { id, slug, name }.
createdAt, updatedAtISO 8601

Webhook events

EventWhendata.object
sector.createdYour workspace creates its own sector during setupThe sector
sector.updatedYour workspace switches to a sectorThe sector
sector.deletedYour workspace stops using a catalog sector (it switched sectors){ id, externalRefs }
sub_sector.createdYour workspace creates its own sub-sectorThe sub-sector
sub_sector.updatedA sub-sector is selected or reorderedThe sub-sector
sub_sector.deletedA sub-sector is deselected{ id, externalRefs }
job_family.createdA family is created, or added to your workspace for the first timeThe job family
job_family.updatedA family's name, an instance's mandate, skills or order changes, an instance is added, duplicated or removed, a sub-sector the family sits under is selected or deselected (its subSectors change), or one of your own skills on an instance is renamed or deletedThe job family
job_family.deletedYour workspace stops using a family (its last instance was removed), or your own family was deleted{ id, externalRefs }
<resource>.bulk_changedToo many rows changed at once to list them{ resource }

Duplicating a job family instance into another mandate sends job_family.updated and, when its job descriptions and positions are copied, job_description.created and position.created for each copy (or <resource>.bulk_changed beyond 50).

*.deleted here usually means the row left your Functional Structure: a catalog sector, sub-sector or family still exists in the catalog. Only a family your workspace created is really deleted, and it then also appears in GET /api/v1/deleted?resource=job_family. A deselection never appears in /deleted: if you may have missed a *.deleted event, re-read the full list (without updatedSince) and compare it with yours; anything missing from it has left your Functional Structure.

Changes to the shared catalog itself (made by Jadiroon) send no events. Re-read these lists from time to time, for example daily with updatedSince, to pick them up.

Errors

Status and codeMeaning
403 forbiddenThe key lacks structure.functional.view.
404 not_foundYour workspace doesn't use a job family with that id.
422 validation_failedlimit, cursor or updatedSince is invalid.
422 validation_failedOnly one of externalSystem and externalId was sent.

Example

curl https://jadiroon.com/api/v1/job-families?limit=1 \
  -H "Authorization: Bearer $JADIROON_KEY"
{
  "data": [
    {
      "id": "cmvjx0h1t0001kn3o9c2a7def",
      "slug": "nursing",
      "name": { "ar": "التمريض", "en": "Nursing" },
      "archivedAt": null,
      "instances": [
        {
          "id": "cmvjx0h9k0003kn3oa1b2c3d4",
          "mandate": "EXECUTIVE",
          "subSectors": [{ "id": "cmvjx0g7r0000kn3o5e6f7a8b", "sortOrder": 0 }],
          "skills": {
            "technical": [{ "id": "cmvjx0f2a0007kn3o1a2b3c4d", "slug": "patient-assessment", "name": { "ar": "تقييم المرضى", "en": "Patient assessment" } }],
            "general": [{ "id": "cmvjx0f3b0008kn3o5e6f7a8b", "slug": "teamwork", "name": { "ar": "العمل الجماعي", "en": "Teamwork" } }]
          },
          "createdAt": "2026-10-20T09:12:44.120Z",
          "updatedAt": "2026-10-21T13:40:02.511Z"
        }
      ],
      "externalRefs": [],
      "createdAt": "2026-09-01T00:00:00.000Z",
      "updatedAt": "2026-10-21T13:40:02.511Z"
    }
  ],
  "nextCursor": "Y212angwaDF0MDAwMWtuM285YzJhN2RlZg"
}