# Error handling

The MK.IO APIs return the same error body for every failure. Once your client handles that one shape, the rest of error handling is consistent across the platform: inspect the HTTP status, branch on the machine-readable code, log the human-readable detail, and keep the request reference for follow-up.

## The standard error body

When an operation fails, the API returns a JSON object with this shape:

```
{

"error": {

"code": "<error_code>",

"detail": "<error_message>",

"extraDetail": {}

},

"status": 400,

"ref": "<request_reference>"

}
```

Each field has a distinct job:

| Field | Use it for |
| :-- | :-- |
| `error.code` | Programmatic branching in your application. |
| `error.detail` | Logs, dashboards, and operator-facing messages. |
| `error.extraDetail` | Any additional context the API includes. |
| `status` | The HTTP status code, repeated in the body. |
| `ref` | Support follow-up and request tracing. |

If you keep only one field beyond the status line, keep `ref`. It is the quickest way to identify a failing request afterwards.

## Status codes across the platform

The exact response set varies by endpoint, but these codes appear throughout the APIs.

Success responses:

| Code | Meaning |
| :-- | :-- |
| `200` | The request succeeded and returned a body. |
| `201` | The resource was created. |
| `202` | The request was accepted and continues asynchronously. |
| `204` | The request succeeded with no response body. |

Client-side problems:

| Code | Meaning | What to do next |
| :-- | :-- | :-- |
| `400` | Bad Request | Recheck the path, query parameters, and body format. |
| `401` | Unauthorized | Recheck the bearer token and `Authorization` header. |
| `403` | Forbidden | Recheck organization, project, and operation access for the token’s user. |
| `404` | Not Found | Recheck names and path parameters, especially project-scoped names. |
| `409` | Conflict | Recheck the resource state, or whether the operation conflicts with an existing reference. |
| `429` | Too Many Requests | Back off and retry later. See [Rate limits](https://docs.mediakind.com/api-guides/understanding/rate-limits). |

Server-side problems:

| Code | Meaning | What to do next |
| :-- | :-- | :-- |
| `500` | Internal Server Error | Retry carefully and keep the `ref` value. |
| `503` | Service Unavailable | Treat it as temporary and keep the `ref` value if it persists. |

## A handling order that works

When a request fails:

1. Record the HTTP status code.
2. Parse `error.code` and `error.detail`.
3. Record `ref`.
4. Decide whether to fix the request, retry it, or surface it to an operator.

As a guide to that decision:

- `400`, `401`, `403`, and many `404` responses mean the request needs correcting.
- `409` usually means the operation is valid, but the target resource is not in the right state yet, or is still referenced elsewhere.
- `429`, `500`, and `503` are the cases where careful retry logic pays off.

## See the status and body together

When you debug from the command line, print the transport status alongside the body so a log line captures both:

```
curl -sS \

-H "Authorization: Bearer <YOUR_TOKEN>" \

-H "Accept: application/json" \

-w "\nHTTP Status: %{http_code}\n" \

"https://app.mk.io/api/v1/projects/<PROJECT_NAME>/media/assets/nonexistent"
```
