Merchant-initiated flows
Certification cases for MIT Async Purchase, MIT Async Authorize, and Sync MIT.
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.
5. MIT Async Purchase
Applies to: MIT-ASYNC-PURCHASE. /evaluate returns SUBMITTED; the outcome arrives by webhook. Hold the merchant order pending, not paid and not declined, and pause your own retries until a terminal event arrives. When a webhook is missed, GET /v1/orders/{id} returns the same numeric status and statusName as the event. The base MIT payload omits expiryDateUtc, so MIT-ASYNC-PURCHASE-01 also proves that the default expiry configured for the merchant is applied.
Reference: Workflows §2.3, Webhooks, GET /orders/{id}, Appendix A.2.
| ID | Scenario | Setup / action | Expected result | Evidence |
|---|---|---|---|---|
| MIT-ASYNC-PURCHASE-01 | Submitted | Base MIT payload | HTTP 200; result Success; status SUBMITTED; orderId present. GET /v1/orders/{orderId} returns status 0 Draft or 4 Processing | orderId |
| MIT-ASYNC-PURCHASE-02 | Rescue approved | Wait for the MIT-ASYNC-PURCHASE-01 order to resolve | order.completed received; GET /v1/orders/{orderId} returns status 7 Completed | Webhook IdempotencyKey |
| MIT-ASYNC-PURCHASE-03 | Rescue declined | Base MIT payload with card 4012888888881881 | order.cancelled received; GET /v1/orders/{orderId} returns status 2 Cancelled | Webhook IdempotencyKey |
| MIT-ASYNC-PURCHASE-04 | Rescue window expires | Base MIT payload with expiryDateUtc set 15 minutes in the future | order.expired received after the window; GET /v1/orders/{orderId} returns status 2 Cancelled | Webhook IdempotencyKey |
| MIT-ASYNC-PURCHASE-05 | Expiry beyond 21 days | Base MIT payload with expiryDateUtc set 30 days in the future | HTTP 400 with an errors object naming expiryDateUtc | traceId |
Onhold is a pending state
Onhold(status1) can appear onGET /v1/orders/{id}when the merchant processing cap is reached. No webhook is sent for it; the order resumes on its own. Treat it as pending.
6. MIT Async Authorize
Applies to: MIT-ASYNC-AUTHORIZE. Same payload as MIT Async Purchase with transactionType: "AUTHORIZATION". The approval arrives as order.capturerequired, and you must call /capture within the capture window. Run the capture cases in Section 8 and the cancel cases in Section 9 after this section.
Reference: Workflows §2.4, /capture, Appendix A.2, Appendix A.3.
| ID | Scenario | Setup / action | Expected result | Evidence |
|---|---|---|---|---|
| MIT-ASYNC-AUTHORIZE-01 | Submitted | Base MIT payload with transactionType AUTHORIZATION | HTTP 200; status SUBMITTED; orderId present | orderId |
| MIT-ASYNC-AUTHORIZE-02 | Capture required | Wait for the MIT-ASYNC-AUTHORIZE-01 order to resolve | order.capturerequired received; GET /v1/orders/{orderId} returns status 5 Capturerequired | Webhook IdempotencyKey |
| MIT-ASYNC-AUTHORIZE-03 | Capture on receipt | POST /v1/capture for the full amount within the capture window after MIT-ASYNC-AUTHORIZE-02 | HTTP 200; status SUCCESS; GET returns status 7 Completed; totalBalancePaid equals the authorized amount; order.completed received | orderId |
| MIT-ASYNC-AUTHORIZE-04 | Declined | Base MIT payload with transactionType AUTHORIZATION and card 4012888888881881 | order.cancelled received; GET returns status 2 Cancelled | Webhook IdempotencyKey |
| MIT-ASYNC-AUTHORIZE-05 | Capture after the window | Repeat MIT-ASYNC-AUTHORIZE-01 and MIT-ASYNC-AUTHORIZE-02, wait longer than the capture window, then capture | HTTP 400; no funds captured. order.expired received; GET returns status 2 Cancelled | Capture response, webhook IdempotencyKey |
7. Sync MIT
Applies to: SYNC-MIT. The first /evaluate always returns DECLINED. Each later retry for the same merchant orderId returns DECLINED until the rescue lands, then APPROVED. The retry that returns APPROVED performs the capture. The rescue window is configured per account in hours from the decline, and the cutoff is hard. Ask your Solutions engineer how the sandbox resolves the rescue for this flow before running SYNC-MIT-03.
Three integration rules apply to this flow. Every retry carries the same merchant orderId and an attemptCount that increases by 1. FlexFactor must be the only retry mechanism during the rescue window: no other retry engine, cascade, re-authorization, or account updater runs for the merchant. At least 1 merchant retry must fall inside the window, or the integration must capture on order.capturerequired as in SYNC-MIT-04.
Reference: Workflows §2.5, Appendix A.2.
| ID | Scenario | Setup / action | Expected result | Evidence |
|---|---|---|---|---|
| SYNC-MIT-01 | Initial call declined | Base MIT payload, expiryDateUtc omitted | HTTP 200; status DECLINED | Response body |
| SYNC-MIT-02 | Retry during processing | Repeat SYNC-MIT-01 with the same merchant orderId, the same amount, the same payment method, and attemptCount increased by 1, before the rescue lands | HTTP 200; status DECLINED. GET /v1/orders?query={merchant orderId} returns exactly 1 order | Order count |
| SYNC-MIT-03 | Retry captures the rescue | Repeat the SYNC-MIT-01 request after the rescue lands | HTTP 200; status APPROVED; orderId present. GET /v1/orders/{orderId} returns status 7 Completed | orderId |
| SYNC-MIT-04 | Webhook backstop with explicit capture | Repeat SYNC-MIT-01. On order.capturerequired, call POST /v1/capture for the full amount instead of waiting for the next retry | HTTP 200; status SUCCESS; GET returns status 7 Completed | orderId, webhook IdempotencyKey |
| SYNC-MIT-05 | Window expires | Repeat SYNC-MIT-01 and send no further call until the configured window has passed, then retry | HTTP 200; status DECLINED; order.expired received; GET returns status 2 Cancelled | Webhook IdempotencyKey |
Updated about 8 hours ago

