Sandbox. Test keys, Arc testnet and test USDC. No real money moves here.

API reference

Refunds

Refund a session in full or in part, as many times as needed, up to what it received. SaphraONE is non-custodial and never moves a merchant’s money, so your server requests a refund and the merchant approves and sends it in SaphraONE.

How a refund works

  1. Request it

    POST /v1/refunds returns a refund with status requested. Its amount is reserved at once, so refunds can never add up to more than the session received.
  2. The merchant sends it

    The business gets a notification and a Refund request in Checkout. They send it from their business wallet, or decline it (cancelled). Merchants can also start refunds themselves in SaphraONE.
  3. It succeeds

    Once the transfer is verified on chain the refund becomes succeeded with its tx_hash, the session’s amount_refunded goes up, and a refund.succeeded webhook is sent.

The refund object

Fields

idstring
Unique id, re_live_… or re_test_….
objectstring
Always refund.
sessionstring
The checkout session refunded.
amountstring
Decimal string in the session currency.
currencystring
USDC or EURC.
statusenum
requested (waiting for the merchant), succeeded (sent and verified on chain) or cancelled (declined by the merchant).
destination_walletstring
The Arc wallet the refund goes to.
tx_hashstring | null
The refund transaction once succeeded, else null.
reasonstring | null
Why, up to 200 characters, or null.
created_at, succeeded_atstring | null
ISO 8601 timestamps.
{
  "amount": "10",
  "created_at": "2026-10-18T10:02:11.000Z",
  "currency": "USDC",
  "destination_wallet": "0x8f3c…a21d",
  "id": "re_test_4h7k2m9q8x3c5vtn1rj6bdwz",
  "object": "refund",
  "reason": "Item out of stock",
  "session": "cs_test_4f9k2m7q1x8v4b6n0c5d2h7j",
  "status": "requested",
  "succeeded_at": null,
  "tx_hash": null
}

Request a refund

POST/v1/refunds

Body parameters

sessionstringrequired
The checkout session to refund.
amountstring
Decimal string. Defaults to everything still refundable; at least 0.01.
destination_walletstring
The buyer’s Arc wallet. Optional when the buyer paid from a wallet or a SaphraONE account (the refund goes back to it). Required when they paid by card, bank or from another chain, because then the paying wallet isn’t the buyer’s.
reasonstring
Shown to the merchant, up to 200 characters.
curl https://sandbox.api.saphra.one/v1/refunds \
  -H "Authorization: Bearer sk_test_…" \
  -H "Content-Type: application/json" \
  -d '{"session": "cs_test_4f9k2m7q1x8v4b6n0c5d2h7j", "amount": "10", "reason": "Item out of stock"}'

Retrieve a refund

GET/v1/refunds/{id}

curl https://sandbox.api.saphra.one/v1/refunds/re_… \
  -H "Authorization: Bearer sk_test_…"

List a session’s refunds

GET/v1/refunds?session={id}

Returns {object: "list", data, has_more}, oldest first. Every refund also appears in the session’s own refunds array.

curl "https://sandbox.api.saphra.one/v1/refunds?session=cs_test_4f9k2m7q1x8v4b6n0c5d2h7j" \
  -H "Authorization: Bearer sk_test_…"