Valdyr

Errors

The structure of an error response from the Seamless OS API, and what each status code means.

The Seamless OS API answers with a standard HTTP status code and a structured error body. The body names the fault in a form that a person can read and in a form that your code can match on.

Error response structure

Every error response has the same structure:

{
  "message": "Validation failed",
  "reason": "order_invalid_input",
  "domain": "order",
  "retryable": false,
  "internalCode": "4240",
  "code": "invalid_input",
  "details": [
    {
      "message": "email is required",
      "reason": "property_required",
      "code": "invalid_argument",
      "property": "contact.email"
    },
    {
      "message": "msisdn is not a phone number",
      "reason": "property_invalid",
      "code": "invalid_argument",
      "property": "subscriber.msisdn"
    }
  ],
  "hint": "Correct the fields that the details name, then send the request again.",
  "traceId": "cc4a73acca1bb07e0e54bd41f5ce1e7e",
  "spanId": "37cec694d3b99f0f"
}

Error fields

message (required): A description of the fault for a developer to read in a log or in a console.

reason: A name in lower snake_case for the condition that failed, such as customer_not_found. The same condition always carries the same reason. It is independent of the HTTP status and of which system reported the fault, and it is stable across releases. Branch on this field.

domain: The business area of the reason, such as customer or porting. It is for information only. Do not branch on it.

retryable: True when the same request can pass later with no change. A 429 and a 503 always have retryable set to true.

externalCode and externalSource: The code that a third party sent for the fault, and the name of that third party. A network operator is an example of a third party. These fields are only present when a third party reported the fault.

internalCode: A string of digits for the condition that failed. It is stable across releases. A condition that we added after reason has no internalCode, so branch on reason instead.

code (required, deprecated): Use reason instead. This field mixes three unrelated codes, and it does not say which one you have. The three are a code that we publish, an operator’s own code, and the request status.

details: A list of the individual faults. Each entry carries these fields:

  • message: A description of the one fault for a person to read.
  • reason: The name of the one fault. The section “Validation reasons” gives the general ones.
  • code (deprecated): The request status of the whole error, such as invalid_argument. Use reason instead.
  • property: The field or the parameter that caused the fault. A nested field uses dot notation, such as billing.email.
  • suggestion: A correct value, when the API can propose one.

hint: One more sentence about how to correct the request.

traceId and spanId: The trace that your request produced, and the span inside it that failed. Quote the trace identifier when you report a fault to us. It is what lets us find your request among everything else the platform served.

Branch on the reason

Match your code on reason. Obey these rules:

  • Accept a reason that you do not know. We add new reasons without notice. Use the HTTP status for a reason that you do not know.
  • Do not branch on domain. A reason can move to a different domain.
  • Do not parse message or hint. Their words can change in each release.

If retryable is true, you can send the same request again later. If the response has a Retry-After header, wait for that number of seconds first.

Validation reasons

A validation problem in details, and an item of the validation of an order, carry a reason. A problem that is not a business condition has one of these general reasons:

ReasonThe problem
property_requiredA value is missing.
property_invalidA value has the wrong format, or is not permitted.
property_conflictTwo values cannot occur together.

A problem that is a business condition has the reason of that condition, such as activation_date_in_past.

HTTP status codes

The status code gives the category of the fault. If an error names no condition of its own, its reason comes from the status:

Status CodeReasonDescription
400bad_requestBad Request - Invalid request syntax, or a validation fault
401unauthorizedUnauthorized - The authentication credentials are absent or invalid
403forbiddenForbidden - The credentials are valid, but the permissions are not sufficient
404not_foundNot Found - The requested resource does not exist
409conflictConflict - The request conflicts with the current state, such as a reused idempotency key with different data
412precondition_failedPrecondition Failed - The resource is not in a state that allows this request
429rate_limit_exceededToo Many Requests - You reached the rate limit
500internal_errorInternal Server Error - An unexpected fault on our side
501not_implementedNot Implemented - The endpoint is not available for your brand
503service_unavailableService Unavailable - A system that we depend on did not answer. Send the request again