Sandbox mode — Use https://wallet.e-mazad.store/api/v1 as your base URL
Payment Gateway

Payments

Retrieve individual payment details or list payments with filters. Use the polling pattern with exponential backoff for real-time status checks.

Get a payment

GET/gateway/payments/{id}

Retrieve the full details of a payment including status, amounts, FX details, and timestamps. Use this to poll for payment completion.

Path Parameters

NameTypeRequiredDescription
idstringrequiredThe payment ID (pay_...) returned when the checkout session was completed.
curl -X GET https://wallet.e-mazad.store/api/v1/gateway/payments/pay_x1y2z3 \
  -H "X-Api-Key: mk_your_key_id"   -H "X-Api-Timestamp: $TIMESTAMP"   -H "X-Api-Signature: $SIGNATURE"

Response

{
  "success": true,
  "data": {
    "id": "pay_x1y2z3",
    "session_id": "cs_9f8e7d6c5b4a",
    "status": "completed",
    "amount": 25000,
    "currency": "IQD",
    "captured_amount": 25000,
    "refunded_amount": 0,
    "user_id": "mzd_usr_9f8e7d6c5b4a",
    "external_user_id": "usr_12345",
    "description": "Order #1234 - Premium Widget",
    "reference": "order_1234",
    "capture_mode": "automatic",
    "fx_details": null,
    "metadata": {
      "order_id": "1234",
      "sku": "widget-premium"
    },
    "authorized_at": "2026-03-20T14:31:00Z",
    "captured_at": "2026-03-20T14:31:00Z",
    "created_at": "2026-03-20T14:30:00Z",
    "updated_at": "2026-03-20T14:31:00Z"
  }
}

Status values

StatusTerminal?Description
createdNoPayment created. Checkout URL has been sent to the customer. Awaiting payment.
reservedNoCustomer paid. Funds are held in escrow. Call /capture or /void to proceed.
completedYes*Funds captured and settled to merchant wallet. *Can still be refunded.
cancelledYesVoided before capture. Funds returned to customer. No settlement.
refundedYesFully refunded after capture. Funds returned to customer.
expiredYesCheckout expired (default: 30 min) before customer completed payment.

List payments

GET/gateway/payments

List payments with optional filters. Returns paginated results sorted by creation date (newest first).

Query Parameters

NameTypeRequiredDescription
statusstringoptionalFilter by status: created, reserved, completed, cancelled, refunded, expired.
user_idstringoptionalFilter by mazad_user_id or external_id.
referencestringoptionalFilter by your reference ID (exact match).
currencystringoptionalFilter by currency code (e.g., IQD, USD).
fromstringoptionalStart date in ISO 8601 (e.g., 2026-03-01T00:00:00Z).
tostringoptionalEnd date in ISO 8601.
pageintegeroptionalPage number. Defaults to 1.
per_pageintegeroptionalResults per page. Max 100. Defaults to 20.
curl -X GET "https://wallet.e-mazad.store/api/v1/gateway/payments?status=completed&currency=IQD&per_page=10" \
  -H "X-Api-Key: mk_your_key_id"   -H "X-Api-Timestamp: $TIMESTAMP"   -H "X-Api-Signature: $SIGNATURE"

List response

{
  "success": true,
  "data": {
    "payments": [
      {
        "id": "pay_x1y2z3",
        "status": "completed",
        "amount": 25000,
        "currency": "IQD",
        "reference": "order_1234",
        "user_id": "mzd_usr_9f8e7d6c5b4a",
        "created_at": "2026-03-20T14:30:00Z"
      }
    ],
    "pagination": {
      "page": 1,
      "per_page": 10,
      "total": 47,
      "total_pages": 5
    }
  }
}

Polling with exponential backoff

If you cannot use webhooks, poll the payment status with exponential backoff. Start at 1 second, double each attempt, cap at 30 seconds, and stop after 10 attempts.

async function pollPayment(paymentId, maxAttempts = 10) {
  let delay = 1000; // Start at 1 second

  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    const response = await fetch(
      `https://wallet.e-mazad.store/api/v1/gateway/payments/${paymentId}`,
      {
        headers: { 'Authorization': 'Bearer sk_sandbox_abc123' },
      }
    );

    const { data } = await response.json();
    const terminal = ['completed', 'voided', 'refunded', 'failed', 'expired'];

    if (terminal.includes(data.status)) {
      return data; // Payment reached final state
    }

    console.log(`Attempt ${attempt}: status=${data.status}, retrying in ${delay}ms`);
    await new Promise(resolve => setTimeout(resolve, delay));
    delay = Math.min(delay * 2, 30000); // Double, cap at 30s
  }

  throw new Error('Payment did not reach terminal state');
}

// Usage
const payment = await pollPayment('pay_x1y2z3');
console.log(`Final status: ${payment.status}`);

Prefer webhooks

Webhooks are more efficient than polling. Register a webhook URL in your dashboard and listen for payment.completed, payment.failed, and other events.