Moneybag

Error Codes

Complete reference for API error codes and their solutions

Error Codes Reference

Comprehensive guide to all error codes returned by the Moneybag API, including descriptions and solutions.


Error Response Format

All API errors follow a consistent format:

{
  "success": false,
  "error": {
    "code": "INVALID_API_KEY",
    "message": "The provided API key is invalid or expired",
    "details": {
      "field": "X-Merchant-API-Key",
      "provided": "sk_test_***"
    },
    "request_id": "req_1234567890",
    "documentation": "https://docs.moneybag.com.bd/errors/INVALID_API_KEY"
  }
}

HTTP Status Codes

Success Codes (2xx)

CodeStatusDescription
200OKRequest successful
201CreatedResource created successfully
202AcceptedRequest accepted for processing
204No ContentRequest successful, no content to return

Client Error Codes (4xx)

CodeStatusDescriptionCommon Causes
400Bad RequestInvalid request formatMalformed JSON, missing fields
401UnauthorizedAuthentication failedInvalid or missing API key
403ForbiddenAccess deniedIP not whitelisted, insufficient permissions
404Not FoundResource not foundInvalid endpoint or resource ID
405Method Not AllowedHTTP method not supportedUsing GET instead of POST
409ConflictRequest conflicts with current stateDuplicate transaction ID
422Unprocessable EntityValidation failedInvalid field values
429Too Many RequestsRate limit exceededToo many API calls

Server Error Codes (5xx)

CodeStatusDescriptionAction Required
500Internal Server ErrorServer error occurredRetry with exponential backoff
502Bad GatewayGateway errorTemporary issue, retry
503Service UnavailableService temporarily downCheck status page, retry later
504Gateway TimeoutRequest timeoutRetry with shorter timeout

Authentication Errors

INVALID_API_KEY

HTTP Status: 401

Description: The API key provided is invalid, expired, or malformed.

Solution:

# Correct format
curl -H "X-Merchant-API-Key: sk_live_abcd1234..."

# Common mistakes
curl -H "API-Key: sk_live_abcd1234..."  # Wrong header name
curl -H "Authorization: Bearer sk_live_abcd1234..."  # Wrong format

API_KEY_MISSING

HTTP Status: 401

Description: No API key was provided in the request.

Solution: Include the API key in request headers:

const headers = {
  'X-Merchant-API-Key': process.env.MONEYBAG_API_KEY,
  'Content-Type': 'application/json'
};

INVALID_ENVIRONMENT

HTTP Status: 403

Description: Using sandbox key with production API or vice versa.

Solution: Match your API key with the correct environment:

  • Sandbox: sk_test_* with sandbox.api.moneybag.com.bd
  • Production: sk_live_* with api.moneybag.com.bd

Validation Errors

VALIDATION_ERROR

HTTP Status: 422

Response Example:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "One or more fields failed validation",
    "details": {
      "amount": ["Amount must be greater than 10"],
      "email": ["Invalid email format"],
      "phone": ["Phone number must be 11 digits"]
    }
  }
}

Common Validation Error Codes

CodeFieldDescriptionSolution
AMOUNT_TOO_LOWamountAmount below minimum (10 BDT)Increase amount to at least 10
AMOUNT_TOO_HIGHamountAmount exceeds maximumCheck transaction limits
INVALID_CURRENCYcurrencyUnsupported currency codeUse "BDT" for Bangladesh Taka
INVALID_EMAILemailEmail format invalidProvide valid email address
INVALID_PHONEphonePhone format invalidUse format: +8801XXXXXXXXX
MISSING_REQUIRED_FIELDvariousRequired field not providedCheck API docs for required fields
INVALID_DATE_FORMATdate fieldsDate format incorrectUse ISO 8601: YYYY-MM-DD

Payment Errors

PAYMENT_FAILED

HTTP Status: 400

Sub-codes:

CodeDescriptionCustomer Action
INSUFFICIENT_FUNDSCustomer has insufficient balanceUse different payment method
CARD_DECLINEDCard issuer declined transactionContact bank or use different card
EXPIRED_CARDCard has expiredUse valid card
INVALID_CVVCVV code incorrectEnter correct CVV
FRAUD_SUSPECTEDTransaction flagged as suspiciousContact support
LIMIT_EXCEEDEDTransaction limit exceededReduce amount or contact bank

PAYMENT_TIMEOUT

HTTP Status: 408

Description: Payment session expired (30 minutes).

Solution: Create a new payment session:

// Implement session refresh
if (error.code === 'PAYMENT_TIMEOUT') {
    const newSession = await createPaymentSession(orderDetails);
    redirectToPayment(newSession.payment_url);
}

DUPLICATE_TRANSACTION

HTTP Status: 409

Description: Transaction with same order_id already exists.

Solution: Use unique order IDs or implement idempotency:

const order_id = `ORD_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;

Refund Errors

REFUND_EXCEEDED

HTTP Status: 400

Description: Refund amount exceeds original transaction amount.

Solution:

// Check refundable amount first
const transaction = await getTransaction(transactionId);
const refundableAmount = transaction.amount - transaction.refunded_amount;

if (refundAmount > refundableAmount) {
    throw new Error(`Maximum refundable: ${refundableAmount}`);
}

REFUND_WINDOW_EXPIRED

HTTP Status: 400

Description: Refund period (180 days) has expired.

Solution: Contact support for manual refund processing.

ALREADY_REFUNDED

HTTP Status: 409

Description: Transaction has already been fully refunded.

Solution: Check transaction status before attempting refund.


Webhook Errors

WEBHOOK_SIGNATURE_INVALID

HTTP Status: 401

Description: Webhook signature verification failed.

Common Causes:

  • Using wrong secret key
  • Modifying payload before verification
  • Encoding issues

Solution:

// Use raw payload for verification
$payload = file_get_contents('php://input');
// Don't use $_POST or json_decode before verification

WEBHOOK_DELIVERY_FAILED

Description: Webhook delivery to your endpoint failed.

Common Causes:

  • Endpoint returned non-200 status
  • Endpoint timeout (>30 seconds)
  • SSL certificate issues
  • Endpoint not publicly accessible

Rate Limiting Errors

RATE_LIMIT_EXCEEDED

HTTP Status: 429

Response Headers:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995200
Retry-After: 3600

Solution: Implement exponential backoff:

async function apiCallWithRetry(fn, maxRetries = 3) {
    for (let i = 0; i < maxRetries; i++) {
        try {
            return await fn();
        } catch (error) {
            if (error.status === 429) {
                const retryAfter = error.headers['retry-after'] || Math.pow(2, i);
                await sleep(retryAfter * 1000);
            } else {
                throw error;
            }
        }
    }
}

Business Logic Errors

MERCHANT_SUSPENDED

HTTP Status: 403

Description: Merchant account is suspended.

Action: Contact support at support@moneybag.com.bd

INSUFFICIENT_BALANCE

HTTP Status: 400

Description: Merchant account has insufficient balance for refunds.

Solution: Add funds to your merchant account via dashboard.

SERVICE_NOT_ENABLED

HTTP Status: 403

Description: Requested service not enabled for your account.

Solution: Contact sales to enable the service.


Integration Errors

INVALID_CALLBACK_URL

HTTP Status: 400

Description: Callback URLs are invalid or use HTTP in production.

Solution:

// Production requires HTTPS
const config = {
    success_url: 'https://yoursite.com/success',  // ✓ HTTPS
    cancel_url: 'http://yoursite.com/cancel',     // ✗ HTTP not allowed
    fail_url: 'https://localhost/fail'            // ✗ Localhost not allowed
};

INVALID_SIGNATURE

HTTP Status: 401

Description: Request signature verification failed.

Solution: Ensure proper signature generation:

const signature = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

System Errors

INTERNAL_SERVER_ERROR

HTTP Status: 500

Description: Unexpected server error occurred.

Response:

{
  "error": {
    "code": "INTERNAL_SERVER_ERROR",
    "message": "An unexpected error occurred",
    "request_id": "req_abc123",
    "support": "Please contact support with request_id"
  }
}

Action:

  1. Retry with exponential backoff
  2. If persistent, contact support with request_id

SERVICE_UNAVAILABLE

HTTP Status: 503

Description: Service temporarily unavailable for maintenance.

Action:

  1. Check status.moneybag.com.bd
  2. Subscribe to status updates
  3. Retry after maintenance window

Error Handling Best Practices

1. Comprehensive Error Handling

try {
    const response = await makeApiCall();
    return response.data;
} catch (error) {
    if (error.response) {
        // API returned error
        switch (error.response.status) {
            case 400:
                handleValidationError(error.response.data);
                break;
            case 401:
                refreshApiKey();
                break;
            case 429:
                await waitAndRetry(error);
                break;
            case 500:
                logErrorAndRetry(error);
                break;
            default:
                handleGenericError(error);
        }
    } else if (error.request) {
        // Network error
        handleNetworkError(error);
    } else {
        // Client error
        handleClientError(error);
    }
}

2. User-Friendly Error Messages

const userMessages = {
    'INSUFFICIENT_FUNDS': 'Your payment could not be processed due to insufficient funds.',
    'CARD_DECLINED': 'Your card was declined. Please try a different payment method.',
    'PAYMENT_TIMEOUT': 'Your payment session has expired. Please try again.',
    'RATE_LIMIT_EXCEEDED': 'Too many requests. Please wait a moment and try again.'
};

function getUserMessage(errorCode) {
    return userMessages[errorCode] || 'An error occurred. Please try again.';
}

3. Error Logging

function logError(error) {
    console.error({
        timestamp: new Date().toISOString(),
        request_id: error.request_id,
        error_code: error.code,
        message: error.message,
        details: error.details,
        stack: error.stack
    });
}

Testing Error Scenarios

Trigger Specific Errors in Sandbox

Test Card/AmountTriggered Error
4000000000000002CARD_DECLINED
4000000000000069EXPIRED_CARD
4000000000000127INVALID_CVV
Amount: 99999.00LIMIT_EXCEEDED
Amount: 5.00AMOUNT_TOO_LOW

Webhook Error Testing

# Trigger webhook failure
curl -X POST https://sandbox.api.moneybag.com.bd/api/v2/webhooks/test \
  -H "X-Merchant-API-Key: YOUR_KEY" \
  -d '{
    "event": "webhook.failed",
    "url": "https://yoursite.com/webhook"
  }'

Getting Help

If you encounter an error not listed here:

  1. Check the request_id in the error response
  2. Review the API documentation for the specific endpoint
  3. Contact support with:
    • Request ID
    • Error code and message
    • Request/response details
    • Timestamp

Support: support@moneybag.com.bd