AZA-ZPayA-ZPay bank-transfer API

Authentication

A-ZPay’s public integration authentication is the signed partner API. Partner portal login and player handoff flows are not machine-to-machine API routes; casino integrations should only sign the partner endpoints documented here.

Partner API signature

Every partner API request must include:

X-Api-Key: pk_live_xxx
X-Timestamp: 1778940000
X-Signature: <hex hmac>

Each casino receives three integration values in its partner portal:

  • apiKey: sent as X-Api-Key.
  • apiSecret: HMAC key.
  • hashSecret: appended as the final canonical-string segment.

The signature is HMAC-SHA256 over:

<timestamp>.<METHOD>.<path>.<raw_body>.<hashSecret>

For GET requests, the raw body is an empty string, so the canonical string still ends with .<hashSecret>.

Example canonical string:

1778940000.POST./v1/deposits.{"amount":"100.00"}.hs_live_xxx

Legacy signatures that omit hashSecret are rejected.

Reusable request signer
import crypto from 'node:crypto';

const apiKey = process.env.AZPAY_API_KEY;
const apiSecret = process.env.AZPAY_API_SECRET;
const hashSecret = process.env.AZPAY_HASH_SECRET;

export function signAZPayRequest(method, path, rawBody = '') {
const timestamp = Math.floor(Date.now() / 1000).toString();
const canonical = [timestamp, method.toUpperCase(), path, rawBody, hashSecret].join('.');
const signature = crypto.createHmac('sha256', apiSecret).update(canonical).digest('hex');

return {
  'content-type': 'application/json',
  'x-api-key': apiKey,
  'x-timestamp': timestamp,
  'x-signature': signature,
};
}

const body = JSON.stringify({ amount: '100.00', currency: 'TRY' });
const headers = signAZPayRequest('POST', '/v1/deposits', body);
<?php
function signAZPayRequest(string $method, string $path, string $rawBody = ''): array {
  $apiKey = getenv('AZPAY_API_KEY');
  $apiSecret = getenv('AZPAY_API_SECRET');
  $hashSecret = getenv('AZPAY_HASH_SECRET');
  $timestamp = (string) time();
  $canonical = implode('.', [$timestamp, strtoupper($method), $path, $rawBody, $hashSecret]);
  $signature = hash_hmac('sha256', $canonical, $apiSecret);

  return [
      'content-type: application/json',
      'x-api-key: ' . $apiKey,
      'x-timestamp: ' . $timestamp,
      'x-signature: ' . $signature,
  ];
}

$body = json_encode(['amount' => '100.00', 'currency' => 'TRY'], JSON_UNESCAPED_SLASHES);
$headers = signAZPayRequest('POST', '/v1/deposits', $body);

Timestamp skew

X-Timestamp is a Unix timestamp in seconds. Requests outside the allowed clock-skew window are rejected, so partner servers should keep NTP time synchronized.

Signed GET request example
const path = '/partner/balance';
const response = await fetch('https://api.azpay.example' + path, {
method: 'GET',
headers: signAZPayRequest('GET', path, ''),
});

if (!response.ok) {
throw new Error('A-ZPay rejected request: ' + response.status);
}

const balance = await response.json();
<?php
$path = '/partner/balance';
$ch = curl_init('https://api.azpay.example' . $path);
curl_setopt_array($ch, [
  CURLOPT_HTTPHEADER => signAZPayRequest('GET', $path, ''),
  CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status < 200 || $status >= 300) {
  throw new RuntimeException('A-ZPay rejected request: ' . $status);
}
$balance = json_decode($response, true);