D
Dehuyz Gateway
Docs Polling

Polling

Polling = lo cek status invoice secara berkala via GET /api/v1/invoices/{id}. Cocok kalau:

  • Lo gak punya endpoint publik (mis. ngerjain di laptop lokal, di belakang NAT)
  • Mau backup dari webhook (defense in depth)
  • Server lo sering crash / restart, takut webhook lost

Endpoint

curl https://gateway.dehuyz.example.com/api/v1/invoices/a1b2c3d4 \
  -H "Authorization: Bearer sk_live_xxx"

Response:

{
  "invoice_id": "a1b2c3d4e5f67890",
  "external_id": "order-001",
  "status": "paid",
  "amount": 50000,
  "paid_at": "2026-05-22T12:05:30+00:00",
  "qr_string": "...",
  "qr_image": "...",
  "metadata": {}
}

Pattern: polling sederhana

import httpx, time

API = "https://gateway.dehuyz.example.com"
KEY = "sk_live_xxx"

def wait_for_payment(invoice_id: str, max_wait: int = 300):
    """Poll invoice tiap 3 detik sampai paid/expired."""
    headers = {"Authorization": f"Bearer {KEY}"}
    deadline = time.time() + max_wait

    while time.time() < deadline:
        r = httpx.get(f"{API}/api/v1/invoices/{invoice_id}", headers=headers)
        r.raise_for_status()
        status = r.json()["status"]

        if status == "paid":
            return "paid"
        elif status in ("expired", "cancelled", "failed"):
            return status

        time.sleep(3)

    return "timeout"

Pattern: jangan hammer

Jangan polling tiap 100ms. Server lo gak butuh sub-second update — pembayaran QRIS minimum delay 1-2 detik dari sisi BRI poll lo.

Recommended interval: 2-5 detik per invoice aktif.

Stop polling setelah expires_at invoice — gak akan ada perubahan setelahnya.

Backoff kalau dapat error 500/503: tunggu 5-10 detik sebelum retry.

Pattern: bulk polling

Kalau lo punya banyak invoice pending bareng (mis. ada 20 customer di kasir), jangan polling tiap invoice satu-satu — saat ini sistem belum support batch endpoint, jadi lo akan hit rate limit (60 req/min default).

Solusi:

  • Gunakan webhook (lebih efisien)
  • Atau prioritize: hanya polling invoice yang paling baru aktif

Phase 6+ akan tambah GET /api/v1/invoices?status=pending (list) supaya 1 call cek banyak.

Polling vs Webhook — kapan pakai apa?

Kondisi Polling Webhook
Lo gak punya public endpoint
Latensi notifikasi penting (<1s)
Cuma <10 invoice/hari ✅ OK ✅ OK
100+ invoice/jam ❌ kena rate limit
Server lo sering restart / unstable ✅ (state di gateway) ❌ butuh outbox di sisi lo
Mau stack-bersih, no infra public

Best practice: pakai keduanya. Webhook sebagai primary, polling sebagai fallback (cek tiap N detik untuk invoice yang lebih dari T detik tanpa webhook fired).

Rate limits

  • Default: 60 req/min per merchant (lewat header tunggal Authorization).
  • Limit terpisah per IP: 5 req/min untuk endpoint signup/login.
  • Hit rate limit -> response 429 dengan header Retry-After: <seconds>.
r = httpx.get(...)
if r.status_code == 429:
    retry_after = int(r.headers.get("retry-after", 60))
    time.sleep(retry_after)