Error Responses & Problem Types
When a request to the Seller API fails, the API returns a consistent, machine-readable error
body alongside the HTTP status code. This page explains the shape of that body, the
type field (the problem type), and—most importantly—how to
handle it so that an integration keeps working as the API evolves.
The type field carries a problem type: a URI that identifies the specific
kind of problem that occurred, independent of the HTTP status code. The remaining fields
(message and errors) are Seller API conventions that add human-readable
and field-level detail.
The Error Body
Every error response shares the same structure:
{
"type": "/problems/validation-error",
"message": "Validation Failed",
"errors": [
{
"field": "callbackUrl",
"message": "not valid"
}
]
}
| Field | Type | Description |
|---|---|---|
type |
string (URI reference) | An identifier for the kind of problem that occurred. Match on it to drive error handling — see Handling problem types below. |
message |
string | A short, human-readable summary of what went wrong. Intended for logs and developers — do not parse it programmatically. |
errors |
array of { field, message } |
Optional. Field-level details, mainly for validation errors. Empty ([]) when there are no per-field details. |
The HTTP status code remains the first signal of what happened (4xx = client error,
5xx = server error). The type field adds a finer-grained identifier on
top of it.
Handling problem types
Handling problem types comes down to a single idea that keeps an integration working as the API grows:
Act on the problem types relevant to the integration. For every other type —
including unrecognised ones and about:blank — fall back to the rest of the
response: the HTTP status code as the primary signal, with the message and
errors fields for additional context.
In practice, this means maintaining a single list — the problem types the integration handles — and nothing more. There is no need to classify types into categories, track which ones are stable, or keep an exhaustive list of every type the API might return.
What we guarantee
Two promises make this approach safe to rely on:
-
A problem type's meaning never changes. Once a
typeis published, its meaning is fixed — for example,/problems/validation-errorwill always carry the same meaning. Published types are never renamed or repurposed. - New, more specific types may appear over time. A situation that returns a broad type today may start returning a new, narrower type in the future, providing more precise, actionable information. As long as the HTTP status code is used as the fallback for types that are not explicitly handled, this is never a breaking change — the new type can be adopted whenever convenient, and until then it behaves exactly as before.
This is the reason the approach matters. Treating a broad type such as
/problems/bad-request as a permanent, exhaustive contract carries a risk: when a
dedicated type is later introduced for one of the cases it used to cover, that handling silently
stops matching. Falling back to the HTTP status code for anything not explicitly handled avoids
this entirely.
Match on type, not on message
Use type—not the message text—to drive logic. The wording of
message may be refined at any time and is meant for humans reading logs. Two
different problems can also share the same HTTP status code (e.g. several distinct
400s); the type is what tells them apart.
When there is no specific problem type: about:blank
Not every error has a dedicated problem type. When a response does not carry a more specific one,
type is set to about:blank:
{
"type": "about:blank",
"message": "Resource not found",
"errors": []
}
about:blank carries no semantics beyond the HTTP status code. It is
not a special case: it should be handled like any other type that is not explicitly matched
— base the response on the HTTP status code, with the message and
errors fields for additional context.
Getting more detail (dereferencing)
type values are relative URIs on purpose (e.g.
/problems/validation-error). They stay identical whether a request is made against
the playground or production — only the base URL changes, not the identifier. To read the
human-readable documentation for a specific problem, resolve the type against the
Seller API base URI — that is, append the type value to:
https://sellerapi.kaufland.com
For example, given this error response:
{
"type": "/problems/units/default-warehouse-not-found",
"message": "No default warehouse is configured for this seller account",
"errors": []
}
open the resolved URL in a browser:
https://sellerapi.kaufland.com/problems/units/default-warehouse-not-found
This links directly to the Problem Types reference, scrolled to
that exact problem, where its description and recommended next steps are documented. Dereferencing
is intended only when a developer wants the full context behind a problem — client code
should match on the type string and must not dereference it
automatically at runtime to make decisions.
Problem Type Reference
The table below lists the broad, cross-cutting problem types the API can return. These act as a fallback: when a specific error case does not (yet) have a dedicated type, one of these generic types is returned instead. Over time some of these error cases gain their own dedicated problem type (tied to a specific resource — orders, returns, warehouses, tickets, …), which then carries more precise information than the generic fallback.
There is no need to memorise which types are broad and which are dedicated — handling them works the same way either way. The complete, up-to-date catalogue, including every dedicated type and the endpoints that return it, is on the Problem Types reference page.
| Problem type | Typical status | Meaning | What to do |
|---|---|---|---|
/problems/bad-request |
400 | The request is invalid or malformed. | Review the request against the API semantics and check message for details. |
/problems/validation-error |
400 | The request contains invalid or malformed details. | Check that every property matches the documented schema. Inspect message and errors. |
/problems/missing-or-invalid-request-header |
400 | A mandatory request header is missing or malformed. | See the required headers documentation and check message. |
/problems/unauthorized |
401 | The request lacks valid authentication information. | Ensure the credentials are valid; check message for details. |
/problems/forbidden |
403 | Access to the requested resource is not authorised. | Verify the account's permissions; check message for why access is restricted. |
/problems/not-found |
404 | The requested resource was not found. | Ensure the correct identifier is used. |
/problems/duplicate-action |
409 | The action was already performed and cannot be repeated. | No action needed — the operation already took effect. |
/problems/action-not-allowed |
422 | The requested action cannot be performed on this entity in its current state. | Check message for details on why the action is not permitted. |
/problems/storefront-not-configured |
400 | The requested storefront is not configured for the account. | Configure the storefront in the Seller Portal, or contact support. |
/problems/invalid-credentials |
401 | No account matched the provided credentials. | Ensure correct and valid credentials are used. |
/problems/corrupted-signature |
401 | The request signature could not be verified. | Re-check the request-signing process and that every step is implemented correctly. |
/problems/inactive-account |
403 | The account being accessed is no longer active. | Contact the responsible seller manager for more information. |
/problems/server-error |
500 | The server encountered an unexpected error. | Retry later; if it persists, contact support. |
/problems/service-unavailable |
503 | The service is temporarily unavailable. | Retry with exponential backoff. If it persists, contact support. |
Best Practices
- Fall back to the rest of the response for any type not explicitly handled. Act on the types that are relevant to the integration, and for unrecognised, new, or
about:blanktypes rely on the HTTP status code, with themessageanderrorsfields for additional context. This is what keeps an integration working as new types are introduced. - Match on
type, not onmessage. Treatmessageas developer-facing text that may change. - Use the HTTP status code for transport-level decisions (retry on
5xx, stop on4xx), and thetypefor application-level decisions. - Ignore unknown fields. New fields may be added to the error body over time; parsers should tolerate them.
- Do not treat the current set of types as exhaustive. New, more specific types can appear for situations that previously returned a broad one; falling back to the HTTP status code for types that are not explicitly handled covers this gracefully.