Fair Usage & Best Practice Guide
Fiuu Payment Gateway – Status Inquiry & Refund Inquiry API
Executive Summary
- The primary mechanism for final payment status should be webhooks or passive notifications from the Payment Gateway (PG) — this is recommended for reliability.
- Requery is a backup method — use it only when a transaction remains in a pending or unknown state after a reasonable waiting period.
- Bulk requery cadence: Perform once every 30 minutes, and only for transactions marked as pending or unknown.
- Always respect API-specific limits, performance classifications, and data windows to avoid throttling or service blocks.
- Excessive or rapid API calls may be blocked without prior notice.
- No results will be returned beyond the data range supported by each API.
General Principle
The Status Inquiry API serves as a backup method to confirm payment or refund outcomes. It should not be used as the primary mechanism for tracking transactions.
Merchants must first rely on Fiuu’s push notification endpoints (via 3-endpoint integration) to receive real-time transaction updates.

Usage Restrictions
- Do NOT trigger a status inquiry immediately after submitting a payment or refund request.
- Do NOT continue querying once the transaction status has been successfully retrieved.
- AVOID looping inquiry calls at short intervals — this may result in rate-limit blocking.
- Excessive API calls from the same source IP may be blocked with an HTTP 429 error for 60 minutes, without prior notice.
Best Practices
✅ Leverage Push Notifications
- Always integrate all three notification endpoints to receive automatic status updates.
- Use the status inquiry API only if a notification is not received within a reasonable timeframe.
⏳ Backoff Strategy
- Apply a progressive retry interval (e.g., retry after 5 minutes → 15 minutes → 30 minutes).
- For transactions with a pending or unknown status, retry no more than once every 30 minutes.
🛑 Stop Once Confirmed
- Once a final status is obtained (Success, Failed, or Refunded), stop further inquiries.
🔍 Use Appropriate API Type
- Select the correct inquiry API based on your business needs (e.g., by Transaction ID, Order ID, or Batch).
- Respect the API’s rate limits and data range (e.g., 30 days, 180 days).
Consequences of Abuse
- HTTP 429 – Too Many Requests: This error is returned when the rate limit is exceeded.
- Automatic IP Blocking: The offending IP address will be blocked for 60 minutes without prior notice.
- Escalated Restrictions: Repeated abuse may lead to longer-term blocks, throttling, or permanent access restrictions.
📊 Visualized Guide (Do’s & Don’ts)
Below is the actual usage and traffic pattern on Fiuu's payment status inquiry APIs:
Dominated by q_by_tid and q_by_oid with peak hours from 11am-11pm (UTC+8)

✅ Correct Way (Best Practice)
- Initiate Payment/Refund Request → Wait for notification via endpoint.
- If no notification is received, trigger a status inquiry after a reasonable delay.
- Apply a progressive retry strategy (max once every 2-5 mins)
- Stop inquiries once a final status is obtained (Success, Failed, or Refunded).
- Always trigger status inquery request from merchant server with static IP address.
❌ Wrong Way (That Gets You Blocked)
- Immediately calling inquiry after sending a payment/refund request.
- Triggering inquiry repeatedly every few seconds or minutes.
- Continuing to query even after the final status is confirmed.
- Ignoring push notification endpoints, relying solely on inquiry calls.
- Distributed inquery by triggering the request on client service/mobile app from various IP address.

Fair Use Principles (Merchant Pledge)
- Webhook-first: Treat webhook/PG notifications as the source of truth. Use requery only as a fallback.
- Purpose-bound calls: Requery only to resolve pending/unknown states. Do not poll completed/failed/refunded transactions repeatedly.
- Respect limits: Never exceed rate limits or maximum results per call. Apply client-side throttling.
- Honor data windows: Choose an API whose data range actually covers the transaction’s age.
- Bulk cadence: If performing bulk checks, run them once every 30 minutes and only for unresolved items.
- Backoff & jitter: Use exponential backoff and randomized jitter to prevent thundering herd issues.
- Stop early: Cease polling immediately once a final state (Success / Fail / Void / Refunded) is confirmed.
- Be predictable: Avoid burst traffic; distribute calls evenly within a time window.
- Secure & compliant: Protect IDs, authenticate requests, log minimal PII, and rotate credentials regularly.
- Operational transparency: Monitor, alert, and reduce traffic promptly if approaching throttling or encountering HTTP 429/5xx errors.
Best-Practice Playbooks
⏱ Real-Time Transactions (single payment)
- T0: Create/authorize payment and listen for webhook.
- If no webhook is received after N minutes (e.g., 2–5 minutes):
- Use q_by_tid (fast, 30 RPS, 180D) for the single transaction.
- Retry using exponential backoff (e.g., 2 min → 5 min → 15 min), and cap the total retry duration (e.g., 60–90 minutes).
- Stop as soon as a final state is received (via webhook or requery).

📦 Bulk Recovery/Housekeeping
- Every 30 minutes (via cron/scheduler), fetch transactions still in pending/unknown status:
- Prefer q_by_tids (10 per call, 10 RPS, 30D) for transaction ID lists.
- If only order IDs are available, use:
- q_by_oids (slow, 10 per call, 5 RPS, 24H), or
- q_oid_batch to fetch the latest 10 matches by order ID (also slow, 5 RPS, 24H).
- For cross-brand/tenant operations, narrow by master merchant using:
- qMaster_tid (1 transaction, 10 RPS, 30D), or
- qMaster_oid (1 transaction, 5 RPS, 24H).
- Spread calls evenly across the 30-minute window to avoid traffic spikes.
- Automatically exclude transactions outside each API’s data range.
❌ Error Handling & Retries
- Handle HTTP 429 (Too Many Requests) by backing off (e.g., 1–5 minutes) and reducing concurrency.
- For 5xx errors, retry using capped exponential backoff and implement a circuit breaker to pause for a cooling period.
- Maintain idempotent job runs; deduplicate work by transaction or order ID.
📄 Choosing the Right API (cheat sheet)
- Know a transaction ID and need a single status → q_by_tid (fast).
- Know many transaction IDs → q_by_tids (batch up to 10).
- Only know a single order ID → q_by_oid.
- Need latest matches for an order → q_oid_batch (latest 10).
- Have many order IDs → q_by_oids (batch up to 10).
- Multi-tenant/master merchant scoping → qMaster_tid / qMaster_oid.
Traffic Management & Guardrails
-
Client-side rate limiter: Respect hard caps per API
(e.g., q_oid_batch ≤ 5 RPS, q_by_tid ≤ 30 RPS).
-
Concurrency caps:
- Moderate APIs → up to 10 workers
- Slow APIs → 3–5 workers
-
Exponential backoff with jitter:
- Base: 30s
- Factor: 2
- Jitter: ±20%
-
Circuit breaker:
- Opens after N consecutive failures or sustained 429/5xx errors
- Cooling period: 5–10 minutes
-
Work deduplication:
- Maintain a queue keyed by transaction/order ID
- Ignore duplicates in-flight
-
Stop conditions:
- Stop immediately on final status
- Auto-exclude records outside the data range
Monitoring, Logging, and Alerts
- Metrics:
- Requests/second per API
- Success rate
- HTTP 429/5xx counts
- Average latency
- Retries
- Backlog size
- SLIs/SLOs:
- Timeliness to final status (e.g., P95 latency)
- Webhook success rate
- Requery savings (how often requery resolved the status)
- Alerts:
- Spike in HTTP 429 errors > threshold (e.g., >1% over 5 minutes)
- Spike in 5xx errors or latency > 2× baseline
- Backlog age exceeds 45 minutes
- Audit logs:
- Log minimal fields: txn_id, order_id, API used, timestamp, attempt number, and result
Security & Compliance
- Protect identifiers (txn_id, order_id) both in transit and at rest
- Apply the principle of least privilege for API credentials; rotate them regularly
- Minimize PII: Do not log sensitive cardholder data; align with PCI DSS where applicable
- Webhooks:
- Verify signatures
- Use HTTPS
- Implement replay protection
- Ensure idempotency (DO NOT treat multiple notification or callback as double or triple payment)
Do’s & Don’ts
Do's
· Use webhooks as the primary signal.
· Requery only unresolved transactions.
· Batch where possible (q_by_tids, q_by_oids).
· Respect Rate Limit, Max Results, Data Range.
· Requery only from server.
Don'ts
· Poll completed transactions.
· Burst at the top of the minute - smooth your traffic.
· Use order-ID endpoints for records older than 24 hours.
· Ignore HTTP 429/5xx errors — always implement backoff.
· Requery from user mobile app.
Reference Scheduler Config
scheduler:
bulk_requery:
interval: "PT30M" # every 30 minutes
include_states: ["PENDING", "UNKNOWN"]
api_choice:
prefer: "q_by_tids"
fallback_for_order_id: "q_by_oids"
rate_limits:
q_by_tid: { rps: 25 } # below hard cap 30
q_by_tids: { rps: 8 } # below hard cap 10
q_by_oid: { rps: 8 } # below hard cap 10
q_by_oids: { rps: 4 } # below hard cap 5
q_old_batch: { rps: 4 } # below hard cap 5
data_windows:
q_by_tid: "P180D"
q_by_tids: "P30D"
q_by_oid: "P7D"
q_by_oids: "P1D"
q_old_batch: "P1D"
retries:
max_attempts: 5
backoff: { baseSeconds: 30, factor: 2.0, jitter: 0.2 }
circuit_breaker:
failureRateThreshold: 0.2
slidingWindow: "PT5H"
coolOff: "PT10M"
Updated about 2 months ago