SETSimple Easy Transactions
SET DocsAPI reference and complianceUpdated 2026-11-10
Browse: SET API (Platforms)

Payment references

SET API · platform keys · Live since 2026-11-12

A payment reference tells SET which order a payment is for. Your customer has one Cash-Out Address for each chain and stablecoin, and anyone can pay it from any wallet, including a payer SET has never seen. A reference reserves one order's amount on that address. When a payment of that amount arrives, SET settles the reference and tells you which order was paid.

A merchant key gets 403 payment_references_platform_only. A business paid for its own goods issues an invoice instead.

The calls

CallScopeWhat it does
POST /v1/payment_referenceswriteTakes {cashOutAddress, amount, expiresAt, payer?, metadata?} and answers payableAmount and reference. reference is the same as id; quote it on your order
GET /v1/payment_referencesreadEvery reference, paged like every list. Filters: customer, state, cashOutAddress, cashOutPayment
GET /v1/payment_references/{id}readOne reference
POST /v1/payment_references/{id}/cancelwriteOpen references only. Frees the payable amount
POST /v1/payment_references/{id}/matchwrite{cashOutPayment}: your own match, for an open or expired reference
  • amount is the order total, with at most two decimals, and at least 2.00 (400 amount_too_small below it).
  • expiresAt falls within the next 30 days.
  • payer takes the same body as POST /v1/cash_out_payments/{id}/sender. SET seals it at rest and never shows it again.
  • A business or customer under a restriction gets 403 restricted when it creates a reference or matches one by hand. It can still read, list and cancel. A payment that reaches the address is still recorded, and held under the restriction.

The amount to ask for

payableAmount is the order amount plus a tag between 0.000001 and 0.009999. The tag is unique among the address's open references and is the same kind of tag an invoice carries. Ask the payer for payableAmount exactly. The tag is under a cent, and the payer pays it.

If one address has too many open references of the same amount, SET answers 409 payable_amount_exhausted. Cancel or settle some first.

How a payment is matched

SET reads, once, the amount the chain shows reaching the address and compares it with the address's open references:

The payment isThe reference becomesRule
Exactly a reference's payableAmountmatchedexact
At least the order's amount and less than a cent above it, and only one open reference fitsunderpaid (with shortBy) below the payable amount, overpaid (with overBy) above itcents
Anything elseNo reference is settled

If two references of the same amount both fit a payment by cents, SET picks neither. The payment stays as it is and you can match it yourself. A payment whose amount the chain cannot give yet is tried again on its next event.

Matching only labels the money. Whatever reaches the address is paid to your customer's bank either way.

The Travel Rule

When you give a payer at creation, SET sends it as the payment's sender, as it does for an invoice's payer. In the sandbox this lifts an unknown_sender hold.

If you gave no payer, the reference settles only a payment whose sender is already named. Otherwise it stays open: name the sender with POST /v1/cash_out_payments/{id}/sender, then match the payment yourself. A manual match with neither a payer nor a named sender answers 409 sender_required.

Whether the payer reached the provider

A settled reference shows senderState, the settling Cash-Out payment's own Travel Rule state (as GET /v1/cash_out_payments/{id} shows it): none, submitted, failed or simulated, and in the sandbox unknown_sender while a payment is held. It is null until a payment settles the reference.

  • Refused. When the provider refuses the payer's details, the reference reads senderState: "failed" and next names the step: POST /v1/cash_out_payments/{id}/sender with the details corrected. Once they are accepted, the reference reads submitted. The match stands either way: matching labels the money, and the provider pays what reached the address.
  • Events. payment_reference.matched, .underpaid and .overpaid are sent after the payer was sent, so each carries the senderState that sending left. A later correction changes the reference and the payment, and sends no new reference event.

GET /v1/capabilities lists payment references as a compliance control, compliance.controls.paymentReferences, with its routes and events.

Where you see it

  • On the payment. GET /v1/cash_out_payments and GET /v1/cash_out_payments/{id} carry paymentReference: the reference the payment settled, or null.
  • Events. payment_reference.created, .matched, .underpaid, .overpaid, .expired and .canceled. Each carries the reference as GET shows it, never the payer.
  • Expiry. Open references past expiresAt expire within about ten minutes, and a GET expires one it reads late. A payment of an expired reference's amount is not matched by itself; match it yourself if it is still the order's.

Try it in the sandbox

POST /v1/sandbox/unknown_sender {cashOutAddress, amount, senderAddress} simulates a payment from a wallet SET has never seen. It runs the match, so a reference with a payer names that payer and lifts the hold.

Not yet

  • Conversion Addresses. conversionAddress answers 400 conversion_address_not_supported.
  • A separate address for each order.