TigerPayDevelopers API v1 tigerpay.app

API reference

Payments

A payment is one attempt to collect money from a customer. You create it, send the customer to its checkout_url, and then follow it until it succeeds, fails, is cancelled or expires.

The payment object#

{
  "id": "pay_r3QA7YeEEBY3ABp3e2zS8iq9",
  "object": "payment",
  "status": "succeeded",
  "amount": "340.00",
  "amount_refunded": "0.00",
  "currency": "AED",
  "fee": "7.65",
  "net": "332.35",
  "reference": "order-1001",
  "description": "Blue mug",
  "customer_email": "buyer@example.com",
  "metadata": { "cart_id": "42" },
  "checkout_url": null,
  "card": { "brand": "VISA", "last4": "4242", "country": "AE" },
  "failure_message": null,
  "livemode": false,
  "created_at": "2026-10-20T10:00:00.000Z",
  "paid_at": "2026-10-20T10:02:31.000Z"
}
FieldDetails
id
string
The payment id. Starts with pay_.
object
string
Always "payment".
status
string
pending, succeeded, failed, cancelled or expired. See Statuses.
amount
string
The amount in AED with two decimals, such as "340.00".
amount_refunded
string
How much has been refunded so far (refunds that have succeeded). "0.00" if none.
currency
string
Always "AED".
fee
string or null
The TigerPay fee. null until the payment succeeds. See Pricing.
net
string or null
amount minus fee. null until the payment succeeds.
reference
string
Your own order id, as you sent it.
description
string or null
The description you sent.
customer_email
string or null
The customer email you sent.
metadata
object
Your key-value pairs. {} if you sent none.
checkout_url
string or null
Where to send the customer to pay. Only set while the status is pending; null after that.
card
object or null
{ brand, last4, country } once the card is known. country is the country that issued the card. null before that.
failure_message
string or null
A short reason when the payment failed or expired.
livemode
boolean
true for live payments, false for test payments.
created_at
string
When the payment was created. ISO 8601, UTC.
paid_at
string or null
When the payment succeeded. null before that.

Statuses#

StatusMeaning
pendingCreated. Waiting for the customer to pay. checkout_url is set.
succeededThe customer paid. fee, net, card and paid_at are set. You can refund it.
failedThe payment did not go through, or could not be created. failure_message says why.
cancelledThe payment was cancelled.
expiredThe customer did not pay in time. Create a new payment if they still want to buy.

A payment normally ends in one of succeeded, failed, cancelled or expired.

A late success is possible

If the payment provider reports a payment as paid after TigerPay had marked it failed, cancelled or expired, the payment moves to succeeded and you get a payment.succeeded webhook. Always act on the latest status. If you already cancelled the order on your side, refund the payment or reopen the order.

Create a payment#

POST/v1/payments

Creates a payment and returns it with a checkout_url. Send the customer there to pay.

Request body#

FieldDetails
amount
string required
Amount in AED with exactly two decimals, such as "340.00". Minimum "2.00", maximum "10000000.00". Digits and one decimal point only: no commas, spaces, leading zeros or currency symbol.
currency
string required
Must be "AED".
reference
string required
Your own order id. 1 to 64 characters. It does not have to be unique, so you can create a new payment for the same order after a failed attempt.
success_url
string required
Where the customer is sent after checkout. Must be https, up to 512 characters, with no username or password in it.
cancel_url
string required
Same rules as success_url. Please read the note below: the customer is not sent to this URL today.
description
string
Up to 500 characters.
customer_email
string
A valid email address, up to 254 characters.
metadata
object
Your own key-value pairs. Up to 20 keys. Each key is 1 to 40 characters. Each value must be a string of up to 500 characters. We send it back on the payment and in webhooks.

success_url and cancel_url are both required. A request that leaves either one out is rejected with a 400 validation error. Unknown fields are rejected with a 400 error too, so a typo in a field name is caught straight away.

The customer always returns to success_url

The hosted payment page supports one return address. After checkout, the customer is sent to success_url whatever the outcome: paid, failed or not finished. cancel_url is required and is stored with the payment, but there is no separate cancel redirect.

So on your success_url page, do not say "thank you, paid". Look up the payment (or wait for the webhook) and show the real result.

Example#

curl https://api.tigerpay.app/v1/payments \
  -H "Authorization: Bearer sk_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1001" \
  -d '{
    "amount": "340.00",
    "currency": "AED",
    "reference": "order-1001",
    "description": "Blue mug",
    "customer_email": "buyer@example.com",
    "success_url": "https://shop.example.com/thanks",
    "cancel_url": "https://shop.example.com/cart",
    "metadata": { "cart_id": "42" }
  }'
const response = await fetch("https://api.tigerpay.app/v1/payments", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.TIGERPAY_SECRET_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "order-1001",
  },
  body: JSON.stringify({
    amount: "340.00",
    currency: "AED",
    reference: "order-1001",
    success_url: "https://shop.example.com/thanks",
    cancel_url: "https://shop.example.com/cart",
  }),
});
const payment = await response.json();
<?php
$ch = curl_init('https://api.tigerpay.app/v1/payments');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . getenv('TIGERPAY_SECRET_KEY'),
        'Content-Type: application/json',
        'Idempotency-Key: order-1001',
    ],
    CURLOPT_POSTFIELDS     => json_encode([
        'amount'      => '340.00',
        'currency'    => 'AED',
        'reference'   => 'order-1001',
        'success_url' => 'https://shop.example.com/thanks',
        'cancel_url'  => 'https://shop.example.com/cart',
    ]),
]);
$payment = json_decode(curl_exec($ch), true);
curl_close($ch);

Response: 200 with the payment object, status pending.

Possible errors#

CodeWhen
parameter_invalid
HTTP 400
A field is missing or wrong. The message names the field, for example amount: must be a decimal string with two decimals, such as "340.00".
invalid_request
HTTP 400
You sent a field that does not exist. The message lists it.
invalid_json
HTTP 400
The body is not a JSON object.
provider_rejected
HTTP 502
The payment could not be created. Check your details and try again.
provider_unavailable
HTTP 502
A temporary problem on our side. Retry. Nobody can pay for the failed attempt, because you never received a checkout_url for it.

Retrieve a payment#

GET/v1/payments/{id}

Returns the payment object for a pay_ id.

curl https://api.tigerpay.app/v1/payments/pay_r3QA7YeEEBY3ABp3e2zS8iq9 \
  -H "Authorization: Bearer sk_test_YOUR_KEY"
  • If the payment is still pending and is more than 2 minutes old, TigerPay checks its latest state before it answers. So this call can show a result even if a webhook has not reached you yet.
  • If the id does not exist, or belongs to another account or the other mode, you get 404 with code resource_missing.

Webhooks are the best way to learn about a result. Use this call to double-check, or to catch up after your server was down.

List payments#

GET/v1/payments

Returns your payments, newest first. A test key lists test payments and a live key lists live payments.

Query parameterDetails
limit
integer
How many payments to return. 1 to 100. Default 10.
starting_after
string
A payment id. Returns the payments that come after it (older ones). Use the last id of the previous page.
status
string
Only payments with this status: pending, succeeded, failed, cancelled or expired.
curl "https://api.tigerpay.app/v1/payments?limit=2&status=succeeded" \
  -H "Authorization: Bearer sk_test_YOUR_KEY"
{
  "object": "list",
  "data": [
    { "id": "pay_r3QA7YeEEBY3ABp3e2zS8iq9", "object": "payment", "status": "succeeded", "…": "…" },
    { "id": "pay_kY9pF34Qy6nB3Wwd25rq4f5z", "object": "payment", "status": "succeeded", "…": "…" }
  ],
  "has_more": true
}

If has_more is true, ask for the next page with starting_after set to the id of the last payment you received:

curl "https://api.tigerpay.app/v1/payments?limit=2&status=succeeded&starting_after=pay_kY9pF34Qy6nB3Wwd25rq4f5z" \
  -H "Authorization: Bearer sk_test_YOUR_KEY"

An unknown query parameter, or a starting_after that is not one of your payments, gives 400 parameter_invalid.

Cancel a payment#

POST/v1/payments/{id}/cancel

Cancels a payment that is still pending, so the customer can no longer pay it. No body is needed. TigerPay sends a payment.cancelled webhook.

curl -X POST https://api.tigerpay.app/v1/payments/pay_kY9pF34Qy6nB3Wwd25rq4f5z/cancel \
  -H "Authorization: Bearer sk_test_YOUR_KEY"

It returns the payment with status cancelled and checkout_url set to null.

  • Only pending payments can be cancelled. Any other status gives 400 payment_not_cancellable. If the customer pays at the same moment, the request can fail with this error. Fetch the payment to see its real status.
  • To give money back for a payment that succeeded, use a refund.

Money maths#

  • Amounts are strings so that no rounding error can creep in. Do not turn them into floating-point numbers. Work in fils ("340.00" is 34000 fils) or use a decimal library.
  • The fee is worked out in whole fils and rounded half up. Example: AED 10.10 on a UAE card at 2.25% is 22.725 fils, so the fee is 23 fils, "0.23".