Bulk Operations

Several endpoints support bulk operations alongside their single-record counterparts. The request shape differs depending on what the operation does — see the three patterns below.

This section tracks which resources have a documented bulk endpoint. Add a row here whenever a new one is confirmed.

1. Bulk create (POST)

A POST to {resource}_bulk takes a JSON array of the same object type its single-create counterpart takes, and creates each item independently. If one item fails, the other items in the same request are still created. The exception is a missing required field: if any item is missing one, the whole request fails and no items are created. See Bulk Create Employees for a fully worked example, including the request and response shapes.

ResourceSingle-create endpointBulk endpoint
EmployeesPOST /wep/companies/{CLIENT_ID}/employeesPOST /wep/companies/{CLIENT_ID}/employees_bulk
DivisionsPOST /wep/companies/{companyId}/divisionsPOST /wep/companies/{companyId}/divisions_bulk
Earning CodePOST /wep/companies/{companyId}/earningcodesPOST /wep/companies/{companyId}/earningcodes_bulk
Cost CodePOST /wep/companies/{companyId}/jobcosting/{jobCostingId}/codesPOST /wep/companies/{companyId}/jobcosting/{jobCostingId}/codes_bulk
Work LocationPOST /wep/companies/{companyId}/worklocationsPOST /wep/companies/{companyId}/worklocations_bulk

Notes

  • The response shape (each array entry as { data: <object> } on success or { errorCode, errorMessage } on failure, matched to the request by array index).

Creates multiple employee records under a company in a single request. Use this instead of Create an Employee when you're importing several employees at once.

Endpoint

POST https://api.worklio.com/wep/companies/{CLIENT_ID}/employees_bulk

Requires a bearer access token (see How to Get API Access). CLIENT_ID is the company identifier returned as id when you create the company.

Request body

The request body is a single JSON array of employee objects. Each object takes the same fields as Create an Employee:

FieldTypeRequiredDescription
firstNamestringRequiredEmployee's first name
lastNamestringRequiredEmployee's last name
ssnstringNot required by employee_bulk but will fail with SSN missingSocial Security Number, with or without dashes
birthDatestring (ISO date)RequiredDate of birth
employeeTypeintegerRequired0 = Employee, 1 = Contractor

Example request

require("dotenv").config();

const TOKEN = process.env.API_KEY;
const CLIENT_ID = process.env.CLIENT_ID;
const url = `https://api.worklio.com/wep/companies/${CLIENT_ID}/employees_bulk`;

const payload = [
  {
    firstName: 'Michael',
    lastName: 'Brown',
    employeeType: 0,
    ssn: '111-11-4084',
    birthDate: '1990-07-14T00:00:00.000Z',
  },
  {
    firstName: 'Sarah',
    lastName: 'Nguyen',
    employeeType: 0,
    ssn: '122-22-2281',
    birthDate: '1988-02-23T00:00:00.000Z',
  }
];

async function createEmployeesBulk() {
  const response = await fetch(url, {
    method: "POST",
    headers: {
      accept: "application/json",
      "api-version": "2.0",
      authorization: `Bearer ${TOKEN}`,
      "content-type": "application/json",
      "x-api-version": "2.0"
    },
    body: JSON.stringify(payload)
  });

  console.log(response.status);
  console.log(await response.text());
}

createEmployeesBulk();

Example response

The response is an array in the same order as the request. Each entry is either { data: <employee> } on success, or { errorCode, errorMessage } on failure for that employee.

[
  {
    "errorCode": "UnknownError",
    "errorMessage": "Employee with the same SSN/FEIN already has an active employment with the current client."
  },
  {
    "data": {
      "id": 4301,
      "firstName": "Sarah",
      "lastName": "Nguyen",
      "employeeType": 0,
      "ssnMasked": "***-**-2281",
      "ssn": "122-22-2281",
      "birthDate": "1988-02-23",
      "payAllocation": [
        {
          "id": 0,
          "order": 1,
          "payMethod": 1,
          "allocatedBy": 2,
          "amount": 100
        }
      ],
      "isAdmin": false,
      "employeeUI_ID": 7,
      "country": "US",
      "citizenshipCountry": "US",
      "citizenship": 1,
      "w2Info": {
        "electronicOnly": false,
        "firstName": "Sarah",
        "lastName": "Nguyen"
      },
      "hrKeyDates": {
        "liabilityStart": "2026-09-08",
        "originalHire": "2026-09-08"
      }
    }
  }
]

In this example, Michael Brown's entry failed because his ssn already belongs to an active employee for this company, while Sarah Nguyen's employee record was created successfully. Check each entry's shape (errorCode/errorMessage vs. data) to tell which employees in the batch succeeded.

Notes

  • This is not all-or-nothing: employees are created independently, so a failure on one doesn't prevent the others in the same request from being created.
  • Match response entries to request entries by array position (index) to know which employee an error applies to.
🚧

Bulk create has two kinds of failure

A missing required field fails the whole request. For example, if one employee has no name, no employees are created (example response below).

A missing ssn or a duplicate ssn fails only that employee. The response contains an errorCode and errorMessage for that employee, and the other employees are created (example response above).

ssn is required to create an employee, but employees_bulk checks it per employee, not before the request is accepted. This differs from Create an Employee, where ssn is required up front.

{
  status: 3,
  code: 'DataValidationError',
  errorCode: '',
  message: 'One or more validation errors occurred.\r\n' +
    '[0].FirstName: [requiredError:The field is required.]',
  stackTrace: '',
  pagination: {
    pageNo: 0,
    pageSize: 0,
    totalRecords: 0,
    totalPages: 0,
    dataToken: ''
  },
  validationErrors: { '[0].firstName': [ [Array] ] }
}

2. Bulk update (PATCH)

A PATCH to the same {resource}_bulk URL used for bulk create takes a JSON object instead of an array. Each key is the id of an existing record, and each value is a partial object containing only the fields to change — fields you omit are left unchanged. Records in the batch are processed independently, same as bulk create. See Bulk Update Work Locations for a fully worked example.

ResourceBulk update endpoint
DivisionsPATCH /wep/companies/{companyId}/divisions_bulk
Cost CodePATCH /wep/companies/{companyId}/jobcosting/{jobCostingId}/codes_bulk
Work LocationPATCH /wep/companies/{companyId}/worklocations_bulk

Example request

require("dotenv").config();

const TOKEN = process.env.API_KEY;
const CLIENT_ID = process.env.CLIENT_ID;
const URL = process.env.URL
const url = `${URL}/wep/companies/${CLIENT_ID}/divisions_bulk`;

const payload = {
  "138":{
    name: "Support Divisions"
  },
  "1119":{ //the id doesnt exist
    name: "This will result in an error"
  }
};

async function bulkPatchDivisions() {
  console.log(url)
  const response = await fetch(url, {
    method: "PATCH",
    headers: {
      accept: "application/json",
      "api-version": "2.0",
      authorization: `Bearer ${TOKEN}`,
      "content-type": "application/json",
      "x-api-version": "2.0"
    },
    body: JSON.stringify(payload)
  });

  console.log(response.status);
  const raw = await response.text();
  console.log(JSON.stringify(JSON.parse(raw), null, 2));
}

bulkPatchDivisions();

Example response

The response is an array in the same order as the request. Each entry is either { data: <employee> } on success, or { errorCode, errorMessage } on failure for that id.

[
  {
    "data": {
      "divisionAddress": {
        "id": 6142,
        "addressLine1": "233 S Wacker Drive",
        "addressLine2": "Suite 8400",
        "addressCity": "Chicago",
        "addressState": "IL",
        "addressZIP": "60606",
        "addressCountry": "US"
      },
      "id": 138,
      "name": "Support Divisions",
      "tradeName": "",
      "status": 1
    }
  },
  {
    "errorCode": "UnknownError",
    "errorMessage": "Division #1119 does not exist."
  }
]

3. Bulk assign by ID list

POST https://api.worklio.com/wep/companies/{CLIENT_ID}/policies/{POLICY_ID}/employees

Example request

require("dotenv").config();

const TOKEN = process.env.API_KEY;
const CLIENT_ID = process.env.CLIENT_ID;
const POLICY_ID = process.env.POLICY_ID;
const url = `https://api.worklio.com/wep/companies/${CLIENT_ID}/policies/${POLICY_ID}/employees`;

const payload = {
  employeeIds: [4277, 4278]
};

async function assignEmployeesToPolicy() {
  const response = await fetch(url, {
    method: "POST",
    headers: {
      accept: "application/json",
      "api-version": "2.0",
      authorization: `Bearer ${TOKEN}`,
      "content-type": "application/json",
      "x-api-version": "2.0"
    },
    body: JSON.stringify(payload)
  });

  console.log(response.status);
}

assignEmployeesToPolicy();

Example response

204 No Content — no response body on success.

Notes

  • Unlike §1 and §2, this endpoint gives no per-item success/failure detail — a 204 tells you the call as a whole succeeded, but not whether every ID in employeeIds was valid or actually got assigned. If you need to confirm an individual assignment, look it up separately after the call.
  • Response and error behavior for an invalid or already-assigned employee ID hasn't been captured yet.




Did this page help you?