REST Error Codes

How to branch on WP Sell Services REST failures from a client.

Clients should branch on the HTTP status first and use the code only to choose the message or the recovery step. The status tells you what kind of failure it is; the code tells you which one.

Asserted by wp wpss rest:contract, which runs the table below against a live site as anonymous, buyer, vendor and admin. Run it before shipping a client release.

Status meanings

Status Meaning What the client should do
401 Not authenticated, or the token expired Refresh the token and retry once. Never log the user out on a single 401.
403 Authenticated, but not allowed Stop. Retrying will not help. Show why, using the code.
404 No such route, or no such resource Stop. Do not cache "gone" for a feature flag - check the code first.
409 Conflict with current state Refetch the resource and reconcile before retrying.
501 Feature disabled on this site Hide the feature. Do not retry.

The single most important rule: a 401 and a 403 must never be interchangeable. A client that treats 403 as "refresh and retry" loops forever; one that treats 401 as "permission denied" logs people out when a token simply expired.

Codes

Authentication

Code Status Meaning
rest_not_logged_in 401 No authenticated user. Every protected route answers this when anonymous.

Authorisation

Code Status Meaning
wpss_not_admin 403 Logged in, but lacks manage_options. Moderation, audit log, analytics, and the Pro admin endpoints.
wpss_not_vendor 403 Logged in, but not a vendor. Vendor-only creates and earnings surfaces.
wpss_not_owner 403 Logged in, but does not own this specific resource - and is not an admin. Orders, reviews, portfolio items, disputes, media.

These three are deliberately distinct. wpss_not_owner is about one resource; wpss_not_admin and wpss_not_vendor are about the caller. Before 1.6.0 the admin case also answered wpss_not_owner, so a client could not tell "this isn't yours" from "you need admin" without reading the English message.

Resources

Code Status Meaning
rest_no_route 404 Unknown path. Also returned by WordPress core for a known path with an unsupported method - see the note below.
wpss_order_not_found 404 The order does not exist, or is not visible to this caller.

State

Code Status Meaning
wpss_order_not_payable 409 The order is not in a payable state. Refetch it before retrying.
wpss_milestone_locked 409 An earlier milestone phase is not approved yet. Phases pay in lock-step.
wpss_report_already_resolved 400 The report has already been actioned by someone else.
wpss_realtime_disabled 501 Realtime is switched off on this site. Hide the feature.
wpss_missing_service_requirement 403 Checkout blocked: a required service requirement was not supplied (FluentCart rail).

Known deviation: wrong HTTP method

A known path called with an unsupported method returns 404 rest_no_route, not 405.

This is WordPress core's behaviour, not ours - DELETE /wp/v2/posts answers the same. We match core deliberately rather than special-casing our namespace, so the client can apply one rule to every WordPress API it talks to. If a client needs to distinguish "wrong method" from "wrong path", check the route against the schema before dispatching.

Verifying

wp wpss rest:contract              # full table, one line per check
wp wpss rest:contract --porcelain  # failure count only, for CI

Exits non-zero on the first violated expectation. Add a row to RestContractCommand::expectations() whenever a new permission gate ships.