API 2.0.0: blocking changes and active contracts
ForPATCH /employees/{id}, an active contract prohibits both blocked: true and blocked: false. If blocked is included, the API rejects the entire patch with HTTP 422 and EMPLOYEE_HAS_ACTIVE_CONTRACT, including when dryRun=true. Other fields in that rejected request are not applied. Sending the employee’s existing blocked value does not avoid this rule.
For profile-only updates, omit blocked entirely. Configure serializers and synchronization mappings so they do not add blocked: false as a default. For example:
Source-of-truth model
Before implementation, assign ownership for every mapped field.Matching order
- Stored JobHandy employee ID
- Stable
employeeNumberwhen the source guarantees uniqueness - Another explicitly agreed unique mapping
- Email only when the customer guarantees it is immutable and unique
Synchronization swimlane
Resolve placement
- Send
X-Tenant-IDwhen the key includes multiple possible tenants. - Send
divisionIdwhen the selected tenant does not resolve one permitted division. - Use only a division inside the target tenant and API-key scope.
divisionId: nullremoves the division assignment but does not transfer the employee.
Find an employee
id after a successful match.
Create safely
1
Confirm no existing match
Search by the stored JobHandy ID or stable employee number.
2
Validate placement and payload
Call
POST /employees?dryRun=true with the final headers and body.3
Apply the create
Send the same request without
dryRun=true.4
Persist the real ID
Store only the ID returned by the non-dry-run
201 response.5
Record the side effect
A successful create sends a password setup email. Do not create duplicate accounts to repeat that email.
Patch only changed fields
null. Omit properties that should remain unchanged.
