Troubleshooting

This page is organized by what you are seeing, not by error code. Find your symptom, read the cause, run the check. For the exhaustive code-by-code reference, see Errors.

Every check runs against the live sandbox at https://phosra-api-sandbox-production.up.railway.app — no key required for the reads below. Set it once:

bash
export BASE=https://phosra-api-sandbox-production.up.railway.app

First: decode any error in five seconds

Every error carries the same three fields. Read them in this order:

  1. code — the HTTP status. 4xx is your request; 5xx is ours.
  2. class(OCSS routes only) the machine failure class. Branch on this.
  3. failed_step(403 standing failures only) the exact check that rejected you.
bash
# Pretty-print any error and its class
curl -s "$BASE/api/v1/providers/did:ocss:nope/connect" | python3 -m json.tool
# {
#   "error": "Not Found",
#   "message": "provider not found",
#   "code": 404,
#   "class": "not_found"
# }

Grab the X-Railway-Request-Id response header before you contact support — it lets us find your exact request in the logs.

bash
curl -s -D - -o /dev/null "$BASE/health" | grep -i x-railway-request-id

401 vs 404: which one should I be getting?

The two most-confused failures. They mean opposite things, and the API keeps them strictly separate so you always know which side the problem is on.

401 signature_invalid404 not_found
The routeexists, and requires you to prove who you aremay or may not exist — the resource behind it doesn't
What's wrongyour request signature (missing, malformed, wrong key_id)the id in the path (a DID / rule / endpoint that isn't there)
Re-signing helps?Yes — fix the signature and retryNo — the thing isn't there; a retry returns 404 forever
Leaks existence?No — you get 401 before any lookupYes, deliberately: 404 means "genuinely absent," never a silent redirect to a nearby live resource

The trap: a signed route you call without a signature returns 401, not 404 — even if the path is nonsense. Authentication is checked before resource lookup, so a missing signature masks whether the resource exists at all.

bash
# No signature on a signed route -> 401 (the id is never even looked up)
curl -s -o /dev/null -w "%{http_code}\n" -X POST "$BASE/api/v1/enforcement-confirmations" \
  -H "Content-Type: application/json" -d '{}'
# 401
 
# An UNSIGNED read route with a bogus id -> 404 (resource lookup runs)
curl -s -o /dev/null -w "%{http_code}\n" "$BASE/api/v1/providers/did:ocss:nope/connect"
# 404

Decide in one question: does this route require a request signature? If yes and you're getting 401 → fix the signature (see below). If no, or your signature is already valid and you still get 404 → the id in your path is wrong; verify it character-for-character. A 404 is terminal — do not poll it back to life.


Symptoms


Still stuck?

  1. 1
    Confirm the census is up

    bash
    curl -s "$BASE/health"          # {"status":"ok"}

  2. 2
    Confirm your identity is on the Trust List

    bash
    curl -s "$BASE/.well-known/ocss/trust-list" | python3 -m json.tool | head

  3. 3
    Capture the request id and reach out

    Grab X-Railway-Request-Id from the failing response and email [email protected] with the request id, the code, the class, and (if present) the failed_step.