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

json
{
  "status": {
    "code": "ERROR_CODE",
    "message": "Human-readable error description"
  },
  "data": null
}

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 is not availableTry a different product or retry later
VERIFICATION_REQUIREDMust verify meter/decoder firstCall /purchases/verify before purchasing
VERIFICATION_FAILEDMeter/decoder verification failedCheck the meter/decoder number

Provider Errors (400)

CodeDescriptionSolution
PROVIDER_ERRORUpstream provider errorRetry the request or contact support
PROVIDER_TIMEOUTProvider request timed outRetry the request
PROVIDER_UNAVAILABLEProvider service is downRetry later

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) {
      // Handle specific error codes
      switch (data.status.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.status.message);
      }
    }

    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