Skip to navigation

Errors and retries

Status codes across the 52ViKING APIs, and what each one asks you to do.
View as Markdown

The 52ViKING APIs are asynchronous where it matters and rate limited throughout. Both facts shape how you should handle failures.

Status codes

CodeMeaningWhat to do
200Success with a bodyNothing
202 AcceptedMaster Data write queuedPoll the Location header until the resource reports a terminal status
400Schema validation failedFix the payload; retrying will not help
401Expired token or insufficient privilegesRefresh once and replay; if it repeats, check permissions
413 Payload Too LargeMaster Data body over 2 MBSplit the batch
429 Too Many RequestsRate limit exceededBack off, then retry
5xxServer-side faultRetry with exponential backoff and jitter

Rate limits

Limits are published as approximate and subject to change. Treat these as order-of-magnitude, and always handle 429 rather than assuming you are under the ceiling.

APIDocumented limit
Auth (/v1/user)15 sign-ins per 60 seconds
Master Data~3 requests/second, measured over a 10-second window

The Master Data guidance is explicit and worth repeating: use the 2 MB body allowance rather than sending many small updates. A single POST carrying a thousand articles is cheaper for both sides than a thousand POSTs, and it is far less likely to hit 429.

Asynchronous writes

Two APIs accept work and complete it later. Neither tells you the outcome in the response to your write.

Master Data

Every POST returns 202 Accepted with a reference in the Location header. Schema validation is synchronous, so a malformed body fails immediately with 400. The distribution to stores is not.

1

POST the batch

You get 202 and a location. This means “accepted for processing”, not “applied”.

2

Poll the location

GET it to read the current status of the backend process.

3

Stop on a terminal status

Poll with backoff, and give up after a bounded number of attempts rather than forever.

Chain-scoped and store-scoped POSTs behave differently. Specify only the chain and the enterprise controller distributes identical data to every store. Specify chain and store and the data is store-specific, handled by that store directly. If you are unsure which you want, ask your FiftyTwo consultant. The choice is difficult to reverse once data is out.

Register Sale

POST /v1/sale returns a correlation ID immediately, and the sale starts in Pending. Poll GET /v1/sale/{correlationId} until it reports Processed or Failed.

import time
def wait_for_sale(client, correlation_id, timeout=120):
"""Poll until the sale reaches a terminal status."""
deadline = time.monotonic() + timeout
delay = 1.0
while time.monotonic() < deadline:
status = client.get_sale(correlation_id)["status"]
if status in ("Processed", "Failed"):
return status
time.sleep(delay)
delay = min(delay * 1.6, 10.0) # back off, but keep checking
raise TimeoutError(f"sale {correlation_id} still pending after {timeout}s")

A retry policy that works here

1

Never retry a 400

Validation failures are deterministic. Log the payload and move on.

2

Retry a 401 exactly once, after refreshing

More than once and you are probably looking at a permissions problem, not an expiry problem.

3

Back off on 429 and 5xx

Exponential backoff with jitter, so a fleet of workers does not resynchronise into a thundering herd after an outage.

4

Make writes idempotent on your side

Master Data POSTs are insert-or-update by object_id, so replaying a batch is safe. Register Sale is not inherently idempotent, so track correlation IDs to stop a retry after a network timeout importing the sale twice.

Duplicate object_id values within a single Master Data POST body are handled according to rules described in the Master Data overview. Deduplicate before you send rather than relying on that behaviour.