Əsas məzmuna keç

Bayilər üçün

API sənədləri

Öz saytınızdan və ya panelinizdən ZTopup kataloqunu oxuyun, oyunçu hesabını yoxlayın və sifarişi birbaşa yaradın. Ödəniş bayi balansından çıxılır, təhvil avtomatikdir.

Başlanğıc

API bayi hesabınızın adından işləyir: gördüyünüz qiymətlər sizin bayi qiymətlərinizdir, sifarişlər sizin balansınızdan ödənilir. Açar hesabınıza bağlıdır — onu paylaşmayın, sızdığını düşünürsünüzsə dərhal bizə yazın.

1. API açarı alın

Bayi hesabınız təsdiqləndikdən sonra panelinizdən açar yaradılır. Açar bir dəfə göstərilir, saxlanmır — itirsəniz yenisini yaradın, köhnəsi dərhal etibarsız olur.

2. Hər sorğuya açarı əlavə edin

İstək
curl https://ztopup.store/api/v1/me \
  -H "X-API-Key: sizin_açarınız" \
  -H "Accept: application/json"

3. Balansı doldurun

Sifariş yaratmaq üçün balansınız kifayət etməlidir — API balansı özü doldurmur. Balans panelin Balansım bölməsindən artırılır; kart məlumatları orada göstərilir.

4. İlk sifariş

Ardıcıllıq həmişə eynidir: kataloqdan paket seçin, oyunçu hesabını yoxlayın, sifarişi yaradın, nəticəni webhook ilə və ya sorğu ilə izləyin.

Ümumi qaydalar

Ünvan və format

Bütün endpointlər https://ztopup.store/api/v1 altındadır və yalnız HTTPS qəbul edir. Sorğu və cavab gövdəsi JSON, kodlaşdırma UTF-8-dir.

Cavab qabığı

Hər cavab ok sahəsi ilə gəlir. Uğurlu cavabda məlumat data içindədir, xətada isə error.

Uğurlu cavab
{
  "ok": true,
  "data": { }
}

Məbləğlər

Bütün məbləğlər AZN və iki onluq işarə ilə, mətn kimi göndərilir ("1.91"). Sürüşən nöqtə xətası olmasın deyə rəqəm tipi işlədilmir.

Tarixlər

ISO 8601, Bakı vaxtı ilə: 2026-09-21T14:05:31+04:00.

Idempotensiya

Sifariş yaradan sorğuda Idempotency-Key başlığı məcburidir. Eyni açarla təkrar göndərilən sorğu yeni sifariş yaratmır — ilk sifarişin cavabını qaytarır. Şəbəkə kəsiləndə sorğunu təhlükəsiz təkrarlamağın yolu budur. Açar 24 saat saxlanır və hesabınıza aiddir.

Eyni açarla fərqli gövdə göndərsəniz sorğu 409 qaytarır — səhvən eyni açarın iki ayrı sifarişə yapışdırılması beləcə tutulur.

Səhifələmə

Siyahı qaytaran endpointlər page və per_page (ən çox 100, standart 25) qəbul edir. Cavabda meta olur.

meta
"meta": {
  "page": 1,
  "per_page": 25,
  "total": 134,
  "last_page": 6
}

Hesab və balans

GET /me Hesab məlumatı
Açarın hansı hesaba aid olduğunu, bayi səviyyənizi və cari balansı qaytarır. Açarı yoxlamaq üçün ən ucuz sorğudur.
Cavab
{
  "ok": true,
  "data": {
    "id": 42,
    "name": "Nümunə MMC",
    "dealer_tier": "Gümüş",
    "balance": "184.50",
    "currency": "AZN"
  }
}
GET /balance Yalnız balans
Sifarişdən əvvəl balansı yoxlamaq üçün yüngül variant.
Cavab
{
  "ok": true,
  "data": { "balance": "184.50", "currency": "AZN" }
}

Kataloq

Kataloq iki səviyyəlidir: məhsul (oyun və region, məsələn «Free Fire Almaz — Azərbaycan») və onun altındakı paketlər. Sifariş həmişə paketə verilir.

GET /products Məhsul siyahısı
Yalnız satışda olan məhsullar qayıdır. category ilə süzgəcləyə bilərsiniz.
Cavab
{
  "ok": true,
  "data": [
    {
      "id": 1,
      "slug": "free-fire-almaz-azerbaycan",
      "name": "Free Fire Almaz — Azərbaycan",
      "category": "Free Fire",
      "region": "AZ",
      "requires_player_id": true,
      "player_id_label": "Player ID"
    }
  ],
  "meta": { "page": 1, "per_page": 25, "total": 18, "last_page": 1 }
}
GET /products/{id}/packages Paketlər
Qiymətlər sizin bayi qiymətinizdir. list_price pərakəndə qiymətdir — öz saytınızda fərqi göstərmək istəsəniz işinizə yarayar.
Cavab
{
  "ok": true,
  "data": [
    {
      "id": 1,
      "name": "110 Almaz",
      "price": "1.64",
      "list_price": "1.91",
      "currency": "AZN",
      "available": true,
      "stock": null
    }
  ]
}

stock dəyəri null olanda limit yoxdur. available false olan paketə sifariş verilə bilməz — paketin özü bağlıdır və ya təchizat müvəqqəti dayanıb.

Oyunçu yoxlaması

requires_player_id olan məhsullarda sifarişdən əvvəl oyunçu hesabı yoxlanmalıdır. Yoxlama sizə oyunçunun adını qaytarır və player_token verir; sifariş həmin token olmadan qəbul edilmir.

Səbəbi sadədir: səhv Player ID-yə yüklənmiş almaz geri qayıtmır. Token 5 dəqiqə etibarlıdır və yalnız yoxlandığı paket + Player ID cütü üçün işləyir.

POST /players/validate Oyunçunu yoxla
İstək
curl -X POST https://ztopup.store/api/v1/players/validate \
  -H "X-API-Key: sizin_açarınız" \
  -H "Content-Type: application/json" \
  -d '{
    "package_id": 1,
    "player_id": "5012345678"
  }'
Cavab
{
  "ok": true,
  "data": {
    "valid": true,
    "player_name": "OyuncuAZ",
    "player_token": "pv_9f2c1a...",
    "expires_at": "2026-09-21T14:10:31+04:00"
  }
}

Bəzi oyunlarda ad sorğulanmır; belə hallarda player_name null gəlir, token yenə verilir. Yanlış ID-də cavab 422 olur və sifariş yaradılmır — pul tutulmur.

Sifarişlər

POST /orders Sifariş yarat
Məbləğ balansınızdan dərhal çıxılır və sifariş paid statusu ilə açılır. Balans çatmırsa sifariş ümumiyyətlə yaradılmır.
İstək
curl -X POST https://ztopup.store/api/v1/orders \
  -H "X-API-Key: sizin_açarınız" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7b1f0c94-2d3a-4e55-9f10-8c2b6de41a77" \
  -d '{
    "package_id": 1,
    "quantity": 1,
    "player_id": "5012345678",
    "player_token": "pv_9f2c1a...",
    "reference": "sizin-sifaris-1042"
  }'
Cavab
{
  "ok": true,
  "data": {
    "id": "ord_8412",
    "order_no": "GX260921ABCD",
    "status": "paid",
    "reference": "sizin-sifaris-1042",
    "package": { "id": 1, "name": "110 Almaz" },
    "player_id": "5012345678",
    "player_name": "OyuncuAZ",
    "quantity": 1,
    "unit_price": "1.64",
    "total": "1.64",
    "currency": "AZN",
    "balance_after": "182.86",
    "items": [
      { "id": "itm_9103", "fulfillment_status": "pending", "delivered_at": null }
    ],
    "created_at": "2026-09-21T14:05:31+04:00"
  }
}

reference sizin öz sifariş nömrənizdir — istəyə bağlıdır, cavablarda və webhook-da geri qaytarılır, hesablaşmanı asanlaşdırır. Idempotensiya üçün isə reference yox, Idempotency-Key istifadə olunur.

GET /orders/{id} Sifarişin vəziyyəti
Həm ord_8412, həm də GX260921ABCD qəbul edilir.
GET /orders Sifariş siyahısı
status, from, to və reference ilə süzgəclənir. Yeni sifariş əvvəldə gəlir.

Təhvil ani deyil

paid ödənişin alındığı deməkdir, məhsulun oyun hesabına düşdüyü yox. Təhvil adətən saniyələr çəkir, amma təchizatçı gecikəndə uzana bilər. Sifarişi dövrə vurub sorğulamaq əvəzinə webhook-a abunə olun; sorğu lazımdırsa 10 saniyədən tez-tez etməyin.

Webhook

Sifariş statusu dəyişəndə göstərdiyiniz ünvana POST göndərilir. Ünvanı və imza açarını paneldən təyin edirsiniz.

Gövdə
{
  "event": "order.completed",
  "sent_at": "2026-09-21T14:05:47+04:00",
  "data": {
    "id": "ord_8412",
    "order_no": "GX260921ABCD",
    "reference": "sizin-sifaris-1042",
    "status": "completed",
    "items": [
      { "id": "itm_9103", "fulfillment_status": "delivered", "delivered_at": "2026-09-21T14:05:47+04:00" }
    ]
  }
}

Hadisələr

HadisəNə vaxt
order.completedBütün sətirlər təhvil verildi
order.failedTəhvil mümkün olmadı, məbləğ balansa qaytarıldı
order.cancelledSifariş ləğv edildi

İmzanı yoxlayın

Hər sorğuda X-ZTopup-Signature başlığı olur: gövdənin imza açarınızla hesablanmış HMAC-SHA256 dəyəri (hex). Gövdəni JSON-a çevirmədən əvvəl, xam haldaca yoxlayın — yenidən kodlaşdırma imzanı pozur.

PHP
$raw = file_get_contents('php://input');
$expected = hash_hmac('sha256', $raw, $secret);

if (! hash_equals($expected, $_SERVER['HTTP_X_ZTOPUP_SIGNATURE'] ?? '')) {
    http_response_code(401);
    exit;
}

Təkrar göndəriş olur

Cavabınız 2xx olmasa, sorğu artan aralıqlarla 24 saat ərzində təkrarlanır. Ona görə emalınız idempotent olmalıdır: eyni id ikinci dəfə gələndə heç nə dəyişməməlidir. Uzun iş görməyin — əvvəlcə 200 qaytarın, sonra növbəyə salın.

Sorğu limitləri

QrupEndpointlərDəqiqədə
Kataloq/products, /products/{id}/packages120
Hesab/me, /balance60
Oyunçu yoxlaması/players/validate30
Sifariş yaratmaPOST /orders30
Sifariş oxumaGET /orders, GET /orders/{id}60

Limit aşılanda cavab 429 olur və Retry-After başlığında neçə saniyə gözləməli olduğunuz yazılır. Qalan haqqınız hər cavabda X-RateLimit-Remaining ilə gəlir.

Statuslar və xətalar

Sifariş statusu

DəyərMənası
paidÖdənildi, təhvil gözlənilir
completedBütün sətirlər təhvil verildi
cancelledLəğv edildi, məbləğ balansa qaytarıldı

Sətir statusu

DəyərMənası
pendingTəhvil davam edir
deliveredOyun hesabına yükləndi
failedTəhvil mümkün olmadı; məbləğ balansa qaytarılır

HTTP kodları

KodMənası
200Uğurlu
201Sifariş yaradıldı
401Açar yoxdur və ya yanlışdır
402Balans kifayət etmir
404Tapılmadı
409Eyni idempotensiya açarı, fərqli gövdə
422Məlumat düzgün deyil (Player ID, paket, miqdar)
429Limit aşıldı
500Bizim tərəfdə xəta — sorğunu təkrarlaya bilərsiniz

Xəta gövdəsi

Nümunə
{
  "ok": false,
  "error": {
    "code": "insufficient_balance",
    "message": "Balans kifayət etmir.",
    "details": { "required": "1.64", "balance": "0.80" }
  }
}

code sabitdir və proqramla yoxlanmaq üçündür; message insan üçündür və dəyişə bilər — şərtlərinizi mesaja görə yazmayın.

Vaxt aşımı uğursuzluq deyil

POST /orders cavabsız qalsa, sifariş yaranmış ola bilər. Yenidən yaratmayın — eyni Idempotency-Key ilə təkrar göndərin, cavab ilk sifarişi qaytaracaq.

Sual var?

İnteqrasiya zamanı ilişdiyiniz yer olsa yazın — sorğu və cavab nümunəsi ilə birlikdə göndərsəniz daha tez kömək edə bilərik.

Tez-tez verilən suallar