Skip to content

Refunds, statements, and fee sharing

A refund is addressed by capture_id, and that value is not the transaction id, the order id, or the session id. It reaches you in three places, and they are all the same string:

  • provider_capture_id on the transaction, from GET /api/transactions or GET /api/transactions/{transaction_id}.
  • captureId in the browser SDK’s onApproved callback, described on Mount the SDK.
  • provider_capture_id inside data.object on the payment.captured event.

GET /api/transactions is how you look one up afterwards. It is a per-merchant read, so pair the channel key with that merchant’s X-Merchant-Id, exactly as the payment calls do.

The list has no order filter: it returns the merchant’s transactions newest first, and nothing in the request ties a row to the order you are refunding. Match the row yourself before you take its provider_capture_id — on checkout_session_id, the session you created for this order, or on external_order_id, the value you sent. Do not refund the first row the list returns: on a merchant with more than one payment that is simply the most recent, which is rarely the one you meant.

list-transactions.sh
curl --request GET \
--url 'https://staging.api.maxanapay.com/api/transactions?limit=20' \
--header 'Authorization: Bearer sk_test_replace_me' \
--header 'X-Merchant-Id: b3f1c8de-7a20-4c55-9e64-1d8f2a6b40c7'

Call POST /api/payments/captures/{capture_id}/refund with the channel key and that merchant’s X-Merchant-Id. Omit amount for a full refund or supply it for a partial refund. Use an Idempotency-Key for a retry, and reconcile the resulting payment.refunded event. The shared refund reference holds the request rules.

refund-capture.sh
curl --request POST \
--url 'https://staging.api.maxanapay.com/api/payments/captures/3XY45678AB901234C/refund' \
--header 'Authorization: Bearer sk_test_replace_me' \
--header 'X-Merchant-Id: b3f1c8de-7a20-4c55-9e64-1d8f2a6b40c7' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: order_1001_refund' \
--data @refund-capture.request.json

The response is {"success":true} and nothing else: no amount, no refund identifier, no updated balance. Everything about what was actually returned arrives on the payment.refunded event, including the pair a reconciler misreads — a partly refunded payment keeps status at captured and refunded_at at null.

The statement operations are channel-level: do not send X-Merchant-Id. GET /api/channel/statements lists closed-period records, one currency per statement. Read one statement and page through its line operation to reconcile merchant transactions and fee adjustments against your own verified event records.

list-statements.sh
curl --request GET \
--url https://staging.api.maxanapay.com/api/channel/statements \
--header 'Authorization: Bearer sk_test_replace_me'

An empty array is the expected answer on a channel that has been trading for less than a period. A statement is a record of a period Maxana has closed, so the first one exists only once a period containing your traffic has been closed and issued; there is no operation that produces one earlier, and payments you can already see in GET /api/transactions are not evidence that a statement is late. Reconcile from your verified event records until one appears.

Each statement stores the terms used when it was issued. A later commercial change does not rewrite an earlier statement, and a correction links the replacement to the superseded record. Treat captured volume and settlement as different facts, and never combine money totals across currencies.

The channel API does not set merchant pricing or channel fee-share terms. Those commercial terms are agreed with Maxana and then reported on issued statements. Statements are not real-time balance endpoints, and the refund response is not a statement or remittance record.

The channel journey is complete. Use the shared API operation reference for exact schemas and security alternatives.