Capture, cancel, and refund

Certification cases for /capture, /cancel, and /refund.

Part of the Certification guide. Mark your scope on that page before you run these cases. Base payloads and test cards are on the Reference page.


8. Capture

Applies to: CIT-AUTHORIZE, MIT-ASYNC-AUTHORIZE, SYNC-MIT. /capture requires idempotencyKey, the FlexFactor orderId, amount in cents, and currency. The amount and currency must match the authorization. A double capture is always prevented on the combination of orderId, amount, and currency.

The response status is the capture outcome: SUCCESS or FAILED. result is always null on this endpoint, and success stays true when the processor declines the capture, so key your logic on status alone. The full capture is proved by CIT-AUTHORIZE-02, MIT-ASYNC-AUTHORIZE-03, or SYNC-MIT-04; the cases below reuse that order or a new authorization from the same flow.

Reference: /capture, /capture HTTP status codes, Appendix A.3.

IDScenarioSetup / actionExpected resultEvidence
CAPTURE-01Replay with the same keyRepeat the capture from CIT-AUTHORIZE-02, MIT-ASYNC-AUTHORIZE-03, or SYNC-MIT-04 with the same idempotencyKeyHTTP 200; the original response is replayed; GET shows one capture in activityItemsBoth responses
CAPTURE-02Double capture with a new keyRepeat the same capture with a new idempotencyKeyHTTP 400; no second capture; totalBalancePaid is unchangedResponse, order balance
CAPTURE-03Unknown orderIdCapture with a random GUIDHTTP 404 with an empty bodyHTTP status
CAPTURE-04Missing idempotencyKeyCapture with idempotencyKey omittedHTTP 400 with an errors object naming idempotencyKeytraceId
CAPTURE-05Amount does not match the authorizationAuthorize 9900 cents, then capture 6000 cents, then capture 12000 centsHTTP 400 both times; GET still returns status 5; totalBalancePaid is unchangedResponses, order balance
CAPTURE-06Currency mismatchCapture with a currency that differs from the authorizationHTTP 400; GET still returns status 5; totalBalancePaid is unchangedResponse, order balance
CAPTURE-07Capture a completed orderCapture a Completed orderHTTP 400; GET still returns status 7 with an unchanged balanceResponse
📘

Partial capture is not available

The capture amount must equal the authorized amount. CAPTURE-05 proves that a lower amount is rejected. To return part of a charge after capture, use /refund with a partial amount. Partial voids are planned; check the changelog for release details.


9. Cancel

Applies to: CIT-AUTHORIZE, MIT-ASYNC-PURCHASE, MIT-ASYNC-AUTHORIZE, SYNC-MIT. Cancel is a void. It applies to MIT orders in any state other than Completed or Cancelled (Draft, Onhold, Processing, Capturerequired) and to CIT orders in Capturerequired or Onhold. A captured order must be refunded instead. The only accepted body field is the optional idempotencyKey; there is no amount or currency field, and a cancel always applies to the full order amount.

A cancel returns HTTP 200 with { "success": true, "responseMessage": null }. There is no status field. The same body is returned when the order was not in a cancellable state and nothing changed, so a 200 does not by itself prove that the order was cancelled. Mark the order cancelled only after GET /v1/orders/{id} returns status 2 or order.cancelled arrives.

Reference: /cancel, /cancel response, Workflows §2.6.

IDScenarioSetup / actionExpected resultEvidence
CANCEL-01Cancel a CIT authorization (CIT-AUTHORIZE)POST /v1/orders/{orderId}/cancel with {} on a Capturerequired CIT orderHTTP 200 with { "success": true, "responseMessage": null }; GET returns status 2 Cancelled; order.cancelled received when WEBHOOKS is InorderId
CANCEL-02Capture after cancel (CIT-AUTHORIZE, MIT-ASYNC-AUTHORIZE)Capture the CANCEL-01 orderHTTP 400; no capture occurs; GET still returns status 2Response
CANCEL-03Cancel a pending MIT order (MIT-ASYNC-PURCHASE, MIT-ASYNC-AUTHORIZE, SYNC-MIT)Cancel an order in Draft or ProcessingHTTP 200 with { "success": true, "responseMessage": null }; order.cancelled received; GET returns status 2Webhook IdempotencyKey
CANCEL-04Cancel an MIT authorization (MIT-ASYNC-AUTHORIZE)Cancel an order after order.capturerequired and before captureHTTP 200; GET returns status 2; no funds captured; order.cancelled receivedorderId
CANCEL-05Cancel by external order IDPOST /v1/orders/{external-order-id}/external-cancel with your merchant orderId on a pending orderHTTP 200 with the same body; GET returns status 2Response
CANCEL-06Cancel that changes nothingRepeat CANCEL-01 on the same order, then cancel an order in status 7 CompletedHTTP 200 with the same body both times; the first order remains status 2 and the second remains status 7; no order.cancelled event; nothing is refundedResponses, webhook count
CANCEL-07Cancel an unknown orderCancel with a random GUIDHTTP 404 with an empty bodyHTTP status
📘

Partial cancel is not available

A cancel releases the full order amount. The request body accepts no amount or currency field. Partial voids are planned; check the changelog for release details.


10. Refund

Applies to: CORE. amountToRefund is in dollars, not cents. Full refunds are de-duplicated by order ID. Partial refunds are not, so every partial refund must carry an idempotencyKey. FlexFactor refunds the cardholder directly and adjusts merchant settlement, so a refund on a rescued order must call /refund and must not go to the original processor.

The response status is the refund outcome: SUCCESS or FAILED. result is always null on this endpoint. A failed refund normally returns HTTP 200 with status FAILED and success false. A refunded order stays at status 7 Completed; GET /v1/orders/{id} reports the refunded total in refundsAmount, in dollars, and order.refunded carries EventData.Amount in cents.

Reference: /refund, /refund HTTP status codes, Workflows §2.7, Appendix A.4.

IDScenarioSetup / actionExpected resultEvidence
REFUND-01Full refundPOST /v1/orders/{orderId}/refund with amountToRefund 99.00 on a Completed 9900-cent orderHTTP 200; status SUCCESS; success true; transactionId present; order.refunded received with Amount 9900; GET returns status 7 Completed and refundsAmount 99.00orderId, webhook IdempotencyKey
REFUND-02Full refund duplicate without a keyRepeat REFUND-01 on the same order with no idempotencyKeyNo second credit; refundsAmount stays 99.00; one order.refunded event in totalOrder record, webhook count
REFUND-03Partial refundamountToRefund 25.00 with idempotencyKey K1 on a new Completed 9900-cent orderHTTP 200; status SUCCESS; order.refunded with Amount 2500; GET returns status 7 and refundsAmount 25.00orderId
REFUND-04Partial refund retry with the same keyRepeat REFUND-03 with K1HTTP 200; the original response is replayed; refundsAmount stays 25.00Both responses
REFUND-05Second distinct partial refundamountToRefund 25.00 with a new key K2 on the REFUND-03 orderHTTP 200; refundsAmount 50.00; a second order.refunded eventWebhook IdempotencyKey
REFUND-06Refund above the remaining balanceamountToRefund 60.00 on the REFUND-05 order (49.00 remains)HTTP 400; refundsAmount stays 50.00traceId
REFUND-07Refund an order that is not completedRefund an order that is not in status 7, for example a cancelled order from Section 9 or the declined CIT-PURCHASE-02 orderThe refund is not applied: HTTP 400, or HTTP 200 with status FAILED. Record whichResponse
REFUND-08Refund an unknown orderRefund with a random GUIDHTTP 404HTTP status


Did this page help you?