Skip to main content

Journey 1: Complete a payment

You prove that a full payment moves the request to PAID, the payment to COMPLETE, your webhook receives every lifecycle event, and Hubpay creates the payout if the request has payout details.

You need

  • Before you start done.
  • A new payment request in UNPAID status. Put the method you will test in paymentMethods. To also test the payout, create it in AED with payoutDetails. See Payment request payouts.

Step 1: Pay

Pick the tab that matches how your payers pay.

Send POST /v1/collections/simulate-payment:

{
"paymentRequestReference": "ORDER-10045",
"paymentMethod": "BANK_TRANSFER"
}

The response has paymentRequestStatus: "PAID". Hubpay also completes the payment and credits your wallet in the same call. Skip step 2.

Step 2: Complete the crypto payment

Bank transfer and card are completed in step 1. For both crypto tabs, the money is received but not yet in your wallet. In production the provider settles first. In sandbox you ask for it:

Send POST /v1/collections/simulate-payment-completion:

{
"paymentRequestReference": "ORDER-10045",
"paymentId": "<paymentId from step 1>"
}

Expect paymentStatus: "COMPLETE" and paymentRequestStatus: "PAID". Your webhook receives payment.completed.

If the response is 400 because a compliance check is still running, wait a moment and send it again.

Step 3: Prove it

CheckExpected
GET /v1/collections/payment-requests/{id}status: "PAID", amountRemaining: 0, one payment with status: "COMPLETE"
Your webhook URLpayment.pending, payment.received, payment_request.paid, payment.completed, in roughly that order
Your appShows the order as paid. Fulfil it only after your webhook receives payment.completed with a valid signature and the API reports the payment as COMPLETE.

Step 4: Check the payout

Only if the request was created with payoutDetails.

Read the payout with Get payment for payment request. Expect the payout status to be INITIATED, or PENDING_APPROVAL if your account requires a second approver. The API returns statuses in uppercase. Webhook names stay lowercase. Sandbox cannot move a payout to PAID or FAILED yet.

If it does not work

ProblemCauseFix
400 on simulate-paymentThe request is already PAID, or the method is not in paymentMethodsCreate a new request with the right method
400 on simulate-crypto-depositNo open quoteOpen checkout and select a token and network first
400 on completionA compliance check is running, or a deposit is still PENDINGWait, or confirm the pending deposit, then retry
404Wrong reference, or the request belongs to another accountCheck the reference and the AccountId header
No payout webhookThe request is not AED, has no payoutDetails, or the beneficiary is not a UAE beneficiaryCreate the request again with valid payout details

Good to know

  • Send the same deposit or completion call again to test duplicates. You get alreadyProcessed: true or alreadyCompleted: true and no extra webhooks.
  • Sending simulate-payment again after a full payment is rejected with 400, because the request is already PAID. While a request is still UNPAID or PART_PAID, each call creates a separate payment.
  • A payout failure never undoes the wallet credit.