Skip to content

Reference

Idempotency

Send an Idempotency-Key with every POST. If a request times out or your process restarts, you can repeat it with the same key and never create a second payment, payout or refund.

The rules

  • The header is required on every POST: 1 to 255 characters, a UUID is a good choice. Without it the API answers 400 idempotency_key_required.
  • For operations that create a resource (payment intents, payouts, refunds) the key is scoped by account and operation type, and compared against a fingerprint of the whole request body for the resource's life.
  • Replaying a key with the same body returns the original resource with 200 instead of 201.
  • Replaying a key with any change to the body answers 409 idempotency_conflict.
  • The same key on a different operation type, or in another account, is independent. A payment intent, a payout and a refund may share a key.
  • A 500 is safe to retry with the same key.
You sendYou get
New key201 and the new resource.
Same key, same body200 and the original resource.
Same key, different body409 idempotency_conflict.
No key400 idempotency_key_required.

In the SDKs

The SDKs generate a UUID for every POST, so their own retries are already safe. To make a create safe across crashes and restarts, derive the key from something you already own, such as your order id, and pass it yourself.

curl

# Run it twice: the first call answers 201, the second 200 with the same intent.
curl -sS -i "$RAVELO_API/v1/payment-intents" \
  -H "Authorization: Bearer $RAVELO_TEST_KEY" \
  -H "Idempotency-Key: order-10492" \
  -H "Content-Type: application/json" \
  -d '{ "order_ref": "order-10492", "asset_id": "usdt-tron", "amount": "25000000" }'

TypeScript

import { Ravelo, RaveloError } from "@ravelo/sdk";

const ravelo = new Ravelo({ apiKey: process.env.RAVELO_TEST_KEY!, baseUrl: process.env.RAVELO_API! });
const input = { order_ref: "order-10492", asset_id: "usdt-tron", amount: "25000000" };

// Derive the key from your own order, so a crash and restart repeats the same request instead of creating a second one.
const first = await ravelo.paymentIntents.create(input, { idempotencyKey: "order-10492" });
const again = await ravelo.paymentIntents.create(input, { idempotencyKey: "order-10492" });
console.log(first.id === again.id); // true: the original intent comes back

try {
  await ravelo.paymentIntents.create({ ...input, amount: "30000000" }, { idempotencyKey: "order-10492" });
} catch (err) {
  if (err instanceof RaveloError && err.code === "idempotency_conflict") console.log("same key, different body");
  else throw err;
}

Python

import os

from ravelo import Ravelo, RaveloError

ravelo = Ravelo(os.environ["RAVELO_TEST_KEY"], os.environ["RAVELO_API"])

# Derive the key from your own order, so a crash and restart repeats the same request instead of creating a second one.
first = ravelo.payment_intents.create(order_ref="order-10492", asset_id="usdt-tron", amount="25000000", idempotency_key="order-10492")
again = ravelo.payment_intents.create(order_ref="order-10492", asset_id="usdt-tron", amount="25000000", idempotency_key="order-10492")
print(first["id"] == again["id"])  # True: the original intent comes back

try:
    ravelo.payment_intents.create(order_ref="order-10492", asset_id="usdt-tron", amount="30000000", idempotency_key="order-10492")
except RaveloError as err:
    if err.code != "idempotency_conflict":
        raise
    print("same key, different body")