---
updatedAt: 2026-03-11T15:45:27.000Z
---

Fetch the complete documentation index at: https://developer.connecteam.com/llms.txt. Use this file to discover all available pages before exploring further.

# Set Pay Rates

The "Set Pay Rates" endpoint creates or updates pay rates for one or more users in a single bulk request.

## Endpoint

`PUT https://api.connecteam.com/pay-rates/v1/pay-rates`

## Authentication

* **API Key** or **OAuth 2.0**
* **OAuth Scope:** `pay_rates.write`

## Upsert Behavior

This endpoint uses **upsert** semantics: if a pay rate already exists for the same user and effective date, it is **fully replaced**. Otherwise, a new entry is added to the user's pay rate history. There is no separate "create" vs "update" endpoint.

## Request Body

| Field                                                       | Type    | Required    | Description                                                         |
| ----------------------------------------------------------- | ------- | ----------- | ------------------------------------------------------------------- |
| `payRatesByUsers`                                           | array   | Yes         | Array of user pay rate objects (max 500)                            |
| `payRatesByUsers[].userId`                                  | integer | Yes         | The user ID                                                         |
| `payRatesByUsers[].payRate.effectiveDate`                   | string  | Yes         | Effective date (YYYY-MM-DD)                                         |
| `payRatesByUsers[].payRate.rateType`                        | string  | Yes         | `hourly`, `monthly`, or `yearly`                                    |
| `payRatesByUsers[].payRate.isDefaultRateEnabled`            | boolean | No          | Enable default rate (default: true)                                 |
| `payRatesByUsers[].payRate.defaultRate`                     | number  | Conditional | Required when `isDefaultRateEnabled` is true. Must be > 0           |
| `payRatesByUsers[].payRate.isResourceRateEnabled`           | boolean | No          | Enable resource-specific rates (default: false)                     |
| `payRatesByUsers[].payRate.isApplyDefaultRateToNewResource` | boolean | No          | Auto-apply default rate to newly assigned resources (default: true) |
| `payRatesByUsers[].payRate.resourcesRates`                  | array   | No          | Resource rate configurations                                        |

## Validation Rules

* **`defaultRate` is required** when `isDefaultRateEnabled` is `true`. Omitting it returns 400.
* **`defaultRate` can be omitted** when `isDefaultRateEnabled` is `false` — the response will not include the field.
* **All rate values must be > 0** — zero and negative values are rejected (400). This applies to `defaultRate`, resource `rate`, and sub-resource `rate`.
* **`effectiveDate` must be in YYYY-MM-DD format** — other formats like DD-MM-YYYY are rejected.
* **`rateType` must be one of** `hourly`, `monthly`, or `yearly` — invalid values (e.g. `weekly`) are rejected.
* **User IDs must exist** in your company — non-existent user IDs return 400 with the invalid IDs listed.
* **Locked days check** — if any user has approved/locked timesheet days on or after the effective date, the entire request is rejected with 409 `HAS_LOCKED_DAYS`.

## Resource Rate Configuration

When `isResourceRateEnabled` is `true`, you can configure per-resource (job) rates:

| Field                                | Type    | Required    | Description                                                   |
| ------------------------------------ | ------- | ----------- | ------------------------------------------------------------- |
| `resourcesRates[].resourceId`        | string  | Yes         | Resource (job) ID                                             |
| `resourcesRates[].rate`              | number  | Conditional | Rate amount (> 0). Not required when `useDefaultRate` is true |
| `resourcesRates[].useDefaultRate`    | boolean | No          | Inherit the user's default rate (default: false)              |
| `resourcesRates[].subResourcesRates` | array   | No          | Sub-resource rate configurations                              |
| `subResourcesRates[].subResourceId`  | string  | Yes         | Sub-resource ID                                               |
| `subResourcesRates[].rate`           | number  | Conditional | Rate amount (> 0). Not required when `useParentRate` is true  |
| `subResourcesRates[].useParentRate`  | boolean | No          | Inherit parent resource's rate (default: false)               |

> 🚧 Important: Include ALL resources
>
> The `resourcesRates` array should include **all** resources that need custom rates. Resources not included will not have a resource-specific rate configured.

> 📘 Rate Inheritance
>
> When `useDefaultRate` is true on a resource, the `rate` field is omitted from both the request and response — the resource inherits the user's default rate. The same applies to sub-resources with `useParentRate` set to true.

## Request Example

```json
{
  "payRatesByUsers": [
    {
      "userId": 12345,
      "payRate": {
        "effectiveDate": "2025-03-01",
        "rateType": "hourly",
        "isDefaultRateEnabled": true,
        "defaultRate": 30.00,
        "isResourceRateEnabled": true,
        "isApplyDefaultRateToNewResource": true,
        "resourcesRates": [
          {
            "resourceId": "job_001",
            "rate": 35.00,
            "useDefaultRate": false,
            "subResourcesRates": []
          },
          {
            "resourceId": "job_002",
            "useDefaultRate": true,
            "subResourcesRates": [
              {
                "subResourceId": "sub_001",
                "useParentRate": true
              }
            ]
          }
        ]
      }
    }
  ]
}
```

## Response

The response mirrors the GET response structure, returning the created/updated pay rates for each user:

```json
{
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "payRatesByUsers": [
      {
        "userId": 12345,
        "payRate": {
          "effectiveDate": "2025-03-01",
          "rateType": "hourly",
          "isDefaultRateEnabled": true,
          "defaultRate": 30.00,
          "isResourceRateEnabled": true,
          "isApplyDefaultRateToNewResource": true,
          "resourcesRates": [...],
          "createdBy": 99999,
          "createdAt": 1709251200
        }
      }
    ]
  }
}
```

## Error Codes

| HTTP Status | Error Code        | Description                                                                                                           |
| ----------- | ----------------- | --------------------------------------------------------------------------------------------------------------------- |
| 400         | 1002              | Invalid request body — bad rate value (0 or negative), missing required field, invalid date format, invalid rate type |
| 400         | 1004              | User validation failed — one or more user IDs don't exist in the company                                              |
| 401         | —                 | Missing authentication                                                                                                |
| 403         | —                 | Invalid API key or insufficient OAuth scope                                                                           |
| 409         | HAS\_LOCKED\_DAYS | Effective date conflicts with approved or locked timesheet days                                                       |

[Pay Rates API Reference](https://developer.connecteam.com/reference)