Skip to main content

Customer Payouts

Send money from your Luxury Fintech balance to your own customers — refunds, goodwill payments, settling a dispute. You create the payout; the recipient chooses how and where to receive it, in their own browser.

You never handle a receiving address, and you never see one.

🌐 Base URL​

EnvironmentHost
Productionhttps://luxfin.org
Sandboxhttps://sandbox.luxfintech.org

āœ… Before you start​

Three things must be true before any payout can be created. Each is checked on every request, not once at onboarding.

RequirementHow it is set
Your account is approved for payoutsLuxury Fintech operations
Payouts are switched on for your accountYour administrator, in the dashboard
You hold an API credential with payouts:writeYour administrator, in the dashboard

A webhook is not a requirement — it is optional, and only announces payouts that have been paid.

Creating a payout reserves money immediately

A payout is not a draft. The amount plus the fee leaves your available balance the moment the create call returns, and comes back only if the payout is cancelled or expires unclaimed.


šŸ” Authentication​

Every call carries a Bearer credential:

Authorization: Bearer pok_a1b2c3d4e5f6a7b8.xK9…
  • The credential is shown once, when it is issued. We store only a verifier, so a lost key is replaced, never recovered.
  • Two scopes: payouts:read and payouts:write. Give an integration that only checks status a read-only credential.
  • Revoking takes effect immediately, on the next request.
  • Credentials are per account. A credential belonging to one account can never act for another.
  • Credentials are per environment. A sandbox credential is refused on production, and the reverse, with wrong_environment (403).
note

Payout credentials are separate from your checkout API key. Using the wrong kind of credential returns wrong_credential_kind (403).


šŸ“Ø Two delivery modes​

linkredirect
Who the recipient isAn email address you supplyA customer you have just authenticated
How they get inA claim link you send themA one-time handoff you redirect them to
Email verificationA code sent to that fixed addressNot needed — you already authenticated them
Access link lifetimeUntil the payout expires10 minutes, single use — request a fresh one
Payout expires if unclaimed7 days after creation24 hours after creation
Required fieldscustomer_emailcustomer_id, return_url

return_url must exactly match an origin registered for your account — scheme, host and port, no wildcards.

  1. Create the payout with delivery: "link" and customer_email.
  2. Store the returned payout_url — it is returned once.
  3. Send the link to your customer yourself. We do not email it.
  4. The recipient opens the link and verifies the email address you supplied (we email them a code), then chooses how to receive the money. A link that reaches the wrong person is not enough to claim it.

If the link is lost, fetch it again with Get or rotate claim link. If it went to the wrong person, rotate it.

redirect mode​

  1. Authenticate your customer on your own site.
  2. Create the payout with delivery: "redirect", customer_id and return_url.
  3. Redirect the customer's browser to the returned payout_url within 10 minutes.
  4. If the handoff expires, request a fresh one with Create redirect session.
caution

The browser returning to your return_url proves nothing. Always confirm the outcome by polling the payout, or with a webhook — which is sent only when a payout is paid.


šŸš€ A complete flow​

# 1. Check what you can commit, and the current fee
curl -s https://luxfin.org/api/payout/balance \
-H "Authorization: Bearer $PAYOUT_KEY"

# 2. Create the payout (money is reserved here)
KEY=$(uuidgen)
curl -s -X POST https://luxfin.org/api/payout/create \
-H "Authorization: Bearer $PAYOUT_KEY" \
-H "Idempotency-Key: $KEY" \
-H "Content-Type: application/json" \
-d '{"amount":"25.00","merchant_reference":"refund-ORD-10231",
"delivery":"link","customer_email":"person@example.com"}'

# 3. Send the payout_url to your customer.

# 4. Follow it: poll (or receive the webhook, sent only when it is paid)
curl -s https://luxfin.org/api/payout/po_9f3c1d7b2a8e4c15d0b6a291 \
-H "Authorization: Bearer $PAYOUT_KEY"

# 5. Changed your mind, before they confirm
curl -s -X POST https://luxfin.org/api/payout/po_9f3c…/cancel \
-H "Authorization: Bearer $PAYOUT_KEY" \
-H "Idempotency-Key: $(uuidgen)"

A payout that nobody claims expires on its own and the money returns to your balance. You never have to clean up.

After the recipient confirms, the payout is normally sent within minutes. If it shows processing with safe_reason: "awaiting_float", it is queued on our side and will be sent automatically — the money stays reserved and there is nothing to do.

Next steps​