Complete list of error codes and how to fix them.
Error Codes
Error Response Format
Error responses use the same wrapper as success responses, with the error message inside content:
json
{
"statusCode": 400,
"content": {
"message": "A human-readable description of what went wrong"
}
}HTTP Status Codes
400 Bad Request
Something is wrong with your request. Missing field, invalid format, or business rule violation.
| Message | Fix |
|---|---|
| "qx must be a valid hex string" | Check the hex format of your P-256 key coordinates |
| "rpIdHash must be 0x-prefixed SHA256 hash (66 chars)" | Ensure rpIdHash is exactly 66 characters (0x + 64 hex chars) |
| "rpIdHash does not match any registered domain" | Register the domain in your organization settings first |
| "Transaction already expired" | Set the expiration to a future timestamp |
| "Expiration too far in the future (max 24h)" | Keep expiration within 24 hours from now |
401 Unauthorized
API key is missing, invalid, disabled, expired, or revoked.
| Message | Fix |
|---|---|
| "Missing x-api-key header" | Add the x-api-key header to your request |
| "Invalid API key" | Check that the API key is correct |
| "API key is disabled or revoked" | Generate a new API key |
| "API key has expired" | Generate a new API key with a later expiration |
| "Organization is disabled or deleted" | Contact support |
403 Forbidden
API key is valid but lacks the required scope, or the wallet does not belong to your organization.
| Message | Fix |
|---|---|
| "Insufficient scopes. Required: wallet:create" | Create a new API key with the required scope |
| "Wallet does not belong to this organization" | Check that the wallet address is correct |
| "Cannot access personal wallets through the BaaS API" | The BaaS API can only access organization wallets, not personal ones |
| "Organization is disabled" | Contact support |
404 Not Found
The resource does not exist in your organization.
429 Too Many Requests
Rate limit exceeded. See Rate Limits.
500 / 502 / 503
Server-side errors. Retry with exponential backoff.
Handling Errors in Code
javascript
class PasskalletError extends Error {
constructor(statusCode, message) {
super(message);
this.statusCode = statusCode;
this.name = "PasskalletError";
}
}
async function passkalletFetch(path, options = {}) {
const response = await fetch(
`https://gateway.dev.passkallet.com/sepolia/api/v1/passkallet/baas${path}`,
{
...options,
headers: {
"x-api-key": process.env.PASSKALLET_API_KEY,
"Content-Type": "application/json",
...options.headers,
},
}
);
const data = await response.json();
if (!response.ok) {
throw new PasskalletError(data.statusCode, data.content?.message);
}
return data.content;
}
// Usage:
try {
const wallets = await passkalletFetch("/wallets");
} catch (error) {
if (error instanceof PasskalletError) {
switch (error.statusCode) {
case 401: console.error("Check your API key"); break;
case 403: console.error("Missing scope:", error.message); break;
case 429: console.error("Rate limited. Retrying..."); break;
default: console.error(`Error ${error.statusCode}: ${error.message}`);
}
}
}Implement retry logic for 429, 500, and 502 errors. Do not retry 400, 401, 403, 404 -- these require fixing the request.