Get started
Test the full flow
A payment integration must handle more than the success path. Test each case below in sandbox.
Before you test#
Use a sandbox API key and a sandbox webhook endpoint. The sandbox checkout page accepts test payment details only. No real money moves, and no live data changes.
Test cases#
| Case | How to cause it | What your integration must do |
|---|---|---|
| Successful payment | Pay a session with test payment details. | Fulfil once, after payment.succeeded or transaction.completed. |
| Failed payment | Pay with sandbox test payment details that are refused. | Do not fulfil on payment.failed. Let the buyer try again. |
| Buyer cancels | Cancel on the hosted page. | Expect the buyer at cancelUrl, and checkout.expired with status cancelled. Release anything that you held. |
| Session expires | Call Expire a checkout session, or wait for expiresAt. |
Handle checkout.expired. Create a new session if the buyer returns. |
| Duplicate event | Send one stored, signed event body to your endpoint twice. | Process it once. Return 2xx both times. |
| Events out of order | Handle checkout.completed before payment.succeeded, then the reverse. |
Reach the same final state in both orders. |
| Refund | Refund a sandbox payment. | Handle refund.succeeded or refund.failed. |
| Lost response | Repeat a create request with the same Idempotency-Key. |
Receive the first result, not a second resource. |
Expire a session#
curl -X POST https://api.merxian.com/v1/checkout-sessions/cs_6HvB2nQx9LmT4kWpR/expire \
-H "Authorization: Bearer $MERXIAN_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"This needs the checkout:write scope. A complete or cancelled session returns 409.
Refund a payment#
curl -X POST https://api.merxian.com/v1/payments/pay_3RtN6wYc8mK2hQvJd/refunds \
-H "Authorization: Bearer $MERXIAN_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "amount": { "amountMinor": 5000, "currency": "EUR" } }'This refunds €50.00 and needs the payments:refund scope. The response is 202 with the refund in the requested state. The result arrives as refund.succeeded or refund.failed. See Refund a payment.
When all cases pass#
Run the integration checklist. Then read Go live.