Skip to main content

The API

Stock Corrections has one endpoint.

POST /business-units/{businessUnitId}/stock-corrections/{itemId}
Hosthttps://stock-corrections-api.retailsvc.com
Permissionscr.corrections.create
Success202 Accepted

The authoritative technical reference is the OpenAPI specification. This page covers what the specification cannot tell you.

The business unit and the item are both in the path, so each call corrects exactly one item in one store. There is no bulk endpoint — to write off ten items, send ten calls.

The request​

{
"quantity": -3,
"reasonCode": "DMG",
"transactionDateTime": "2026-09-23T09:14:02+02:00",
"comment": "crushed in the stockroom",
"serialNumber": "SN-99481",
"batchNumber": "B-2026-14",
"businessPartnerId": "supplier-4471"
}
FieldRequiredMeaning
quantityyesHow much the stock changes by, signed. Must not be zero.
reasonCodeyesThe id of a configured reason code — see Reason codes.
transactionDateTimenoWhen the correction happened: an RFC 3339 date-time with an offset, such as 2026-09-23T09:14:02+02:00. Leave it out and the time the service receives the call is used. It may be in the past, but not more than a few minutes in the future. Send it if you might ever retry — see Retrying safely.
stockTypenoWhich stock the correction applies to: SalesStock or Returned. Leave it out for sellable stock. Any other value is rejected. See Which stock a correction moves.
commentnoFree text. Carried through to the event unchanged.
serialNumbernoFor serial-tracked items, the specific unit being corrected.
batchNumbernoFor batch-tracked items, the batch being corrected.
businessPartnerIdnoThe partner the correction relates to — a supplier whose delivery was short, for example.

A Correlation-Id header is accepted and is generated for you if you leave it out. It comes back as the response body and rides along on the published event, which makes it the easiest way to trace one correction across systems. Together with transactionDateTime, it is also what makes a retry safe.

🛑 quantity is a change, not a new level​

"quantity": -3 means three fewer than before. It does not mean set the stock to −3.

This is the mistake that corrupts data rather than failing loudly, so it is worth being blunt:

  • to write off 3 damaged units, send -3
  • to add 3 units found in the stockroom, send 3
  • to say "there are 12 on the shelf", do not use this API at all — that is a stock count

Zero is rejected with 400, because a correction that changes nothing has nothing to record.

The Inventory app presents this as an Add / Remove toggle with a positive number, and converts it to a signed value before calling. If you are building your own client, that pairing is worth copying — asking a person to type a minus sign is how sign errors get made.

Decimals​

quantity is a number, not an integer, so items sold by weight or length can be corrected in their own unit of measure — -0.75 kg is a valid correction. Send the quantity in the item's sales unit of measure; do not convert it to pieces.

Which stock a correction moves​

By default, sellable stock. That is the right answer for almost every correction: damage on the shelf, theft, expiry, a mistake made while receiving.

The exception is returned goods. When Hii Retail keeps the stock, a customer return lands in a separate returned stock rather than back on sale, because nothing at the till can tell whether a returned item is fit to sell again. When it turns out not to be, write it off from there:

{ "quantity": -1, "reasonCode": "DMG", "stockType": "Returned" }

🛑 Leave stockType out on a returned item and two figures go wrong at once. Sellable stock drops by an item that was never on the shelf, and the returned quantity stays standing. Nothing fails and nothing flags it.

Only SalesStock and Returned are accepted. Stock that is on order, in transit or reserved belongs to the document that created it (a purchase order, a transfer, a reservation) and is settled when that document completes, so correcting it by hand would put it out of step with that document.

The reason code does not choose the stock: Damaged on its own still means sellable stock.

What the response tells you​

202 Accepted means the correction was accepted and published as an event. It does not mean stock has moved yet — that happens a moment later, in whichever system applies it. Any other response means nothing was published, and nothing will reach stock.

The distinction that matters to a client is between the two kinds of failure:

  • a 4xx means the request cannot succeed as sent. Fix it — retrying it unchanged fails the same way.
  • a 5xx means the service could not complete it just now. Retry the same request.

Reason codes are checked when the call arrives​

The reason code is looked up in the business unit's configuration for every call. A correction is rejected with 400 when its code:

  • does not exist for the business unit — including a misspelling or a difference in case;
  • exists, but is not configured for stock corrections;
  • is deactivated.

It is also rejected when the business unit has no reason codes configured at all. The message says which of these applies and names the code and the business unit. It is written for the person fixing the configuration — do not parse it.

If Customer Controlled Configuration (CCC) cannot be reached to make the check, the response is 503, not 400: nothing is wrong with the request, so retry it.

The check is made once, at the moment of the call. A correction accepted under a code that is later deactivated stays valid, and is still applied if its message is delivered again.

To avoid rejections in the first place, read the tenant's configured codes from CCC and send only codes you found there — see Reason codes.

Retrying safely​

A retry is safe when it is the same request. Send your own Correlation-Id and a transactionDateTime, and on a retry resend both unchanged, with the same body. The service derives the correction's stockCorrectionId from what you sent, so the retry produces the same id and the same event. Every consumer, Stock Transaction Processing included, recognises it as a repeat, and the stock moves once.

So when a call times out, the connection drops or you get a 5xx, retry the same request. You do not need to find out first whether the first attempt landed — that is the point.

On a retry you sendThe retry is
your own Correlation-Id and a transactionDateTime, both unchanged✅ recognised as the same correction
no Correlation-Id, or no transactionDateTime🛑 a second correction — the stock moves twice
the same Correlation-Id with a new transactionDateTime🛑 a second correction

"The same request" means the business unit and item in the path, every field in the body, the Correlation-Id, and the credentials you call with, because the caller's identity is part of the correction. Change any of them and it is a new correction — which is what you want when someone corrects their own mistake with a second call.

⚠ Give each correction its own Correlation-Id. Reusing one across a batch run is fine as long as the corrections differ: a different item, quantity, reason or time keeps them apart. But two corrections that are identical in every field, sent under the same Correlation-Id and the same transactionDateTime, cannot be told apart from a retry and are treated as one. If you genuinely mean two, send them with different Correlation-Ids.

The Inventory app does this for you. A correction is written to a queue on the handset first, and every attempt to send it carries the same Correlation-Id and the moment the correction was made. So a correction captured with no signal can be sent hours later, retried as often as needed, and still land once, at the time it actually happened.

Validation​

ResponseWhen
202Accepted and published
400quantity missing, not a number, or zero; reasonCode missing, or not a code that can be used (see above); transactionDateTime not a date-time with an offset, or more than a few minutes in the future; stockType other than SalesStock or Returned; empty businessUnitId or itemId
403The token lacks scr.corrections.create, or is not valid for this tenant
503CCC could not be reached to check the reason code. Retry the same request.
other 5xxThe correction was not published. Retry the same request.

⚠ The item is not validated. A correction for an item that does not exist in the catalogue is accepted and published. What happens next is the consumer's decision — when Stock Transaction Processing is master, whether an unknown item is stock handled depends on its own Use default values if item is unknown setting. Send catalogue item ids, and treat a rise in corrections for unknown items as a sign that an integration is sending the wrong identifier.

Who the correction is attributed to​

The correction records the user whose access token made the call, taken from the token itself — there is no field for it in the request and you cannot set it.

⚠ The userId on the event is an opaque identifier, not a username or an e-mail address. It identifies the caller consistently, so you can group corrections by who made them, but it is not a name and carries no personal data.

Do not build a display around it. For a system integration authenticating as itself, the value identifies the integration rather than any person, so it will be the same on every correction you send. If you need to know which of your users triggered a correction, record that on your side and match it up with the Correlation-Id.