Pay with a Saved Token
To charge a saved card, call the same POST /api/v1/payment endpoint used to create any payment. Instead of letting the customer enter a card, you pass the token in paymentData.
Before you start
- You have a token that is not blocked, received as described in Enable & Save a Card.
- For recurring payments (
recurrent: true): the token type isAUTH, and recurring payments are enabled on your terminal (Step 1).
Create the payment
API Endpoint
POST https://uat-sandbox-3ds-api.qi.iq/api/v1/payment
Headers
| Name | Value | Required |
|---|---|---|
X-Terminal-Id | The ID of the Merchant Terminal. Provided by the Acquirer. | Yes |
Authorization | Basic followed by your Base64-encoded credentials. See Basic Auth. | Yes |
Content-Type | application/json | Yes |
Accept | application/json | Yes |
CURL Example
curl --location '<API_HOST>/api/v1/payment' \
--header 'X-Terminal-Id: {terminalId}' \
--header 'Authorization: Basic <Base64<username:password>>' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"requestId": "<GUID>",
"amount": 1000.00,
"currency": "IQD",
"recurrent": true,
"paymentData": {
"paymentType": "PAYMENT_TOKEN",
"paymentToken": "<token>"
},
"finishPaymentUrl": "https://www.merchant.com/finish",
"notificationUrl": "https://www.merchant.com/webhook-notification"
}'
Request Body
Media type: application/json
{
"requestId": "9a7c1e42-5d3b-4f8a-b6e0-1c2d3e4f5a6b",
"amount": 1000.0,
"currency": "IQD",
"recurrent": true, // true for a recurring, merchant-initiated payment
"paymentData": {
"paymentType": "PAYMENT_TOKEN",
"paymentToken": "48b85aa5-e7a6-5ccc-9466-703472aa7541"
},
"finishPaymentUrl": "https://merchant.net/finish",
"notificationUrl": "https://merchant.net/notification"
}
Request body fields
| Field | Type | Description |
|---|---|---|
| requestId | string required | A unique identifier generated by the Merchant's side. It must be ensured that the RequestId remains unique within the context of each Merchant Terminal to prevent duplication or conflicts. |
| recurrent | boolean optional | Set to true when you charge a saved token as a recurring, merchant-initiated payment (for example a subscription renewal) without the payer present. Recurring payments require an AUTH token. Omit it or set it to false for payments the payer starts. |
| amount | number required | Specifies the total payment amount, including any applicable fees or commissions from the merchant. This field is required for all payment transactions but should be absent for non-payment transactions. Note non-payment transactions are used to collect card information without processing any payment. This type of transaction is useful when card details are needed for future use, but no immediate charge is required. |
| currency | string required | The ISO 4217 code represents the currency for the payment, for example: IQD - Iraqi Dinar, The value must be exactly 3 characters long, Max value = 3, Min value = 3 |
| paymentData | object required | The payment method to use. To charge a saved card, set paymentType to PAYMENT_TOKEN and paymentToken to the token value. |
| paymentData.paymentType | string required | The payment method. Use PAYMENT_TOKEN to pay with a previously saved token. |
| paymentData.paymentToken | string required | The token value you received when the payer's card was tokenized. Maximum 100 characters. |
| finishPaymentUrl | string required | This field specifies the URL where the payer will be redirected after the payment process is completed. The redirection occurs on the client side, and the URL is provided by the merchant. Once the payment is processed, the user is automatically sent to this URL, reflecting the outcome of the transaction, A merchant can use this field to redirect his user back to the merchant side, Maximum characters: 1024 |
| notificationUrl | string required | This field is used to provide a webhook URL where the payment gateway will send a POST request to notify the merchant's side of the payment status after the payer completes the transaction. The notification will include in its body the updated data object of the payment (containing the new status: success, pending, or failure), allowing the merchant to track the result of the payment in real time |
Choosing recurrent
How to set recurrent according to your business use case:
| Scenario | recurrent | Token types you can use |
|---|---|---|
| You charge on a schedule without the customer present: subscription renewals or monthly bills | true | AUTH |
| The customer is present and picks their saved card, for example at checkout | false, or leave it out | AUTH, NON_RECUR, UNAUTH |
A payment with an UNAUTH token still needs the customer to authenticate, so it works only when the customer is present to complete the hosted payment page.
Handle the result
The response is the same Payment object that Create Payment returns. Save the paymentId, then:
- If the customer needs to authenticate — for example with an
UNAUTHtoken — redirect them toformUrl, exactly as for a normal payment. - Wait for the webhook. The gateway sends the final payment object, with its
status, to yournotificationUrl. Treat it as the source of truth (see Webhook Notifications).
A token payment can be refunded or cancelled like any other payment, with Refund Payment and Cancel Payment.
recurrent and paymentToken are part of the createPayment signature string, after withoutAuthenticate. Send - for any value that is not in the request. See Signature-Based Authentication.
If the request fails with a token error (codes 31, 32, or 35), see Token error codes.
Next: Block a token →