# Error handling

> HTTP status codes, the error response format and every error type the API returns.

![](https://developers.mothership.com/images/error-handling.svg)

Mothership uses conventional HTTP response codes.

- `2xx` codes represent a successful request.
- `4xx` codes represent a failed request with a descriptive error message.
- `5xx` codes represent a failed request due to a Mothership server error.

All error responses follow the same format.

```json Error Response JSON
{
  "code": 404,
  "type": "NOT_FOUND",
  "message": "Shipment not found"
}
```

| Property | Type | Description |
| --- | --- | --- |
| `code` | number | Status code of the error. |
| `type` | string | General categorization of the error. One of the types below. |
| `message` | string | Description of the error. |
| `metadata` | object | Extra detail for some errors, such as the fields a quote is missing. Often absent. |

> [!NOTE] Errors are not wrapped in data
> Successful responses wrap their body in a `data` object. Error responses don't. The published OpenAPI document shows a `data` wrapper on error responses, but the API sends the flat object above.

## Error types

Below are the error types you may encounter across all Mothership endpoints. Endpoint-specific details are in the documentation for the endpoint in question.

| type | Status code | Description |
| --- | --- | --- |
| `INVALID_REQUEST` | 400, 409 | The request failed validation or business rules, such as an invalid field. `message` explains why. Cancelling a shipment that cannot be cancelled returns this type with a 409. |
| `CARGO_TOO_LARGE` | 400 | The freight is too large to quote. |
| `NO_RATES_FOUND` | 400 | No carrier returned a rate for this shipment. |
| `QUOTE_NOT_PURCHASABLE` | 400 | The quote is missing details needed to book it. `metadata.invalidFieldsRequiredForPurchase` lists them. |
| `UNAUTHENTICATED` | 401 | Missing or invalid authentication token. |
| `PAYMENT_FAILED` | 402 | The organization has no payment source, or the payment failed. |
| `PAYMENT_REQUIRED` | 402 | Cancelling would cost more than the request accepted, and `metadata.feeCents` is the lowest fee available. Or the account is suspended, and `metadata.reason` says why. See [Account suspensions](https://developers.mothership.com/reference/error-handling#account-suspensions). |
| `MISSING_PERMISSION` | 403 | Authenticated, but missing permission to use this resource. |
| `NOT_FOUND` | 404 | The resource does not exist, or belongs to another organization. |
| `RATE_LIMIT_EXCEEDED` | 429 | Too many requests in too short of a timespan. |
| `SERVER_ERROR` | 500 | An internal error stopped Mothership from completing the request. |
| `UNKNOWN` | 500 | An unexpected server error occurred. |

## Account suspensions

When a payment fails, your account usually has a few days to pay before it is suspended. Some failures suspend the account right away, with no warning first. Either way, the same notice shows in the dashboard and in emails to your account owners and accounting contacts.

During that window, Create a quote and Create a shipment still succeed. Their response has a `warnings` array next to `data`, with the amount owed, the unpaid invoices, the deadline and where to pay them.

```json 201 Response with a warning
{
  "data": { "id": "-LawNN52lCcvj6T5qiEp" },
  "warnings": [
    {
      "type": "PAYMENT_HOLD_GRACE_WINDOW",
      "message": "We could not collect your payment. You can still get quotes and book shipments. To avoid suspension, pay your 2 unpaid invoices ($150.50) by Oct 20, 2026, 10:00 PM UTC. Another failed payment may suspend your account sooner. Pay at https://dashboard.mothership.com/billing.",
      "amountCents": 15050,
      "invoiceCount": 2,
      "invoiceIds": ["inv_1", "inv_2"],
      "deadline": "2026-10-20T22:00:00.000Z",
      "billingUrl": "https://dashboard.mothership.com/billing"
    }
  ]
}
```

`warnings` is left out when there is nothing to report. `amountCents` is `null` if we couldn't work out the amount.

Once the account is suspended, both endpoints fail with `402 PAYMENT_REQUIRED` and nothing is quoted or booked. `metadata.reason` is `unpaid_invoices` or `manual`. For `unpaid_invoices`, `metadata` also has `amountCents`, `invoiceCount`, `invoiceIds` and `billingUrl`. Paying every listed invoice lifts the suspension within a few minutes. For `manual`, contact [support@mothership.com](mailto:support@mothership.com).

```json 402 Response
{
  "code": 402,
  "type": "PAYMENT_REQUIRED",
  "message": "Your account is suspended. You cannot get quotes or book shipments because of unpaid invoices. You owe $150.50 on 2 invoices. Pay all of them to use your account again. Pay at https://dashboard.mothership.com/billing.",
  "metadata": {
    "reason": "unpaid_invoices",
    "amountCents": 15050,
    "invoiceCount": 2,
    "invoiceIds": ["inv_1", "inv_2"],
    "billingUrl": "https://dashboard.mothership.com/billing"
  }
}
```

## Retrying

- Retry a `429` after the window in the `Retry-After` header. See [Rate limiting](https://developers.mothership.com/reference/rate-limiting).
- Don't retry a `4xx` with the same request. Fix the request first.
- A `5xx` can be retried with backoff. If you encounter one and the problem is not resolved within 24 hours, please contact us at [developers@mothership.com](mailto:developers@mothership.com). Include the `mshp-request-id` response header, which identifies the request in our logs.