Skip to main content
A sale usually comes back with its result straight away. Sometimes KRA is slow, or the sale has to be retried, and the result arrives later. A callback tells your server when that happens, so you do not have to poll.
Callbacks are not signed. There is no signature header and no shared secret, so you cannot prove from the request alone that it came from us. Treat a callback as a notification only: before you act on it, for example by releasing goods or marking an order paid, fetch the sale with GET /v1/sales/{id} and trust that.

Ask for a callback

Add callbackUrl to POST /v1/sales or POST /v1/credit-notes.
The URL must:
  • be an absolute https URL, at most 2048 characters;
  • not contain credentials, as in https://user:pass@host;
  • point at a public host. Localhost and private, loopback and link-local addresses are refused. The host is checked again at delivery against every address it resolves to.
A URL that breaks a rule is refused with a 400 that names callbackUrl. To test locally, expose your machine with a public https tunnel, because localhost is refused.

When we call you

An event is sent for every result the document reaches, however it got there: the original request, POST /v1/sales/{id}/retry, or a retry from the dashboard. If KRA rejects a sale, you fix it and it is then accepted, you receive sale.failed and then sale.completed.

What we send

A POST with a JSON body and these headers:
data.sale is the same object GET /v1/sales/{id} returns, without its callback block. It is abridged above.

What your server must do

Reply with any 2xx status within 10 seconds. Anything else counts as a failed attempt: a non-2xx status, a timeout, a connection error, or a redirect. We do not follow redirects.

Retries

If an attempt fails we try again, up to 7 attempts in total. The waits between attempts are 1, 5, 15, 60, 180 and 360 minutes, about ten and a half hours in all. Retries run on a sweep that happens once a minute, so the timings are approximate. After the last failure the delivery is marked failed. The same result is delivered once. If it is announced twice, you still get one delivery.

Check the delivery state

GET /v1/sales/{id} includes a callback object that shows whether you were told:

Resend a callback

If your endpoint was down for longer than the retries lasted, call POST /v1/sales/{id}/callback/resend. It needs sales:write. It makes one attempt right now to deliver the latest result, and returns the updated callback object so you can see how it went. It is a 404 if the sale was created without a callbackUrl, and a 409 if the sale has no result from KRA yet.

Build a safe receiver

1

Answer fast

Return 200 as soon as you have stored the event. Do the real work afterwards.
2

Ignore duplicates

Keep the X-Callback-Id values you have handled. It is stable across retries of one result, so a repeat is safe to skip.
3

Confirm before acting

Fetch GET /v1/sales/{id} with your key and use that response, not the callback body, to decide what to do.
Node.js