Idempotency and Outcome Recovery

Persist a client-generated event_id before submitting each payment operation that exposes one. Retain it with your order and the returned transaction_id. A new event ID represents a new operation; it is not a way to retry an uncertain payment.

Identifiers

Identifier Purpose
event_id Identifies one operation, such as a sale, capture, or refund
transaction_id Groups the original payment and its follow-up events

Generate a UUID4 for event_id. Save it durably before the request leaves the device or backend. Keep the outcome and identifiers for reconciliation after app restarts. If you omit it, Koard can generate an ID, but a lost response then leaves your client without the lookup identifier.

SDK arguments vary by released platform version. For example, iOS capture accepts eventId, while Android 1.0.7 capture and tip adjustment do not expose that argument. Follow the platform-specific API instead of inventing an argument.

Duplicate Responses

A duplicate event ID is rejected with HTTP 400 and the stable error code duplicate_event_id. Look up that event's outcome; do not treat the duplicate error as a decline or generate a new ID to submit again. Branch on error, not human-readable details text.

Look Up an Event

Your backend can query:

curl 'https://api.uat.koard.com/v1/transactions/event/YOUR_PERSISTED_EVENT_ID' \
  -H 'X-Koard-apikey: YOUR_API_KEY'

Requires payments:read and access to the account owning the event. Keep backend API keys out of shipped apps; expose an authenticated recovery endpoint through your backend if needed.

Response Action
200 with a completed operation Reconcile the transaction status, amounts, and processor response with your order
200 with pending Keep the operation unresolved and poll with bounded backoff
200 with surcharge_pending Complete the supported cardholder confirmation flow; polling alone does not confirm the surcharge
404 No visible committed event was found. The request may still be in flight, or your key may be querying the wrong account or environment
Authentication or permission failure Correct access; do not infer a payment outcome from this response
Lookup timeout or server error Keep the outcome unresolved and retry the lookup with backoff

A 404 does not prove the original POST never reached the processor. Do not immediately resubmit, switch event IDs, or replay one-time EMV reader data or cryptograms based solely on a missing lookup result.

Recovery Sequence

  1. Save the operation's event ID, order, intended amount, merchant account, location, and environment before submitting.
  2. Submit once through the supported SDK or REST endpoint.
  3. Inspect a successful response's transaction status and amounts. Pending states, partial approvals, and recorded errors need their appropriate follow-up; HTTP 2xx alone is not enough.
  4. For a duplicate event, timeout, lost response, or server error, stop automatic payment retries and look up the saved event ID.
  5. Poll with bounded backoff, for example 1, 2, 5, 10, and 30 seconds. Reconcile against your signed webhook deliveries and processor reports when available.
  6. If the outcome remains unresolved, retain the identifiers and flag the order for investigation. Start a new reader session or operation only after resolving the previous outcome through the supported recovery process.

Duplicate detection is a safeguard, not a promise that concurrent or in-flight retries are safe. Avoid parallel submissions of the same operation.

Webhook Reconciliation

Verify webhook signatures and deduplicate by delivery ID. Transaction bodies include event_id and transaction_id; store them with the event outcome. A webhook mirror in your backend can support recovery when the app cannot reach Koard, but delayed or missing webhook delivery is not evidence of failure.

See Payment Lifecycle, Available Events, and Webhook Setup.