Troubleshooting
Symptom first, cause second. Quote the X-Request-ID from the failing response whenever you escalate.
API calls
| Symptom | Cause |
|---|---|
401 "Invalid API key format" | header missing, or the key does not start with iss_ / ver_ and split into three parts |
401 "Invalid API key" | wrong secret, revoked key, or the key expired |
403 "not authorized for this issuer" | iss_ key used against a different issuer, verifier or organization — or a ver_ key on an issuer route |
400 on initiate-verification | metadata.redirectUri missing; one of redirectUri or redirect_uri is mandatory |
400 offer too large | credentialOfferMode: "by_value" with an offer over the inline limit — use auto |
404 on status or diagnostics | those routes exist only on the public edition, and diagnostics also need DIAGNOSTICS_ENABLED |
422 with a Zod envelope | request body failed schema validation; read the issue paths |
Wallet flows
| Symptom | Cause |
|---|---|
| Wallet cannot open the offer | the string is a deep link, not a URL — render it as a QR code or an HTTPS bridge link |
| Wallet rejects the credential | platform root CA not installed on the device |
| Wallet cannot resolve the offer | it does not support credential_offer_uri; force credentialOfferMode: "by_value" if the offer is small enough |
Token exchange fails on tx_code | the offer was created with userPinRequired: true and the holder must enter the returned transactionCode |
| Nothing reaches your host | wallets need public HTTPS — tunnel it, see Local testing |
Stuck states
| Symptom | Cause |
|---|---|
Issuance status stays pending | the wallet never exchanged the pre-authorized code; the offer will move to expired |
Verification stays initiated | the wallet never posted a response; it expires after 15 minutes, 60 for email delivery |
Verification is failure | read failureReason, then the diagnostics timeline |
| Email never arrives | check deliveryStatus; bounced and complained are terminal and will not retry |
| No callback ever fires | by design — there are no outbound webhooks, poll instead |