Deel HRIS API

Unified HR Information System API covering all workers (IC, EOR, employee). Surfaces include people directory, working locations, time off (policies, requests, entitlements, events, work schedules), positions, employment information, departments, manager hierarchy, custom HR fields, and SCIM 2.0 user provisioning for Okta, Azure AD, and other IdPs.

Deel HRIS API is one of 8 APIs that Deel publishes on the APIs.io network, described by a machine-readable OpenAPI specification.

This API exposes 3 machine-runnable capabilities that can be deployed as REST, MCP, or Agent Skill surfaces via Naftiko and 1 JSON Schema definition.

Tagged areas include HRIS, HR, People, Time Off, and SCIM. The published artifact set on APIs.io includes API documentation, an OpenAPI specification, 3 Naftiko capability specs, and 1 JSON Schema.

OpenAPI Specification

deel-hris-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Deel HRIS API
  description: |
    Unified HR Information System API across all worker types (IC, EOR, employee).
    Surfaces include people directory, working locations, time off (policies, requests,
    entitlements, events, work schedules), positions, employment information, departments,
    manager hierarchy, custom HR fields, and SCIM 2.0 user provisioning for Okta, Azure AD,
    and other identity providers.
  version: '2026-05-25'
  contact:
    name: Deel Developer Support
    url: https://developer.deel.com/api/hris/introduction

servers:
  - url: https://api.letsdeel.com/rest/v2
    description: Production
  - url: https://api-sandbox.demo.deel.com/rest/v2
    description: Sandbox

security:
  - BearerAuth: []
  - ScimBearerAuth: []

tags:
  - name: People
    description: Unified directory across IC, EOR, and direct employees
  - name: Time Off
    description: Time-off policies, requests, entitlements, events, work schedules
  - name: Positions
    description: Position/role definitions
  - name: SCIM
    description: SCIM 2.0 user provisioning per RFC 7643/7644

paths:
  /people:
    get:
      operationId: getPeople
      summary: List Of People
      description: Returns a paginated unified directory across all worker types.
      tags: [People]
      parameters:
        - { name: after_cursor, in: query, schema: { type: string } }
        - { name: limit, in: query, schema: { type: integer, default: 20, maximum: 100 } }
        - { name: hiring_type, in: query, schema: { type: string, enum: [contractor, eor, direct_employee, global_payroll] } }
        - { name: employment_status, in: query, schema: { type: string, enum: [active, terminated, onboarding, offboarded] } }
        - { name: country, in: query, schema: { type: string } }
      responses:
        '200':
          description: People list
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { type: array, items: { $ref: '#/components/schemas/Person' } }
    post:
      operationId: createPersonWithoutContract
      summary: Create A Person Without A Contract
      description: Create a person record (for example a future hire) before any contract exists.
      tags: [People]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/PersonCreate' }
      responses:
        '201':
          description: Person created
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Person' }

  /people/{person_id}:
    get:
      operationId: getPersonById
      summary: Retrieve A Single Person
      tags: [People]
      parameters:
        - { name: person_id, in: path, required: true, schema: { type: string } }
      responses:
        '200':
          description: Person
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Person' }

  /people/{person_id}/working-location:
    patch:
      operationId: updateWorkingLocation
      summary: Update Working Location
      tags: [People]
      parameters:
        - { name: person_id, in: path, required: true, schema: { type: string } }
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/WorkingLocationUpdate' }
      responses:
        '200': { description: Location updated }

  /time-off/policies:
    get:
      operationId: getTimeOffPolicies
      summary: List Policies
      tags: [Time Off]
      responses:
        '200':
          description: Policies
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { type: array, items: { $ref: '#/components/schemas/TimeOffPolicy' } }

  /time-off/requests:
    get:
      operationId: getTimeOffRequests
      summary: List Time-Off Requests
      tags: [Time Off]
      parameters:
        - { name: person_id, in: query, schema: { type: string } }
        - { name: status, in: query, schema: { type: string, enum: [pending, approved, declined, cancelled] } }
        - { name: from, in: query, schema: { type: string, format: date } }
        - { name: to, in: query, schema: { type: string, format: date } }
      responses:
        '200':
          description: Time-off requests
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { type: array, items: { $ref: '#/components/schemas/TimeOffRequest' } }
    post:
      operationId: createTimeOffRequest
      summary: Create Time-Off Request
      tags: [Time Off]
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/TimeOffRequestCreate' }
      responses:
        '201':
          description: Time-off request created
          content:
            application/json:
              schema: { $ref: '#/components/schemas/TimeOffRequest' }

  /time-off/requests/{request_id}/review:
    post:
      operationId: reviewTimeOffRequest
      summary: Approve Or Reject Time-Off Requests
      tags: [Time Off]
      parameters:
        - { name: request_id, in: path, required: true, schema: { type: string } }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [decision]
              properties:
                decision: { type: string, enum: [approve, decline] }
                notes: { type: string }
      responses:
        '200': { description: Request reviewed }

  /time-off/requests/{request_id}:
    delete:
      operationId: cancelTimeOffRequest
      summary: Cancel Time-Off Request
      tags: [Time Off]
      parameters:
        - { name: request_id, in: path, required: true, schema: { type: string } }
      responses:
        '204': { description: Request cancelled }

  /time-off/entitlements/{person_id}:
    get:
      operationId: getEntitlements
      summary: Get Profile Entitlements
      tags: [Time Off]
      parameters:
        - { name: person_id, in: path, required: true, schema: { type: string } }
      responses:
        '200':
          description: Entitlements
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: { type: array, items: { $ref: '#/components/schemas/Entitlement' } }

  /time-off/work-schedule/{person_id}:
    get:
      operationId: getWorkSchedule
      summary: Get Work Schedule And Holidays
      tags: [Time Off]
      parameters:
        - { name: person_id, in: path, required: true, schema: { type: string } }
      responses:
        '200':
          description: Work schedule
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      working_days: { type: array, items: { type: string } }
                      hours_per_week: { type: number }
                      holidays: { type: array, items: { type: object, properties: { date: { type: string, format: date }, name: { type: string } } } }

  /scim/v2/Users:
    get:
      operationId: scimListUsers
      summary: SCIM List Users
      description: SCIM 2.0 user listing endpoint for IdP integration (Okta, Azure AD).
      tags: [SCIM]
      security:
        - ScimBearerAuth: []
      parameters:
        - { name: filter, in: query, schema: { type: string } }
        - { name: startIndex, in: query, schema: { type: integer, default: 1 } }
        - { name: count, in: query, schema: { type: integer, default: 100 } }
      responses:
        '200':
          description: SCIM ListResponse
          content:
            application/scim+json:
              schema: { $ref: '#/components/schemas/ScimListResponse' }
    post:
      operationId: scimCreateUser
      summary: SCIM Create User
      tags: [SCIM]
      security:
        - ScimBearerAuth: []
      requestBody:
        required: true
        content:
          application/scim+json:
            schema: { $ref: '#/components/schemas/ScimUser' }
      responses:
        '201':
          description: SCIM user created
          content:
            application/scim+json:
              schema: { $ref: '#/components/schemas/ScimUser' }

  /scim/v2/Users/{user_id}:
    get:
      operationId: scimGetUser
      summary: SCIM Get User
      tags: [SCIM]
      security:
        - ScimBearerAuth: []
      parameters:
        - { name: user_id, in: path, required: true, schema: { type: string } }
      responses:
        '200':
          description: SCIM user
          content:
            application/scim+json:
              schema: { $ref: '#/components/schemas/ScimUser' }
    patch:
      operationId: scimPatchUser
      summary: SCIM Patch User
      tags: [SCIM]
      security:
        - ScimBearerAuth: []
      parameters:
        - { name: user_id, in: path, required: true, schema: { type: string } }
      requestBody:
        required: true
        content:
          application/scim+json:
            schema:
              type: object
              properties:
                schemas: { type: array, items: { type: string } }
                Operations:
                  type: array
                  items:
                    type: object
                    properties:
                      op: { type: string, enum: [add, replace, remove] }
                      path: { type: string }
                      value: {}
      responses:
        '200': { description: Patched, content: { application/scim+json: { schema: { $ref: '#/components/schemas/ScimUser' } } } }
    delete:
      operationId: scimDeleteUser
      summary: SCIM Deactivate User
      tags: [SCIM]
      security:
        - ScimBearerAuth: []
      parameters:
        - { name: user_id, in: path, required: true, schema: { type: string } }
      responses:
        '204': { description: User deactivated }

components:
  securitySchemes:
    BearerAuth: { type: http, scheme: bearer, bearerFormat: opaque }
    ScimBearerAuth:
      type: http
      scheme: bearer
      bearerFormat: scim_token
      description: Dedicated SCIM bearer token configured per IdP in the Developer Center.
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      schema: { type: string, format: uuid }
  schemas:
    Person:
      type: object
      properties:
        id: { type: string }
        first_name: { type: string }
        last_name: { type: string }
        preferred_name: { type: string }
        email: { type: string, format: email }
        work_email: { type: string, format: email }
        hiring_type: { type: string, enum: [contractor, eor, direct_employee, global_payroll] }
        employment_status: { type: string, enum: [active, terminated, onboarding, offboarded] }
        country: { type: string }
        working_location: { $ref: '#/components/schemas/WorkingLocation' }
        department: { type: object, properties: { id: { type: string }, name: { type: string } } }
        manager: { type: object, properties: { id: { type: string }, name: { type: string } } }
        job_title: { type: string }
        start_date: { type: string, format: date }
        external_id: { type: string }
    PersonCreate:
      type: object
      required: [first_name, last_name, email]
      properties:
        first_name: { type: string }
        last_name: { type: string }
        email: { type: string, format: email }
        preferred_name: { type: string }
        country: { type: string }
        job_title: { type: string }
        external_id: { type: string }
    WorkingLocation:
      type: object
      properties:
        country: { type: string }
        state: { type: string }
        city: { type: string }
        address: { type: string }
        timezone: { type: string }
    WorkingLocationUpdate:
      type: object
      required: [country]
      properties:
        country: { type: string }
        state: { type: string }
        city: { type: string }
        address: { type: string }
        timezone: { type: string }
        effective_date: { type: string, format: date }
    TimeOffPolicy:
      type: object
      properties:
        id: { type: string }
        name: { type: string }
        type: { type: string, enum: [vacation, sick, parental, bereavement, jury_duty, study, unpaid, other] }
        accrual_rate: { type: number }
        accrual_unit: { type: string, enum: [days, hours] }
        carry_over_days: { type: integer }
        country: { type: string }
    TimeOffRequest:
      type: object
      properties:
        id: { type: string }
        person_id: { type: string }
        policy_id: { type: string }
        type: { type: string }
        start_date: { type: string, format: date }
        end_date: { type: string, format: date }
        days: { type: number }
        status: { type: string, enum: [pending, approved, declined, cancelled] }
        reason: { type: string }
        created_at: { type: string, format: date-time }
    TimeOffRequestCreate:
      type: object
      required: [person_id, policy_id, start_date, end_date]
      properties:
        person_id: { type: string }
        policy_id: { type: string }
        start_date: { type: string, format: date }
        end_date: { type: string, format: date }
        reason: { type: string }
        half_day: { type: boolean }
    Entitlement:
      type: object
      properties:
        policy_id: { type: string }
        policy_name: { type: string }
        accrued: { type: number }
        used: { type: number }
        pending: { type: number }
        available: { type: number }
        unit: { type: string, enum: [days, hours] }
        as_of: { type: string, format: date }
    ScimListResponse:
      type: object
      properties:
        schemas: { type: array, items: { type: string }, example: ["urn:ietf:params:scim:api:messages:2.0:ListResponse"] }
        totalResults: { type: integer }
        startIndex: { type: integer }
        itemsPerPage: { type: integer }
        Resources: { type: array, items: { $ref: '#/components/schemas/ScimUser' } }
    ScimUser:
      type: object
      properties:
        schemas: { type: array, items: { type: string }, example: ["urn:ietf:params:scim:schemas:core:2.0:User"] }
        id: { type: string }
        userName: { type: string }
        active: { type: boolean }
        name:
          type: object
          properties:
            givenName: { type: string }
            familyName: { type: string }
        emails:
          type: array
          items:
            type: object
            properties:
              value: { type: string, format: email }
              type: { type: string }
              primary: { type: boolean }
        externalId: { type: string }
        meta:
          type: object
          properties:
            resourceType: { type: string }
            created: { type: string, format: date-time }
            lastModified: { type: string, format: date-time }
            location: { type: string, format: uri }