---
title: "Bulk Create Pay Items"
method: POST
path: "/v1/pay-items/bulk"
tags: ["Pay Items"]
---

# Bulk Create Pay Items

`POST /v1/pay-items/bulk`

## Request

- Base URL: `https://gateway.remote.com`
- URL: `https://gateway.remote.com/v1/pay-items/bulk`
- Auth: one of:
  - OAuth 2
    - Authorization code: `/auth/oauth2/authorize`
    - Token URL: `/auth/oauth2/token` scopes: `https://gateway.remote.com/company.manage`
  - OAuth 2
    - Authorization code: `/auth/oauth2/authorize`
    - Token URL: `/auth/oauth2/token` scopes: `pay_item:write`
  - OAuth 2
    - Authorization code: `/auth/oauth2/authorize`
    - Token URL: `/auth/oauth2/token` scopes: `all:write`
  - OAuth 2
    - Client credentials
    - Token URL: `/auth/oauth2/token` scopes: `pay_item:write`
  - OAuth 2
    - Client credentials
    - Token URL: `/auth/oauth2/token` scopes: `all:write`
  - HTTP bearer

Bulk creates pay items for employments. Supports up to 500 items per request.
Each item must supply exactly one of `code` or `external_import_code` to identify the pay element.
Integration-specific fields (shift code, currency, pay amount, etc.) go in the `provider_data` object.
Pay codes that use a pay item custom configuration, such as a company car, describe it under `custom_configuration` in GET /v1/companies/:company_id/legal-entities/:legal_entity_id/pay-codes. Send its values in the pay item's `custom_configuration`, with the same `key`.
Only Global Payroll employments are supported. Non-GP employments are returned as `employment_not_global_payroll`.
An item whose `partner_external_id` the integration already holds on a live pay item of the company updates that pay item under the same rules as `PATCH`, and any other item creates a new pay item.
When that pay item belongs to another employment or pay code, the item fails with `partner_external_id_held_by_other_pay_item` instead.
When pay items generated from a recurring pay item hold the value, the item fails with `partner_external_id_held_by_generated_pay_item`, naming them. Clear its `partner_external_id` with `PATCH` to use the value again; when it has more than one live version, contact Remote support.
When more than one live pay item holds the value, the item fails with `partner_external_id_ambiguous`, unless it already fails for its employment or its pay code, or because the value is held by a recurring pay item or a payment generated from one.
Within one request each `partner_external_id` may appear once, and `null` or an empty string fails the item.
An item without `partner_external_id` always creates a new pay item, so sending it again creates a duplicate.
See [Your own IDs on Remote records](https://developer.remote.com/docs/your-own-ids-on-remote-records).

## Authentication

This endpoint accepts any one of the following token types:

- **Company-scoped access token** (`OAuth2AuthorizationCode`) — obtained by a company manager through the Authorization Code flow or the Refresh Token flow. See [Authentication for partners](https://developer.remote.com/docs/authentication-for-partners).
- **Company-scoped access token (assertion)** (`OAuth2CompanyManagerAssertion`) — obtained through the `urn:ietf:params:oauth:grant-type:jwt-bearer` grant for a company manager. See [OAuth Assertion](https://developer.remote.com/docs/authorization-method-oauth-assertion).
- **Customer API token** (`CustomerAPIToken`) — generated by the customer on their Integration Settings page, with the scopes they choose there. See [Authorization for customers](https://developer.remote.com/docs/authorization-for-customers).

## Scopes

Any one of the scopes in a token type's row is enough. `all:write` works too.

| Token type | Category | Read only Scope | Write only Scope (read access implicit) |
|---|---|---|---|
| Company-scoped access token | Manage payroll runs (`payroll`) | - | Manage pay items (`pay_item:write`) |
| Company-scoped access token (assertion) | Manage payroll runs (`payroll`) | - | Manage pay items (`pay_item:write`) |
| Customer API token | Manage payroll runs (`payroll`) | - | Manage pay items (`pay_item:write`) |

## Request body

- BulkCreatePayItemsParams
  - `pay_items` PayItemParams[], required
    - `amount` integer, required: Value of the pay item. Its unit depends on the `type` of the pay code (see GET /v1/companies/:company_id/legal-entities/:legal_entity_id/pay-codes): `amount` in cents, `percentage` in basis points, `unit` as a raw count, `hours` as a whole number of hours, `duration` in seconds. Must not be zero. **Negative values are supported.** A positive `amount` adds value; a negative `amount` takes value away. Send a negative `amount` to submit a deduction, or to correct an earlier submission downwards. This applies to every pay code, whatever its unit — including hours-based codes such as `working_hours`. For example: - `-5000` on an `amount` code (cents) deducts 50.00 from pay. - `-3` on an hours-based code such as `working_hours` removes 3 hours reported in error.
    - `code` string: Pay item type code. Mutually exclusive with `external_import_code` — provide exactly one.
    - `currency` string, nullable: Currency code in [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) format.
    - `custom_configuration` PayItemCustomConfiguration, nullable: The pay item custom configuration values for pay codes that use one, such as the employee's company car. The pay code's `custom_configuration` (GET …/pay-codes) gives the `key` and the JSON Schema of the `values`. On PATCH, `values` are merged onto the stored ones: nested objects merge, and `null` removes a field at any level. Send `null` for the whole `custom_configuration` to remove the stored values.
      - `key` string, required: The pay code's `custom_configuration.key`
      - `values` object, required: Values matching the pay code's `custom_configuration.schema`
    - `effective_date` string, date, required: Date the pay item is applied on (YYYY-MM-DD). For an original submission this is the day worked; for a correction it is the day the correction is submitted, so the pay item lands in the right payroll run. The day being corrected goes in `provider_data.correction_effective_date`. On a leave-of-absence pay item this is the first day of the leave period, whose last day goes in `end_date`.
    - `employment_id` string, uuid, required: Employment UUID. Only Global Payroll employments are supported.
    - `end_date` string, date, nullable: Last day of a leave period, inclusive (YYYY-MM-DD). Set this only on leave-of-absence pay codes — parental, sick, maternity, unpaid leave and similar — where the pay item covers a period rather than a single day, and `effective_date` is the first day of that period. Leave it off ordinary time & attendance items such as worked hours, overtime or allowances, which apply to a single day.
    - `external_import_code` string: Partner-defined pay element identifier, as configured on the legal entity pay element. Mutually exclusive with `code` — provide exactly one.
    - `partner_external_id` string, nullable: A reference code for the pay item record in the calling integration's own system. Private to that integration — no other integration can read or overwrite it. When the integration already holds this value on a live pay item, the item updates that pay item; otherwise it creates a new pay item holding the value. `null` or an empty string fails the item. An item without the field always creates a new pay item, so sending it again creates a duplicate. At most 64 characters, counting any surrounding whitespace sent; that whitespace is then trimmed off. A value can be held by one live pay item at a time, per integration and company; editing a pay item keeps its value on the new version. See [Your own IDs on Remote records](https://developer.remote.com/docs/your-own-ids-on-remote-records).
    - `provider_data` PayItemProviderDataParams
      - `adjustment_effective_date` string, date: **Deprecated — renamed to `correction_effective_date`**, which this value backfills. `correction_effective_date` wins when both are sent.
      - `correction_effective_date` string, date: Set this only on a correction: the original working day being corrected (YYYY-MM-DD). Its presence is what marks the pay item as a correction rather than an original submission.
      - `hourly_rate` integer: Hourly rate in cents
      - `hourly_rate_currency_code` string, nullable: Currency code in [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) format.
      - `is_deduction` boolean: **Deprecated — accepted and ignored.** Express a deduction as a negative `amount`.
      - `pay_rate` number: Overtime rate multiplier (e.g. 1.5)
      - `payout_amount` integer: **Deprecated — accepted and ignored.** The payout value belongs in the pay item's own `amount`.
      - `payout_currency_code` string: **Deprecated — accepted and ignored.** The payout currency belongs in the pay item's own `currency`.
      - `shift_code` string: Shift identifier from partner system
      - `work_day_duration` integer: Expected work day duration in seconds

## Response `200`

Success

- BulkCreatePayItemsResponse
  - `data` object, required
    - `failures` PayItemBulkCreateFailures[], required
      - `error` union: Failure reason. Includes `employment_not_global_payroll` when the provided employment is not Global Payroll, `pay_item_code_not_allowed` / `pay_item_external_import_code_not_allowed` when the given identifier does not resolve to an allowed pay element, and `effective_date_after_termination_date` (as a `code`/`message` pair) when a `time_attendance` pay item's `effective_date` falls after the employment's termination date. It also includes `custom_configuration_required`, `custom_configuration_not_used` and `invalid_custom_configuration` (as `code`/`message`/`param`) when the pay item's `custom_configuration` doesn't match the pay code's. An item with a `partner_external_id` can also fail with `partner_external_id_not_available`, `partner_external_id_blank`, `partner_external_id_repeated_in_request`, `partner_external_id_ambiguous`, `partner_external_id_held_by_other_pay_item` or `partner_external_id_held_by_generated_pay_item` (as `code`/`message`), with the errors `PATCH` returns when the matched pay item cannot be updated, or with `errors.partner_external_id` when the value is refused.
        - string
        - PayItemBulkCreateFailureDetail
          - `code` string, required: Stable, machine-parseable failure reason.
          - `message` string, required: Human-readable detail for the failure reason.
          - `param` string: Slash-separated path of the field at fault, e.g. `custom_configuration/values/make`.
        - object
          - `errors` object, required
      - `row_number` integer
    - `successes` PayItemBulkCreateSuccesses[], required
      - `pay_item` PayItem, required
        - `amount` integer, required: Value of the pay item. Its unit depends on the `type` of the pay code (see GET /v1/companies/:company_id/legal-entities/:legal_entity_id/pay-codes): `amount` in cents, `percentage` in basis points, `unit` as a raw count, `hours` as a whole number of hours, `duration` in seconds.
        - `code` string, required: Pay item type code
        - `custom_configuration` PayItemCustomConfiguration, nullable: The pay item custom configuration values for pay codes that use one, such as the employee's company car. The pay code's `custom_configuration` (GET …/pay-codes) gives the `key` and the JSON Schema of the `values`. On PATCH, `values` are merged onto the stored ones: nested objects merge, and `null` removes a field at any level. Send `null` for the whole `custom_configuration` to remove the stored values.
          - `key` string, required: The pay code's `custom_configuration.key`
          - `values` object, required: Values matching the pay code's `custom_configuration.schema`
        - `effective_date` string, date, required: Date the pay item is applied on (YYYY-MM-DD) — the day worked, the day a correction was submitted, or the first day of a leave period.
        - `employment_id` string, uuid, required: Employment UUID
        - `end_date` string, date, nullable, required: Last day of a leave period, inclusive (YYYY-MM-DD). Only for Leave-of-absence pay codes; Leave empty for other pay codes.
        - `id` string, uuid, required: Pay item's unique identifier. Editing `amount` or `effective_date` creates a new version with a new `id`; every `id` this API returned for a pay item edited through `PATCH` keeps working on `PATCH` and `DELETE` and resolves to the current version, except for a payment generated from a recurring pay item, which returns 422.
        - `partner_external_id` string, nullable: A reference code for the pay item record in the calling integration's own system. Private to that integration — no other integration can read or overwrite it. Null when the integration has not set one. See [Your own IDs on Remote records](https://developer.remote.com/docs/your-own-ids-on-remote-records).
        - `provider_data` PayItemProviderData, required
          - `correction_effective_date` string, date: Set this only on a correction: the original working day being corrected (YYYY-MM-DD). Its presence is what marks the pay item as a correction rather than an original submission.
          - `hourly_rate` integer: Hourly rate in cents
          - `hourly_rate_currency_code` string: Currency code in [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) format.
          - `pay_rate` number: Overtime rate multiplier (e.g. 1.5)
          - `shift_code` string: Shift identifier from partner system
          - `work_day_duration` integer: Expected work day duration in seconds
        - `replaced_ids` string[], required: Earlier `id`s of this pay item, oldest first; empty if it has never been edited. Each of them still resolves to the current version on `PATCH` and `DELETE`, so tracking them is strongly advised but not necessary.
      - `row_number` integer, required

## Other responses

- `400`: Bad Request
- `403`: Forbidden
- `409`: Conflict
- `422`: Unprocessable Entity
- `429`: Unprocessable Entity

---

[API](https://skmtc.dev/remote-com/apis/pay-compensation.md) - [All operations](https://skmtc.dev/remote-com/apis/pay-compensation/llms.txt) - [OpenAPI document](https://skmtc.dev/remote-com/apis/pay-compensation/revisions/ec29f1865c5e?raw)
