A lost update now answers 409 instead of overwriting or failing opaquely
When two updates to the same resource overlap, the one that arrives second answers 409 CONCURRENT_MODIFICATION instead of silently discarding the other's change or surfacing an internal error. Re-read the resource and retry.
When two updates to the same resource overlap, the one that arrives second answers 409 CONCURRENT_MODIFICATION instead of silently discarding the other's change or surfacing an internal error. Re-read the resource and retry.
What else changed
- What you may see that you did not before. A
PATCHon a customer, a product or a series can now answer409with codeCONCURRENT_MODIFICATION. It means another write to the same resource landed between your read and your write. Nothing was applied. - What to do with it. Re-read the resource, re-apply your change on top of the fresh state, and send it again. The retry is safe: the rejected request had no effect.
- Why it is an improvement even though it is a new failure. Before, one of the two updates won and the other disappeared without telling anyone — the field you set was simply not there afterwards. Where the collision hit a uniqueness rule instead, it surfaced as a generic database error rather than something you could act on.
- Promoting a default series is the same story: two simultaneous promotions for the same document type now leave exactly one default, and the loser gets the
409rather than an internal error.
Endpoints
- PATCH/v1/companies/{company_id}/customers/{customer_id}May answer 409 CONCURRENT_MODIFICATION
- PATCH/v1/companies/{company_id}/products/{product_id}May answer 409 CONCURRENT_MODIFICATION
- PATCH/v1/companies/{company_id}/series/{series_id}May answer 409 CONCURRENT_MODIFICATION
Request bodies now have a 2 MB limit, with its own error code
A body above 2 MB is now rejected by the API with `413` and the new error code `REQUEST_BODY_TOO_LARGE`, whose `error.details` carries the applicable maximum and the size the request declared. The 8 MB ceiling still exists but is enforced at the network edge, before the request reaches the API, and keeps answering `PAYLOAD_TOO_LARGE`. Chunked transfer encoding is no longer rejected: `411 LENGTH_REQUIRED` is gone. The largest body the API expects is a bulk import at its declared `maxItems`, comfortably under 2 MB. If you are approaching it, split the batch.
The contract stops declaring what the server never sends
Several responses and one header were documented but never produced. They are gone from the contract, so a generated client no longer waits for them. Nothing about the server changes: it never sent them.