Update a site rate contract
const url = 'https://api2.recruso.co.uk/v1/clients/1/sites/1/rate-contracts/1';const options = { method: 'PUT', headers: {Authorization: '<Authorization>', 'Content-Type': 'application/json'}, body: '{"jobDescription":"Order picking and pallet wrapping in a chilled environment.","otRulesAndDetails":"Time and a half after 40 hours in a week.","startTime":"2026-04-15T12:00:00Z","endTime":"2026-04-15T12:00:00Z","contactPersonId":88,"healthAndSafety":"Chilled store, 2-4C. Manual handling briefing required.","ppe":"Safety boots, hi-vis vest, thermal jacket.","assessmentRequired":true,"assessmentDetails":"Manual handling assessment at the gatehouse.","trainingRequired":true,"trainingDetails":"Half-day pallet truck training, renewed annually.","inductionRequired":true,"inductionDetails":"Site induction on first shift, 45 minutes.","holidayEntitlement":28,"agriculture":true,"expensesPaid":"Mileage at 45p per mile beyond 25 miles.","collectiveFacilities":"example","permanentVacancyAccess":"example","intervalOfPayments":"Weekly","lengthOfTermination":"1 week","frenchExtension":true,"dayRateRuleId":2,"breakTime":"30 minutes unpaid","restTimeBetweenShifts":11,"natureOfBusiness":"example","isRolledUpHoliday":false,"rolledUpHolidayOn":"2026-04-06T00:00:00","holidayPolicy":"Accrued at 12.07% of hours worked.","periodOfExtendedHire":"example","ratesToAddOrUpdate":[{"rateTypeId":1,"prePayRate":12.6,"preChargeRate":16.8,"preRequiredForHolidayPot":true,"prePayRateLimited":1,"prePayRatePsc":1,"preMarginRate":1,"preMarginRateLimited":1,"preMarginRatePsc":1,"preUseInAod":true,"postPayRate":13.4,"postChargeRate":17.65,"postRequiredForHolidayPot":true,"postPayRateLimited":1,"postPayRatePsc":1,"postMarginRate":1,"postMarginRateLimited":1,"postMarginRatePsc":1,"postUseInAod":true}],"rateTypeIdsToRemove":[1]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url https://api2.recruso.co.uk/v1/clients/1/sites/1/rate-contracts/1 \ --header 'Authorization: <Authorization>' \ --header 'Content-Type: application/json' \ --data '{ "jobDescription": "Order picking and pallet wrapping in a chilled environment.", "otRulesAndDetails": "Time and a half after 40 hours in a week.", "startTime": "2026-04-15T12:00:00Z", "endTime": "2026-04-15T12:00:00Z", "contactPersonId": 88, "healthAndSafety": "Chilled store, 2-4C. Manual handling briefing required.", "ppe": "Safety boots, hi-vis vest, thermal jacket.", "assessmentRequired": true, "assessmentDetails": "Manual handling assessment at the gatehouse.", "trainingRequired": true, "trainingDetails": "Half-day pallet truck training, renewed annually.", "inductionRequired": true, "inductionDetails": "Site induction on first shift, 45 minutes.", "holidayEntitlement": 28, "agriculture": true, "expensesPaid": "Mileage at 45p per mile beyond 25 miles.", "collectiveFacilities": "example", "permanentVacancyAccess": "example", "intervalOfPayments": "Weekly", "lengthOfTermination": "1 week", "frenchExtension": true, "dayRateRuleId": 2, "breakTime": "30 minutes unpaid", "restTimeBetweenShifts": 11, "natureOfBusiness": "example", "isRolledUpHoliday": false, "rolledUpHolidayOn": "2026-04-06T00:00:00", "holidayPolicy": "Accrued at 12.07% of hours worked.", "periodOfExtendedHire": "example", "ratesToAddOrUpdate": [ { "rateTypeId": 1, "prePayRate": 12.6, "preChargeRate": 16.8, "preRequiredForHolidayPot": true, "prePayRateLimited": 1, "prePayRatePsc": 1, "preMarginRate": 1, "preMarginRateLimited": 1, "preMarginRatePsc": 1, "preUseInAod": true, "postPayRate": 13.4, "postChargeRate": 17.65, "postRequiredForHolidayPot": true, "postPayRateLimited": 1, "postPayRatePsc": 1, "postMarginRate": 1, "postMarginRateLimited": 1, "postMarginRatePsc": 1, "postUseInAod": true } ], "rateTypeIdsToRemove": [ 1 ] }'Updates one rate contract on one of your own agency’s sites.
The contract’s own fields are a full replacement — every mutable field is written from the request, so an omitted field is set to null.
The rates are not. Rates change by delta rather than by replacement: ratesToAddOrUpdate adds a rate pair for a rate type the contract does not have, or overwrites the pair it does, and rateTypeIdsToRemove drops pairs by rate type. Omitting both leaves every existing rate untouched. A rate type may appear only once in ratesToAddOrUpdate, and a rateTypeIdsToRemove entry the contract does not hold returns 400.
A contract must keep at least one rate pair. A request that would remove them all returns 400.
jobCategoryId, shiftId and isDailyRate are fixed at creation and are not part of this request. Where isDailyRate is true, dayRateRuleId must still be supplied and greater than 0.
As on create, a margin shortfall is a warning, not an error: the update succeeds and warnings names the pairs that fell below their rate type’s minimum.
The site must belong to the client named in the route and the contract to that site; otherwise 404.
Access. Requires a client-credentials access token. Tokens issued through the interactive user login are rejected.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The clientId path parameter
The siteId path parameter
The id path parameter
Request Bodyrequired
Section titled “Request Bodyrequired”The replacement values for a rate contract. The contract’s own fields are fully replaced, so an omitted field is set to null; its rates change by delta instead. Job category, shift and daily-rate mode are fixed at creation and are absent here.
object
The job description for work under this contract. Up to 5000 characters.
Example
Order picking and pallet wrapping in a chilled environment.The overtime rules that apply, as free text. Up to 500 characters.
Example
Time and a half after 40 hours in a week.The site contact responsible for this contract. Must be a contact of the same site.
Example
88Health and safety information for work under this contract. Up to 5000 characters.
Example
Chilled store, 2-4C. Manual handling briefing required.The personal protective equipment required for this work. Up to 5000 characters.
Example
Safety boots, hi-vis vest, thermal jacket.Whether a worker must complete an assessment before being placed under this contract.
Example
trueWhat the required assessment involves. Up to 5000 characters.
Example
Manual handling assessment at the gatehouse.Whether a worker must complete training before being placed under this contract.
Example
trueWhat the required training involves. Up to 5000 characters.
Example
Half-day pallet truck training, renewed annually.Whether a worker must complete an induction before being placed under this contract.
Example
trueWhat the required induction involves. Up to 5000 characters.
Example
Site induction on first shift, 45 minutes.The holiday entitlement for work under this contract.
Example
28What expenses are paid under this contract. Up to 5000 characters.
Example
Mileage at 45p per mile beyond 25 miles.How often workers are paid under this contract. Up to 50 characters.
Example
WeeklyThe notice required to end an assignment under this contract. Up to 50 characters.
Example
1 weekThe day rate rule that applies, as an id from your agency’s Day rate rules lookup. Required when isDailyRate is true.
Example
2The break time for work under this contract, as free text. Up to 25 characters.
Example
30 minutes unpaidThe rest time required between consecutive shifts.
Example
11Whether holiday pay is rolled up into the rate rather than accrued.
Example
falseWhen rolled-up holiday pay was turned on for this contract, in UK local time (GMT/BST).
Example
2026-04-06T00:00:00The holiday policy that applies to this contract. Up to 4000 characters.
Example
Accrued at 12.07% of hours worked.Rate pairs to add or update. If a RateTypeId already exists, it will be updated; otherwise, it will be added.
Represents a rate pair input (pre-parity and post-parity) for a specific rate type. Duration is handled internally and is not exposed to the API.
object
The rate type ID (FK to tblRateTypes in AgencySettings).
The hourly rate paid to the worker before they qualify for AWR parity.
Example
12.6The hourly rate charged to the client before the worker qualifies for AWR parity.
Example
16.8Whether the pre-parity rate contributes to the worker’s holiday pot.
Example
trueThe hourly rate paid to the worker once they qualify for AWR parity.
Example
13.4The hourly rate charged to the client once the worker qualifies for AWR parity.
Example
17.65Whether the post-parity rate contributes to the worker’s holiday pot.
Example
trueRate type IDs to remove. Cannot remove all rates; at least one must remain.
Responses
Section titled “Responses”OK
A rate contract as it stands after the update, with any advisory margin warnings.
object
The rate contract’s unique identifier, assigned by Recruso.
The site this rate contract applies to.
The job category this contract prices, as an id from your agency’s Job categories lookup. Required, and fixed at creation.
The shift this contract prices, as an id from your agency’s Shifts lookup. Fixed at creation.
The job description for work under this contract. Up to 5000 characters.
The overtime rules that apply, as free text. Up to 500 characters.
The site contact responsible for this contract. Must be a contact of the same site.
Health and safety information for work under this contract. Up to 5000 characters.
The personal protective equipment required for this work. Up to 5000 characters.
Whether a worker must complete an assessment before being placed under this contract.
What the required assessment involves. Up to 5000 characters.
Whether a worker must complete training before being placed under this contract.
What the required training involves. Up to 5000 characters.
Whether a worker must complete an induction before being placed under this contract.
What the required induction involves. Up to 5000 characters.
The holiday entitlement for work under this contract.
What expenses are paid under this contract. Up to 5000 characters.
How often workers are paid under this contract. Up to 50 characters.
The notice required to end an assignment under this contract. Up to 50 characters.
When the contract was last updated, in UK local time (GMT/BST) — not UTC. Null until the contract is first updated.
Whether the contract is deleted. Deleted contracts are excluded from the list but are still returned when fetched by id.
Whether the contract is priced at a daily rate rather than an hourly one. Fixed at creation, and requires dayRateRuleId when true.
The Recruso user who created the contract.
When the contract was created, in UK local time (GMT/BST) — not UTC.
The Recruso user who last updated the contract. Null until the contract is first updated.
The day rate rule that applies, as an id from your agency’s Day rate rules lookup. Required when isDailyRate is true.
The break time for work under this contract, as free text. Up to 25 characters.
The rest time required between consecutive shifts.
Whether holiday pay is rolled up into the rate rather than accrued.
When rolled-up holiday pay was turned on for this contract, in UK local time (GMT/BST).
The holiday policy that applies to this contract. Up to 4000 characters.
The rate pairs associated with this contract. Each entry groups pre-parity and post-parity rates for a specific rate type.
API response DTO for a site rate pair in details view. Groups pre-parity (Duration=0) and post-parity (Duration=12) rates for a specific rate type. Duration is not exposed in the API.
object
The identifier of the pre-parity rate row in this pair.
The rate type this pair prices, as an id from your agency’s Rate types lookup.
The hourly rate paid to the worker before they qualify for AWR parity.
The hourly rate charged to the client before the worker qualifies for AWR parity.
Whether the pre-parity rate contributes to the worker’s holiday pot.
The identifier of the post-parity rate row in this pair.
The hourly rate paid to the worker once they qualify for AWR parity.
The hourly rate charged to the client once the worker qualifies for AWR parity.
Whether the post-parity rate contributes to the worker’s holiday pot.
Advisory warnings (e.g. margin rate below threshold). The record was saved successfully. Empty when there are no warnings.
Example
{ "siteRateContractId": 3041, "siteId": 512, "jobCategoryId": 17, "shiftId": 5, "jobDescription": "Order picking and pallet wrapping in a chilled environment.", "otRulesAndDetails": "Time and a half after 40 hours in a week.", "contactPersonId": 88, "healthAndSafety": "Chilled store, 2-4C. Manual handling briefing required.", "ppe": "Safety boots, hi-vis vest, thermal jacket.", "assessmentRequired": true, "assessmentDetails": "Manual handling assessment at the gatehouse.", "trainingRequired": true, "trainingDetails": "Half-day pallet truck training, renewed annually.", "inductionRequired": true, "inductionDetails": "Site induction on first shift, 45 minutes.", "holidayEntitlement": 28, "expensesPaid": "Mileage at 45p per mile beyond 25 miles.", "intervalOfPayments": "Weekly", "lengthOfTermination": "1 week", "modifiedOn": "2026-06-11T14:02:09", "isDeleted": false, "isDailyRate": false, "createdBy": 12, "createdOn": "2026-03-12T15:33:20", "modifiedBy": 12, "dayRateRuleId": 2, "breakTime": "30 minutes unpaid", "restTimeBetweenShifts": 11, "isRolledUpHoliday": false, "rolledUpHolidayOn": "2026-04-06T00:00:00", "holidayPolicy": "Accrued at 12.07% of hours worked.", "rates": [ { "siteRateId": 9107, "rateTypeId": 3, "prePayRate": 12.6, "preChargeRate": 16.8, "preRequiredForHolidayPot": true, "postSiteRateId": 9108, "postPayRate": 13.4, "postChargeRate": 17.65, "postRequiredForHolidayPot": true } ]}Bad Request
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Unauthorized
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Forbidden
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Not Found
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}
