Amwal Tech logoDocs

Troubleshooting Payment Link & QR Code Errors

When a customer or POS cashier visits an Amwal payment URL (https://pay.sa.amwal.tech/payment-link/{id}), errors can arise if the link has expired, already been paid, or configured with invalid parameters.


  • Root Cause: The ISO 8601 timestamp in selectedDate has elapsed.
  • Default TTL: If not explicitly specified during creation, payment links expire after 24 hours.
  • Solution:
    • To generate persistent links for long invoices, set selectedDate to a future timestamp (e.g. 2026-12-31T23:59:59Z).
    • In POS in-store mode, QR codes are generated dynamically with shorter 15-minute expiry for security.
  • Root Cause: The link was generated with "singleUse": true and a successful payment was already completed.
  • Solution:
    • For single invoices, generate a new link for repeat customer orders using the Create Payment Link API.
    • For reusable static donation or multi-buyer product links, set "singleUse": false.

3. "Store Not Found or Inactive" (STORE_INACTIVE_OR_INVALID)

  • Root Cause: The store_id UUID in the path /payment_links/{store_id}/create does not exist or has been paused in the Merchant Portal.
  • Solution:
    • Verify your Store ID under Merchant Portal -> Stores & Terminals.
    • Ensure the store's verification status is active with an approved Commercial Registration (CR).

You can inspect the live status of any payment link using the Get Payment Link Details API — note this is a POST, and payment_link_id is the only path parameter (no separate store_id segment):

curl -X POST "https://backend.sa.amwal.tech/payment_links/d0901e69-02ec-499f-ba5c-9c7ef95ad062/details" \
  -H "Authorization: YOUR_SECRET_KEY" \
  -H "X-Amwal-Key: sandbox-amwal-xxx" \
  -H "Content-Type: application/json"

payment_link.status reverts to Unpaid after ANY refund

Confirmed against the live API: once a refund lands on a transaction — even a partial one — the payment link's status reverts to Unpaid, identical to a link nobody ever paid. Don't use payment_link.status alone to diagnose "was this ever paid" — check transactions[].status instead. See Get Payment Link Details for the full caveat.

On this page