Developers

Three ways to accept payments — from a ready-made link with no code at all to a full API integration with webhooks.

01

Payment link

Created in the dashboard. Good for messengers, invoices and a QR code at the counter.

No code
02

Ready-made module

Integration with InSales and other platforms: the payment method appears right in the shop basket.

Set up in an hour
03

REST API

Create a payment from your server, use a ready payment page on our domain or a form right on your site, charge saved cards automatically, and get the result as a webhook signed with HMAC-SHA256.

Full control

What the integration looks like

Your server creates a payment and gets a link to send the buyer to. When the payment finishes, we call your webhook URL and sign the call. Keys are issued in the merchant cabinet, section “API and webhooks”.

Creating a paymentPOST /api/v2/payments
curl -X POST https://exezine.az/api/v2/payments \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1024-try-1" \
  -d '{
    "amount": 4990,
    "currency": "AZN",
    "order_id": "1024",
    "description": "Order #1024",
    "customer": { "email": "client@example.com" },
    "return_url": "https://your-site.az/thanks"
  }'
Response201 Created
{
  "id": "EXZ-20260922-1FA5E8A416",
  "object": "payment",
  "status": "pending",
  "amount": 4990,
  "currency": "AZN",
  "order_id": "1024",
  "checkout_url": "https://exezine.az/checkout/EXZ-20260922-1FA5E8A416",
  "created_at": "2026-09-22T20:15:00+04:00"
}
Result notificationPOST /your-webhook
X-Exezine-Event: payment.succeeded
X-Exezine-Event-Id: evt_9f1c2b3a4d5e
X-Exezine-Signature: t=1758560100,v1=<HMAC-SHA256>

{
  "id": "evt_9f1c2b3a4d5e",
  "type": "payment.succeeded",
  "livemode": true,
  "data": { "object": {
    "id": "EXZ-20260922-1FA5E8A416",
    "status": "succeeded",
    "amount": 4990,
    "currency": "AZN",
    "order_id": "1024"
  } }
}
Verifying the webhook signaturePHP
$body = file_get_contents('php://input');
[$t, $v1] = sscanf($_SERVER['HTTP_X_EXEZINE_SIGNATURE'], 't=%d,v1=%s');
$ok = hash_equals(hash_hmac('sha256', $t . '.' . $body, $secret), $v1)
      && abs(time() - $t) < 300;   // the signature is valid for 5 minutes
Payment form on your siteHTML
<div id="pay"></div>
<script src="https://exezine.az/assets/js/exezine-checkout.js?v=2"></script>
<script>
  ExezineCheckout.mount('#pay', {
    url: payment.checkout_url,
    onSuccess: function (p) { location.href = '/thanks'; }
  });
</script>

Subscriptions and automatic charges

The customer pays once on our page and saves the card — after that you charge it yourself, without the payment page: subscriptions, autopay, one-click payments. Neither you nor we see the card number: you only get a pm_… identifier and the card mask. Enabled on request.

First payment: the card is savedPOST /api/v2/payments
{
  "amount": 4990,
  "order_id": "sub-77-1",
  "save_payment_method": true,
  "customer": { "id": "user-77", "email": "client@example.com" },
  "return_url": "https://your-site.az/thanks"
}

→ payment.succeeded: "payment_method": { "id": "pm_3f9a1c7e5b2d4f6a8c0e1b3d",
                       "card": { "brand": "visa", "last4": "4242", "exp_month": 7, "exp_year": 2030 } }
Then — an automatic charge without the customerPOST /api/v2/payments
curl -X POST https://exezine.az/api/v2/payments \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: sub-77-2026-11" \
  -d '{
    "amount": 4990,
    "order_id": "sub-77-2026-11",
    "description": "Subscription, November",
    "payment_method": "pm_3f9a1c7e5b2d4f6a8c0e1b3d",
    "customer": { "id": "user-77" }
  }'

→ { "id": "EXZ-20261101-5C2E9A0B17", "status": "succeeded", "initiator": "merchant", … }

What else the API does

  • Full and partial refunds in one request — protected against double refunds.
  • Cancel an unpaid payment: the payment link stops working at once and the payment.canceled webhook arrives.
  • A custom payment deadline per payment — from 5 minutes to 24 hours; payment.expired arrives a few minutes after it.
  • Double-payment protection: a second payment for an already paid order number is not created.
  • A test key and a separate URL for test webhooks with its own secret — check your integration without touching production.
  • Payment links via the API and an embedded payment form right on your site.

The full specification is available as OpenAPI 3.1 — import it into Postman or Insomnia.

Full documentation

A reference for every endpoint: creating payments, statuses, refunds and cancellation, saved cards and automatic charges, payment links, webhooks with signature verification and the embedded form. You can send the link to your developer — no account is needed for it.

Integration security

  • The API key is sent in the Authorization header only — never in the page URL.
  • Every webhook is signed with HMAC-SHA256: verify the signature before changing an order status.
  • Treat a webhook as a possible duplicate: remember the event id (evt_…) and simply acknowledge repeats with 200.
  • Card data never passes through your server — it is captured on the bank page.
  • A saved card is an encrypted bank token on our side — the card number is stored nowhere. A card is removed with one request and can no longer be charged after that.

Need the full specification or sandbox access? Write to support@exezine.az and we will send the documentation and test keys.