> ## Documentation Index
> Fetch the complete documentation index at: https://developers.perform.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Responses and errors

> The response envelope, warning model, and error codes shared by every Perform.AI Public API endpoint.

Every Perform.AI API response is JSON. Alongside the HTTP status code, the response body carries an `api_response` code that tells you precisely what happened — including cases HTTP alone can't express, such as a success with warnings.

## The response envelope

Every functional endpoint returns an `api_response` field. On success its value is the string `"200"`, usually accompanied by a `data` object or array:

```json theme={null}
{
  "api_response": "200",
  "data": { ... }
}
```

The shape of `data` varies by endpoint: an object (Create Shipment, Retrieve Shipment Details), an array (List Shipments), or absent entirely when there is nothing to return (Create Events).

<Note>
  The one exception is the [token endpoint](/authentication): its success response contains no `api_response` field — only `access_token`, `expires_in`, and `token_type`.
</Note>

<Info>
  In application responses `api_response` is a **string** (`"200"`, `"299"`, `"4030"`). Errors generated at the API gateway — authorization failures and throttling — return it as a **number** (`403`, `429`). Parse it leniently: treat `"403"` and `403` as the same code.
</Info>

## Success with warnings (299)

A request can succeed while parts of it could not be applied — a value in the wrong format, or a reference that isn't configured in your account. The request still processes, and the response tells you what was skipped: HTTP status `299`, `api_response: "299"`, and a `warnings` object mapping each affected field to an array of messages.

```json theme={null}
{
  "api_response": "299",
  "data": { ... },
  "warnings": {
    "tracking_page_reference": [
      "tracking_page_reference specified in the request has not been configured."
    ]
  }
}
```

Warnings you can encounter across endpoints:

| Warning message                                                                                            | Why it occurred                                                                                          |
| ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `tracking_page_reference specified in the request has not been configured.`                                | The value doesn't match an activated tracking experience in your account.                                |
| `Manual events were not created for this shipment as a tracking_number and carrier has not been assigned.` | Events in the request were skipped because the shipment has no tracking number and assigned carrier yet. |
| `Description value ignored as both description and standard_key provided.`                                 | An event provided both fields; `standard_key` takes precedence and `description` is ignored.             |

<Tip>
  Treat HTTP 299 as a signal to inspect, not to retry. The resource was created or updated — resending the same request creates duplicates, not fixes.
</Tip>

Endpoint-specific warnings are listed on each endpoint's reference page.

## Request-level errors

These apply across all endpoints and relate to the request as a whole:

| HTTP | `api_response` | Message                                              | Why it occurred                                                                                          |
| ---- | -------------- | ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| 400  | `4000`         | Invalid request format                               | The request body could not be parsed — malformed JSON or a wrong `Content-Type`.                         |
| 403  | `403`          | Key not authorized                                   | The Bearer token is expired, invalid, or missing. Generate a new token.                                  |
| 403  | `403`          | Quota exceeded                                       | Your account's API request quota has been reached.                                                       |
| 403  | `403`          | Forbidden                                            | Your account does not have access to this endpoint.                                                      |
| 404  | `4041`         | No results found with the provided search parameters | The search was valid but matched nothing. Returned only by List Shipments and Retrieve Shipment Details. |
| 429  | `429`          | Throttled                                            | You exceeded the [rate limit](/essentials/rate-limits).                                                  |
| 500  | `500`          | System error                                         | An internal error caused the request to fail.                                                            |
| 502  | `502`          | Bad Gateway Error                                    | The proxy did not receive a valid response from the backend.                                             |
| 503  | `503`          | Service unavailable                                  | The API is temporarily unavailable.                                                                      |
| 504  | `504`          | Endpoint request timed out                           | The system timed out before responding.                                                                  |

<Note>
  A `4041` "no results" response is an empty search result, not a failure — handle it as "zero shipments matched". Endpoints that list documents, labels, PUDO locations, or carrier configurations instead return HTTP 200 with an empty `data` array.
</Note>

## Field validation errors (4030)

When one or more fields fail validation, the response is HTTP `400` with `api_response: "4030"` and an `errors` object mapping each rejected field to its messages:

```json theme={null}
{
  "api_response": "4030",
  "message": "validation_error",
  "errors": {
    "carrier_reference": [
      "carrier_reference specified in request has not been configured."
    ]
  }
}
```

For fields inside arrays — line items, events, shipping costs — errors are keyed by the item's position in the array (as a string), then the field inside it:

```json theme={null}
{
  "api_response": "4030",
  "message": "validation_error",
  "errors": {
    "shipping_costs": {
      "0": {
        "name": ["This field is required."]
      }
    }
  }
}
```

Nothing is persisted when a request fails validation: fix the listed fields and resend the whole request. Each endpoint's reference page lists its specific validation rules and messages.
