Skip to content

Complete payment flow

Checkout sequence

StepEndpointNext action
1. MethodsGET /v2/payment-methodsSend customer ID; display available and saved payment methods.
2. CalculatePOST /v2/orders/calculateSend items, method, and customer fee percent; confirm the returned total.
3. OrderPOST /v2/ordersCreate once; save order_id. No charge starts.
4. PaymentPOST /v2/paymentsSend order ID, payer, return URL, method, and confirmed amount. Follow the returned action.
5. ResultsWebhooksTrack collection, per-unit fulfillment, and order-level refunds.

For direct card entry, the client form sends input through your backend. A returned redirect may be for 3DS rather than card entry. Browser return or successful authentication is not proof of collection; use verified status from webhooks or API reads.

Other operations

PurposeEndpoint
Calculate before retrying paymentPOST /v2/orders/calculate with order_id instead of items
Cancel an eligible pending paymentPOST /v2/payments/{payment_id}/cancel
Read collection statusGET /v2/payments/{payment_id}
Read fulfillment and refundsGET /v2/orders/{order_id}
Retrieve order historyGET /v2/orders

See Calculate Order, cancellation, and result reads. There is no order cancellation or public refund-submission endpoint.

Retries and idempotency

Order and payment creation require a unique Idempotency-Key. Reuse it when retrying the same request. Order external_reference must also remain unique within your account.

Keys are scoped per endpoint: an order-creation key and a payment-creation key do not conflict with each other. A key is bound once the API accepts the request (2xx or 202); rejected requests (4xx) do not consume it. A bound key replays indefinitely for the lifetime of the resource.

SituationAction
Order creation or hosted/saved-method payment creation loses its responseRetry with the same key and body, using fresh HMAC headers. Never create a new key merely because the response was lost.
An admitted request is replayedThe original response is returned, not current state. Read the resource before using a replayed redirect. Changed bound contents return idempotency_conflict.
Request was rejected (4xx)The key is not consumed. Correct the fields and retry with the same key, or use a new key. Either is safe.
Payment returns total_mismatchNo payment was created. Confirm error.details.calculation.totals.payment_total, then submit the corrected request with a new key.
Payment is pending, processing, or cancellation is unresolvedDo not create another attempt. Read latest_payment_id from the order, then check that payment's status.
Payment is confirmed failed, cancelled, or expiredRecalculate, confirm, then use the same unpaid order and a new payment key. The new attempt supplies its own payer, method, share, and return URL.

Direct full-PAN recovery has additional restrictions: never persist sensitive card input for retries.

Payment expiry

Each payment link is usable for 30 minutes. After that, check the payment status before retrying:

  • Still processing: wait. The payment may already have been collected.
  • Failed, cancelled, or expired: calculate again, confirm the total, and create a new payment for the same unpaid order.

The order stays available for payment. Its item prices stay the same; payment fees may change. If an extra payment is collected, it is refunded rather than fulfilling the order twice.

Shared errors

Error responses use this envelope; endpoint-specific tables describe additional codes.

FieldTypeDescription
error.codestringMachine-readable error code.
error.messagestringSafe explanation.
error.request_idstringReference for support.
error.detailsobject or arrayReturned only where documented: validation, duplicate reference, or total mismatch.
HTTPCodeAction
400invalid_requestCorrect malformed JSON or request format.
401Authentication errorCheck the signing headers.
429rate_limitedHonor Retry-After or use bounded backoff.
503service_unavailableBack off; preserve creation keys and follow the retry rules above.

Validation details

FieldTypeDescription
error.details[].fieldstringField path, including array position when relevant.
error.details[].codestringrequired_field, invalid_field, or a product validation code.
error.details[].messagestringHow to correct the field; never echoes card input.
json
{
  "error": {
    "code": "validation_error",
    "message": "The request contains invalid fields.",
    "request_id": "req_example",
    "details": [
      {
        "field": "items[0].account",
        "code": "invalid_account",
        "message": "Check the account number."
      }
    ]
  }
}

If any item is invalid, calculation returns the field errors instead of a total. Correct the listed fields and calculate again.

IIMMPACT API Documentation