Skip to content
StraventaDocs
Guides

Errors

Error envelope format, stable error codes, and recovery guidance for all 505pay API errors

Errors

All 505pay API errors use a consistent JSON envelope. Error codes are stable strings — you can rely on them across API versions.

Error envelope

{
  "error": "code_string",
  "message": "Human-readable description of what went wrong.",
  "request_id": "01j..."
}
FieldTypeDescription
errorstringStable machine-readable error code
messagestringHuman-readable description; may change between releases
request_idstringUUIDv7 identifying this request; include in support tickets

Always key your error-handling logic on error, not message. The message is for humans and may be updated without notice.

Error catalog

Deep link to any error with #error-<code> — for example #error-idempotency_conflict.

CodeHTTPServiceSummaryRemediation
invalid_credentials401authInvalid client credentials.Verify CLIENT_ID and CLIENT_SECRET. Check for whitespace or encoding issues in secrets.
token_expired401authAccess token has expired.Refresh using your refresh_token. Refresh proactively before expiry.
token_invalid401authAccess token is malformed or tampered.Obtain a new token. Never modify JWT payload manually.
insufficient_scope403authToken does not have the required scope.Request a token with the necessary scopes. Check the scope parameter in your token request.
tenant_suspended403authTenant account is suspended.Contact 505pay support. All API calls return this until suspension is lifted.
tenant_not_found404authTenant not found.Verify tenant ID or API credentials. May indicate misconfigured environment (sandbox vs production).
payment_not_found404paymentsPayment not found.Verify the payment ID. IDs are UUIDv7 — check for typos.
payment_already_settled409paymentsPayment has already been settled.No action needed — treat as success (idempotent).
insufficient_balance422paymentsInsufficient account balance.Top up merchant balance or contact ops. Specific to balance-deducted payment methods.
method_not_supported422paymentsPayment method not supported for this transaction.Use an alternate payment method. Check enabled methods in your tenant settings.
idempotency_conflict409paymentsIdempotency key reused with different request body.Use a unique idempotency key per distinct request, or ensure the request body matches the original.
rate_limited429allRate limit exceeded.Retry after the time in X-RateLimit-Reset header. See the Rate Limits guide for backoff guidance.
validation_failed400allRequest validation failed.Check the request body against the API reference. The message field contains field-level details.
internal500allAn internal server error occurred.Retry with exponential backoff. Contact support if persistent — include request_id in your support ticket.
not_found404allResource not found.Verify the resource ID and endpoint path. Check you are using the correct base URL for the environment.

Error handling example

interface ApiError {
  error: string;
  message: string;
  request_id: string;
}

async function callApi(url: string, token: string): Promise<Response> {
  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${token}` },
  });

  if (!res.ok) {
    const err: ApiError = await res.json();

    switch (err.error) {
      case 'token_expired':
        // Refresh token and retry
        token = await refreshAccessToken();
        return callApi(url, token);

      case 'rate_limited':
        // Wait and retry
        const resetAt = Number(res.headers.get('X-RateLimit-Reset')) * 1000;
        await new Promise(r => setTimeout(r, resetAt - Date.now()));
        return callApi(url, token);

      case 'internal':
        console.error(`Server error [${err.request_id}]:`, err.message);
        throw new Error(`API internal error — request ID: ${err.request_id}`);

      default:
        throw new Error(`${err.error}: ${err.message}`);
    }
  }

  return res;
}

Was this page helpful?

On this page