> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://mediakind.ferndocs.com/platform/understanding/error-handling/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://mediakind.ferndocs.com/_mcp/server. # 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: ```json { "error": { "code": "", "detail": "", "extraDetail": {} }, "status": 400, "ref": "" } ``` 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](/platform/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: Record the HTTP status code. * Parse `error.code` and `error.detail`. * Record `ref`. * 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: ```bash curl -sS \ -H "Authorization: Bearer " \ -H "Accept: application/json" \ -w "\nHTTP Status: %{http_code}\n" \ "https://app.mk.io/api/v1/projects//media/assets/nonexistent" ```