Skip to main content
All SandPay errors follow a single, stable format. No surprises, no ad-hoc shape depending on the endpoint.

Response format

{
  "error": "invalid_body",
  "message": "amount must be greater than 0",
  "detail": {
    "fieldErrors": {
      "amount": ["Number must be greater than 0"]
    }
  }
}
  • error — machine-readable code, stable — use it in your logic (switch, if).
  • message — human-readable text, in English, subject to change.
  • detail — optional structured payload (per-field Zod errors, additional context).
The X-Request-Id header is included on every response (success and error alike). Keep it if you open a support ticket.

Codes by HTTP status

StatuserrorWhen
400invalid_bodyThe JSON body fails schema validation (Zod). detail contains the failing fields.
400invalid_paramsInvalid query parameters (e.g. limit=999).
401unauthorizedAuthorization header is missing.
401invalid_api_keyKey is unknown, revoked, or malformed.
402quota_exceededMonthly quota reached on the current plan. Upgrade your plan.
404not_foundResource not found (transaction, application, client…).
404env_not_foundThe country/operator pair has no configured environment.
429rate_limitedToo many requests — retry after the Retry-After header.
5xxinternalError on SandPay’s side. Tracked in Sentry, retry recommended.

Retry strategy

StatusRetriable?Notes
4xx (except 429)NoFix the request. Retrying will not help.
429YesHonour Retry-After, then exponential backoff.
5xxYesExponential backoff: 1s, 2s, 4s, 8s, 16s. Max 5 attempts.
The Node SDK raises a SandPayApiError that exposes status, code, message, detail, and requestId — use it to wire up your retry logic.

Example — handling a quota exceeded error

import { SandPay, SandPayApiError } from "@sandpay/node";

const sp = new SandPay({ apiKey: process.env.SANDPAY_API_KEY! });

try {
  await sp.payments.create({ /* ... */ });
} catch (err) {
  if (err instanceof SandPayApiError && err.code === "quota_exceeded") {
    // Notify the team, trigger an upgrade, etc.
    notifyOps("SandPay quota exceeded, requestId=" + err.requestId);
    return;
  }
  throw err;
}