TigerPayDevelopers API v1 tigerpay.app

API reference

Idempotency

Networks fail. If a request times out, you do not know if it worked. An idempotency key lets you send the same request again without creating a second payment or a second refund.

How to use it#

Add an Idempotency-Key header to a POST request. Use any unique value you choose.

POST /v1/payments HTTP/1.1
Host: api.tigerpay.app
Authorization: Bearer sk_test_YOUR_KEY
Idempotency-Key: order-1001-attempt-1
Content-Type: application/json
  • The header is optional. It works on every POST endpoint: create payment, cancel payment and create refund.
  • The key is 1 to 255 printable ASCII characters, with no spaces. A bad key gives 400 idempotency_key_invalid.
  • Keys are remembered for 24 hours.
  • Keys belong to one API key. A test key and a live key do not share keys.
  • GET requests are safe to repeat already, so they do not need a key.

What happens when you reuse a key#

You sendYou get
The same key and the same requestThe original response again, with the same status code. The header Idempotent-Replayed: true is added. Nothing new is created.
The same key and a different request409 with code idempotency_key_reused.
The same key while the first request is still running409 with code idempotency_conflict. Wait a moment and send it again.

"The same request" means the same bytes#

TigerPay compares the method, the URL path and the raw body. If you change anything in the body, even the order of the fields or a space, it counts as a different request. Build the body once and resend the exact same text.

Errors are remembered too#

If the first request got a 4xx error (for example a validation error), that error is stored and replayed for the same key. If you fix the request and send it with the same key, you get idempotency_key_reused. Use a new key when you change the request.

Errors with status 5xx are not stored, so you can retry them with the same key. Rate-limit (429) and authentication errors happen before the key is checked, so they are not stored either.

After a 5xx on a refund, do not retry blindly

Because 5xx answers are not stored, sending the same refund again can start a second refund. The amount that is still refundable is protected, so you cannot refund more than the customer paid. But check the payment's amount_refunded or wait for the refund webhook first. See Refunds.

Picking good keys#

  • Tie the key to the thing you are doing, such as order-1001-attempt-1 or refund-order-1001-1. The same order retried after a network error reuses the same key.
  • When the customer starts a new payment attempt, make a new key (attempt-2).
  • Random UUIDs also work, as long as you save the key and reuse it when you retry.

Example: a safe retry#

async function createPaymentWithRetry(body, key, attempts = 3) {
  const raw = JSON.stringify(body); // build the body once, resend the same text
  for (let i = 0; i < attempts; i++) {
    try {
      const res = await fetch("https://api.tigerpay.app/v1/payments", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.TIGERPAY_SECRET_KEY}`,
          "Content-Type": "application/json",
          "Idempotency-Key": key,
        },
        body: raw,
      });
      if (res.status < 500 && res.status !== 429) return await res.json(); // success or a real answer
    } catch (err) {
      // network error: fall through and retry with the same key
    }
    await new Promise((r) => setTimeout(r, 500 * 2 ** i)); // wait 0.5s, 1s, 2s…
  }
  throw new Error("TigerPay is not reachable right now");
}