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.

MessageFix
"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.

MessageFix
"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.

MessageFix
"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.