Infinity Africa

API Reference

Dynamic QR API

Generate a scannable QR code for a specific amount — no customer phone number required. Good for in-person checkouts, printed receipts, or a payment screen a customer scans with any mobile money app.

Endpoint

POST/v1/collections/dynamic-qr

Generate a Dynamic QR collection.

API key or dashboard

Authentication

Call this endpoint from your own backend with an API key that has the collections:write scope, or from the Merchant Portal dashboard (signed-in session). Generate a key on the Merchant Portal — see API Key Authentication.

bash — cURL
curl -X POST https://api.infinityafrica.net/v1/collections/dynamic-qr \
  -H "Authorization: Bearer inf_live_xxxxxxxxxxxxx" \
  -H "Idempotency-Key: 6f1e2a3b-..." \
  -H "Content-Type: application/json" \
  -d '{
    "merchant_id": "5c1f0b2a-3e21-4b9a-9c33-2f6a1d0e8b71",
    "amount": "15000.00",
    "currency": "TZS",
    "merchant_reference": "ORDER-4821"
  }'

Response

Unlike a push collection, no customer_phone is required or returned. The response includes a qr_payload string — render it as a QR code with any client-side QR library — and a qr_expires_at timestamp.

json — 202 Accepted
{
  "success": true,
  "data": {
    "id": "2d4f8a91-...",
    "merchant_id": "5c1f0b2a-3e21-4b9a-9c33-2f6a1d0e8b71",
    "method": "DYNAMIC_QR",
    "amount": "15000.00",
    "currency": "TZS",
    "status": "processing",
    "qr_payload": "selcompay://qr?ref=MOCK-SELCOM-7C1E&amount=15000&currency=TZS",
    "qr_expires_at": "2026-08-14T09:05:00Z",
    "qr_image_url": null,
    "expires_at": "2026-08-14T09:05:00Z",
    "message": "Scan the QR code with a mobile money app to complete payment.",
    "provider": "mock_selcom",
    "provider_reference": "MOCK-SELCOM-7C1E",
    "transaction_reference": "TXN-...",
    "created_at": "2026-08-14T09:00:00Z"
  }
}

qr_image_url is always null today — no server-rendered QR image is generated yet, so render qr_payload client-side instead. expires_at is the same value as qr_expires_at, shared with the push endpoints' response shape.

Resolving a scan

A Dynamic QR collection starts as processing and resolves once the customer scans and confirms on their end. Listen for collection.success / collection.failed, or poll Transaction Status by reference. The code itself expires at qr_expires_at — generate a fresh one if the customer doesn't scan in time.

info

Regenerate on expiry, don't reuse an old QR

A scanned-but-expired code will be rejected by the customer's wallet app. If qr_expires_at has passed, call this endpoint again for a new code rather than re-displaying the old one.