code. Client code branches on code. It must never branch on detail, which is human text, localized, and free to change.
The envelope
Public and MCP surfaces send this body as
application/problem+json; console routes send the identical body as application/json.
Anything that is not an expected error becomes a generic 500 with the code wondeya.internal.error. Stack traces, database messages, prompts and third-party provider errors never appear in a response; they go to the logs, keyed by the same requestId.
Codes by area
Request and transport
Authentication and session
Credentials
Workspaces and membership
Agents
Projects (sites) and their addresses
Pages and theme
Chat
Plans and billing
Onboarding
Knowledge
A source that fails after it was accepted does not raise an error: it moves to
status: "failed" and carries a machine-readable reason such as unsupported_document, ingest_failed, fetch_timeout, fetch_dns_failed, fetch_response_too_large or fetch_blocked_address:link_local. Branch on those the same way, and show a person the translated version, never the raw code.
Assets
Brand
Generic resources
Two habits worth having
Treat identical 404s as identical. Several codes deliberately collapse distinct situations into one answer: “not a member” reads the same as “no such workspace”, and an unknown host reads the same as an unpublished page. Telling them apart would turn the endpoint into a probe. Do not build UI that guesses which one it really was. Keep therequestId. It is the only handle that ties a failure you saw to the server-side logs of the same request.