Yappy API errors

Every failure — REST, auth, and batch alike — comes back as a JSON document. Nothing in this API ever answers an agent with an HTML error page.

The shape

RFC 9457 problem details, served as application/problem+json:

{
  "type": "https://yappy.biz/developers/errors#not_found",
  "title": "Resource not found",
  "status": 404,
  "detail": "No documentation page with slug 'agent-mod'. Did you mean 'agent-mode'?",
  "instance": "/api/v1/docs/agent-mod",
  "code": "not_found",
  "request_id": "01J9X4Q0F7",
  "docs_url": "https://yappy.biz/developers/errors"
}

code is the field to branch on: it is stable, lowercase snake_case, and never changes meaning. title and detail are for humans and for an agent explaining itself to a user. detail names the fix wherever a fix exists.

Validation failures add an errors array, one entry per offending parameter:

{
  "code": "invalid_request",
  "status": 400,
  "errors": [
    { "field": "limit", "code": "out_of_range", "detail": "limit must be between 1 and 100, got 500" }
  ]
}

Codes

HTTPcodeMeansWhat to do
400invalid_requestA parameter is missing, malformed, or out of rangeRead errors[]; fix and retry
400invalid_cursorThe cursor value was not one we issuedRestart the listing without a cursor
401invalid_tokenToken expired, malformed, or revokedGet a new token; do not retry with the old one
403insufficient_scopeThe token is valid but lacks the scopeRe-issue with the scope named in the header
404not_foundNo such release, page, or jobCheck detail — it usually suggests the near miss
405method_not_allowedWrong verb for that pathSee Allow on the response
406not_acceptableNo representation matches your AcceptAsk for application/json or text/markdown
409idempotency_conflictSame Idempotency-Key, different bodyUse a new key, or send the original body
413payload_too_largeBatch over 20 operations, or a body over 64 KBSplit the request
415unsupported_media_typePOST without application/jsonSet the content type
422unprocessableSyntactically fine, semantically impossibledetail explains why
429rate_limitedToo many requestsWait Retry-After seconds; see rate limits
500internal_errorOur faultRetry once with backoff, then report request_id
503upstream_unavailableA dependency (the release feed) is downRetry with backoff; cached data may still answer

Retrying safely

429, 500, 502, 503, and 504 are worth retrying with exponential backoff and jitter. 4xx codes other than 429 are not — the same request will fail the same way, and hammering it only spends your rate budget.

Every GET in this API is safe to repeat. Every POST accepts an Idempotency-Key, so a retry after a network timeout returns the original result rather than starting a second job.

Batch semantics

A POST /api/v1/batch returns 200 even when individual operations fail. Each entry carries its own status and, on failure, a full problem document in body. Check per-operation status; do not infer success from the envelope.

Request ids

Every response carries X-Request-Id, echoed into the problem document as request_id. Quote it when you report something — it is how we find the one request among many.

MCP errors

The MCP server speaks JSON-RPC, so its errors use that shape instead: -32700 parse error, -32600 invalid request, -32601 method not found, -32602 invalid params, -32603 internal error. A tool that ran but could not answer returns a normal result with isError: true and text explaining what to try — that distinction matters, because the first kind means your call was wrong and the second means the world was.

Reading this as an agent? The same page in markdown: /developers/errors.md · machine index: /llms.txt · API: /openapi.json · MCP: https://yappy.biz/mcp