NEW APP AVAILABLE FOR DOWNLOAD NOW

Get it on Google PlayDownload on the App Store

Error Handling

Understand API response formats and error codes

Learn how to handle API responses and errors gracefully in your application.

Response Format

All API responses follow a consistent format:

Success Response

json
{
  "status": {
    "code": 200,
    "message": "Success"
  },
  "data": {
    // Response data here
  }
}

Error Response

Errors carry a separate error object. status.code is the numeric HTTP status; the machine-readable code is error.code. Match on error.code, never on the message text.

json
{
  "status": {
    "code": 400,
    "message": "Bad Request"
  },
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Please check your input and try again.",
    "details": {}
  }
}

The details object is included only when there are field-level details.

HTTP Status Codes

CodeMeaning
200Success
201Created (for new resources)
400Bad Request - Invalid parameters
401Unauthorized - Invalid or missing API key
403Forbidden - Insufficient permissions
404Not Found - Resource doesn't exist
429Too Many Requests - Rate limit exceeded
500Server Error - Something went wrong on our end

Error Codes Reference

Authentication Errors (401)

CodeDescriptionSolution
AUTHENTICATION_REQUIREDNo API key providedInclude Authorization: Bearer header
INVALID_CREDENTIALSAPI key is invalidCheck your API key is correct
TOKEN_REVOKEDAPI key has been revokedGenerate a new API key
TOKEN_EXPIREDAPI key has expiredGenerate a new API key

Authorization Errors (403)

CodeDescriptionSolution
INSUFFICIENT_SCOPEMissing required scopeAdd the required scope to your API key
API_DISABLEDAPI access is disabledEnable API access in account settings
IP_NOT_ALLOWEDIP address not whitelistedAdd your IP to the whitelist or remove restrictions
ENVIRONMENT_MISMATCHWrong environmentUse sk_test_* for sandbox, sk_live_* for production

Validation Errors (400)

CodeDescriptionSolution
VALIDATION_ERRORGeneral validation failureCheck the error message for details
MISSING_PARAMETERRequired parameter missingInclude all required parameters
INVALID_PARAMETERParameter format invalidCheck parameter format requirements
INVALID_PHONE_NUMBERPhone number format wrongUse Nigerian format: 080, 081, 070, 090, 091
INVALID_AMOUNTAmount outside allowed rangeCheck product min/max amounts
DUPLICATE_REFERENCEexternal_reference already usedUse a unique reference for each transaction
INSUFFICIENT_BALANCEAccount balance too lowFund your account before purchasing
PRODUCT_UNAVAILABLEProduct or provider unavailableTry a different product or retry later

Meter and decoder verification failures return VALIDATION_ERROR with a message describing the problem: there is no dedicated verification error code. A purchase submitted before verifying, or with details that do not match, also returns VALIDATION_ERROR (or PURCHASE_FAILED when the purchase itself is rejected downstream).

Provider Errors (400)

CodeDescriptionSolution
PROVIDER_ERRORUpstream provider errorRetry the request or contact support
PURCHASE_FAILEDPurchase was rejectedCheck the message, then retry

Not Found Errors (404)

CodeDescriptionSolution
PRODUCT_NOT_FOUNDProduct doesn't existCheck the product ID
TRANSACTION_NOT_FOUNDTransaction doesn't existCheck the transaction ID
PURCHASE_NOT_FOUNDPurchase doesn't existCheck the purchase/transaction ID

Status Errors (400)

CodeDescriptionSolution
INVALID_STATUSTransaction status doesn't allow this actionOnly pending transactions can be requeried

Rate Limit Errors (429)

CodeDescriptionSolution
RATE_LIMIT_EXCEEDEDToo many requestsWait and retry, check Retry-After header

Handling Errors in Code

javascript
// Generate external reference: 10-digit timestamp + 6 alphanumeric
function generateReference() {
  const timestamp = Math.floor(Date.now() / 1000);
  const chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  let suffix = "";
  for (let i = 0; i < 6; i++) {
    suffix += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return `${timestamp}${suffix}`;
}

async function makePurchase(productId, phoneNumber, amount) {
  try {
    const response = await fetch(
      "https://my.rizpay.app/api/partners/v1/purchases",
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${API_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          product_id: productId,
          phone_number: phoneNumber,
          amount: amount,
          external_reference: generateReference(),
        }),
      }
    );

    const data = await response.json();

    if (!response.ok) {
      // Match on error.code (status.code is the numeric HTTP status)
      switch (data.error?.code) {
        case "INSUFFICIENT_BALANCE":
          throw new Error("Please fund your account");
        case "INVALID_PHONE_NUMBER":
          throw new Error("Please enter a valid phone number");
        case "DUPLICATE_REFERENCE":
          throw new Error("This transaction was already processed");
        case "RATE_LIMIT_EXCEEDED":
          const retryAfter = response.headers.get("Retry-After");
          throw new Error(
            `Too many requests. Retry after ${retryAfter} seconds`
          );
        default:
          throw new Error(data.error?.message || "Request failed");
      }
    }

    return data.data;
  } catch (error) {
    console.error("Purchase failed:", error.message);
    throw error;
  }
}

Best Practices

  1. Always check the status code - Don't assume success
  2. Log error responses - Include the full response for debugging
  3. Handle rate limits gracefully - Use the Retry-After header
  4. Use unique references - Prevent duplicate transaction errors
  5. Verify before purchase - For electricity and cable TV, always verify first

Next Steps