Skip to main content

API 2.0.0: blocking changes and active contracts

For PATCH /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:
Do not retry an unchanged rejected patch. Resolve the blocking request through the responsible business process, or, for an independently intended profile update, send a new patch containing only the intended supported profile fields. A successful dry run does not reserve contract state; handle the same validation on the real write. A reliable synchronization separates identity matching, tenant placement, validation, mutation, and checkpointing. Never create a new JobHandy employee on every import run.

Source-of-truth model

Before implementation, assign ownership for every mapped field.

Matching order

  1. Stored JobHandy employee ID
  2. Stable employeeNumber when the source guarantees uniqueness
  3. Another explicitly agreed unique mapping
  4. Email only when the customer guarantees it is immutable and unique
If a query returns zero or more than one plausible match, stop automated creation and route the record for reconciliation.

Synchronization swimlane

Resolve placement

  • Send X-Tenant-ID when the key includes multiple possible tenants.
  • Send divisionId when the selected tenant does not resolve one permitted division.
  • Use only a division inside the target tenant and API-key scope.
  • divisionId: null removes the division assignment but does not transfer the employee.

Find an employee

Persist the returned JobHandy 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

Nullable patch properties can be cleared with null. Omit properties that should remain unchanged.

Checkpoint model

Persist at least:

Timeout reconciliation

Common failures

Last modified on October 20, 2026