Skip to main content
Track payment outcomes via Webhooks (recommended) or by polling GET /api/v1/payments/{id}.

Status values

StatusTerminalDescription
pendingNoPayment created; waiting for customer (USSD, QR, card checkout)
processingNoRare/legacy intermediate state — mobile payments normally go straight from pending to a terminal status
completedYesPayment successful
failedYesPayment failed
cancelledYesCancelled before completion
expiredYesPayment not completed within ~30 minutes of creation
partially_refundedSet after completion when a partial refund is applied
refundedSet after completion when the full amount has been refunded
Payments that are not completed expire roughly 30 minutes after creation (occasionally slightly later), transitioning to expired with webhook and callback delivery.

Webhook events per status

Webhooks fire on status transitions only — there is no webhook when the payment is created (pending is the initial state, not a transition):
Status reachedWebhook eventCallback sent?
processing (rare)payment.processingNo
completedpayment.completedYes
failedpayment.failedYes
cancelledpayment.cancelledYes
expiredpayment.expiredYes
No webhook is currently emitted for the refund statuses (partially_refunded, refunded).
Payload shapes and field reference: Webhook payloads. Processing guidance: Handle events.

Poll payment status

GET /api/v1/payments/{id} returns the current recorded status instantly — it is safe to poll every 2–5 seconds while the customer is on the USSD prompt.

API reference

GET /api/v1/payments/
curl -X GET "https://meet.briq.tz/api/v1/payments/PAYMENT_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"
Example response (fields may vary by payment type):
{
  "status": "success",
  "code": 200,
  "message": "Payment retrieved successfully",
  "data": {
    "id": "f5d238bd-f8ab-4379-9832-0f1ce6d65cbe",
    "reference": "ORDER_123",
    "external_id": "EXT-20260609-001",
    "amount": 5000,
    "margin_amount": 150,
    "total_amount": 5000,
    "currency": "TZS",
    "type": "mobile",
    "status": "pending",
    "phone": "255712345678",
    "network": "vodacom",
    "payment_url": "",
    "qr_code": "",
    "created_at": "2026-06-09T12:53:50Z",
    "completed_at": null
  }
}
reference is always your merchant reference; external_id is PayGrid’s upstream payment identifier — quote it in support requests.

Force status refresh

POST /api/v1/payments/{id}/refresh performs a live status check and updates the payment (also triggers webhooks if the status changed):
curl -X POST "https://meet.briq.tz/api/v1/payments/PAYMENT_ID/refresh" \
  -H "Authorization: Bearer YOUR_API_KEY"
Use sparingly — each call performs a live upstream check and returns 502 PROVIDER_ERROR if that check is temporarily unavailable. For routine polling prefer GET; PayGrid also refreshes pending payments automatically.

List payments

GET /api/v1/payments — query params page (default 1) and per_page (default 10, max 100; invalid values fall back to the defaults). Results are ordered newest first. Responses include a meta block:
{
  "meta": {
    "current_page": 1,
    "per_page": 10,
    "total": 42,
    "total_pages": 5
  }
}
curl -X GET "https://meet.briq.tz/api/v1/payments?page=1&per_page=10" \
  -H "Authorization: Bearer YOUR_API_KEY"

API reference

GET /api/v1/payments

Integration pattern

POST /api/v1/payments  →  status: pending

Customer pays (USSD / QR / card)

PayGrid confirms the payment  →  status transition  →  your webhook_url

payment.completed  →  fulfill order
If your server was down:
GET /api/v1/payments/{id}  →  check current status