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

Authentication

Every Gateway API request must be authenticated using HMAC-SHA256 request signing. There is no simple Bearer token for the gateway — every request must be signed with your API secret to prevent tampering and replay attacks.

API Keys

When your merchant account is provisioned, you receive two credentials:

CredentialFormatUsage
Key IDmk_<32 chars>Sent in X-Api-Key header on every request
Secretrandom stringUsed to sign requests — never sent directly

Never expose your API secret

The secret is used only to compute HMAC signatures on your server. It must never appear in browser code, mobile apps, or public repositories. Rotate it immediately via the admin panel if it is ever compromised.

Required Headers

Every Gateway API request must include these three headers:

HeaderValue
X-Api-KeyYour Key ID (mk_...)
X-Api-TimestampCurrent Unix timestamp in seconds (e.g. 1712345678)
X-Api-SignatureHMAC-SHA256 hex digest of the canonical string (see below)

HMAC Request Signing

The signature is computed over a canonical string that includes the timestamp, HTTP method, URL path, and raw request body. This ensures the entire request cannot be tampered with in transit.

Canonical String

{timestamp}.{METHOD}.{path}.{raw_body}

Signature Formula

HMAC-SHA256(secret, canonical_string)

timestamp — the value of X-Api-Timestamp (Unix seconds)

METHOD — uppercase HTTP verb (e.g. POST, GET)

path — URL path without host or query string (e.g. api/v1/gateway/payments)

raw_body — raw JSON body string, or empty string for GET requests

TIMESTAMP=$(date +%s)
METHOD="POST"
PATH="api/v1/gateway/payments"
BODY='{"order_id":"order_1234","amount":"25.00","currency":"USD","return_url":"https://yoursite.com/success","cancel_url":"https://yoursite.com/cancel"}'
KEY_ID="mk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
SECRET="your_api_secret"

CANONICAL="$TIMESTAMP.$METHOD.$PATH.$BODY"
SIGNATURE=$(echo -n "$CANONICAL" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')

curl -X POST https://wallet.e-mazad.store/api/v1/gateway/payments \
  -H "X-Api-Key: $KEY_ID" \
  -H "X-Api-Timestamp: $TIMESTAMP" \
  -H "X-Api-Signature: $SIGNATURE" \
  -H "Content-Type: application/json" \
  -d "$BODY"

90-second timestamp window

Mazad rejects requests where X-Api-Timestamp is more than 90 seconds old. Make sure your server clock is synchronized via NTP. This is a strict replay-attack prevention window — 5xx retries must regenerate a fresh timestamp and signature.

Idempotency Keys

All state-changing (POST) requests should include an Idempotency-Key header with a UUID v4 value. If you retry a request with the same key, Mazad will return the original response without processing the request again — preventing duplicate charges.

# Add Idempotency-Key to any POST request
curl -X POST https://wallet.e-mazad.store/api/v1/gateway/payments \
  -H "X-Api-Key: mk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \
  -H "X-Api-Timestamp: $TIMESTAMP" \
  -H "X-Api-Signature: $SIGNATURE" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -H "Content-Type: application/json" \
  -d '{"order_id":"order_1234","amount":"25.00","currency":"USD","return_url":"https://yoursite.com/success","cancel_url":"https://yoursite.com/cancel"}'

# Retrying with the same Idempotency-Key returns the original response — no duplicate payment.

Key lifecycle

Use the same Idempotency-Key when retrying a timed-out request — it is safe to retry. Use a new key for a genuinely new request. Sending the same key with a different body returns a IDEMPOTENCY_KEY_REUSED error.

Authentication Error Codes

CodeHTTPCause
HMAC_HEADERS_MISSING401One or more of X-Api-Key, X-Api-Signature, X-Api-Timestamp is absent.
HMAC_TIMESTAMP_EXPIRED401Timestamp is more than 90 seconds old. Regenerate timestamp and signature.
HMAC_KEY_INVALID401The X-Api-Key value does not exist or has been revoked.
HMAC_SIGNATURE_INVALID401Signature mismatch. Check canonical string format: timestamp.METHOD.path.body
MERCHANT_NOT_FOUND403API key exists but is not linked to a merchant account.
MERCHANT_NOT_APPROVED403Merchant account exists but is Pending, Rejected, or Suspended.
RATE_LIMIT_EXCEEDED429More than 60 requests/minute from this merchant. Check Retry-After header.