Payments

Statuses and projections

Why a payment status is a projection, the finality outcomes, and the duplicate-payment caveat.

Every status Tekmerion exposes for a payment is a projection of canonical on-chain truth. It is derived, it may lag, and it is never authoritative on its own. The authoritative record is the finalized on-chain outcome — surfaced as a finality_outcome — and the signed Proof-of-Payment.

Status is a projection, not truth

A status describes where a payment sits in its expected lifecycle. It is rebuilt from canonical finalized outcomes and can change as on-chain truth is confirmed. A status MUST NOT be treated as settlement truth. Reconcile through the API and the Proof-of-Payment, not through a status read or a received notification.

One settlement per intent

A payment_intent_id is settled at most once. When more than one finalized, matched payment exists for the same intent, exactly one is the canonical winner, selected deterministically — independent of arrival order, delivery order, or timing. The winner settles the intent; every other finalized match for that intent is recorded as duplicate_payment and is not an additional settlement.

Finality outcomes

At finality, a payment carries one canonical finality_outcome:

finality_outcomeMeaning
paidThe deposit was swept to the merchant's approved destination; the protocol fee was collected on-chain.
refundedThe merchant returned a reject decision with a refund destination; the deposit was refunded; the protocol fee was collected on-chain.
failedThe payment reached a terminal failure state without settlement or merchant-directed refund. No funds moved.
duplicate_paymentA finalized, matched payment for an intent that was already settled. The intent's settlement is unaffected.

Status maps to outcome

Statusfinality_outcomeMeaning
PAIDpaidSwept to the merchant; the intent is settled.
REFUNDEDrefundedThe merchant rejected; the deposit was refunded.
FAILEDfailedTerminal failure; no funds moved.
FAILEDduplicate_paymentThe payment lost winner selection; the intent is already settled. Not a failed payment.
EXPIREDThe expected window elapsed without a confirmed deposit. A late deposit may still settle.
HELDHeld pending compliance or operational resolution. Not terminal; not an outcome.

FAILED is not always a failed payment

This is the central caveat. A status of FAILED carrying finality_outcome duplicate_payment means the payment lost the deterministic winner selection for its intent. The payment_intent_id is already PAID through the winning payment, and the merchant has received funds. It does not mean the customer's payment was invalid or that money was not received.

Correlate by payment_intent_id, not by a per-attempt status. A FAILED payment with finality_outcome duplicate_payment is a signal to reconcile an extra on-chain payment — not a signal that a payment did not go through.

The notification plane carries a parallel signal

The same events surface as notifications, where the field that selects meaning is notification_class:

notification_classfinality_outcomeWhen
payment_observednullDeposit observed on-chain at the observed threshold. Progress, not settlement.
payment_finalizedpaid | refunded | failedA terminal outcome was finalized.
payment_heldnullThe payment is held; no funds moved and no outcome is finalized.
duplicate_payment_incidentnullAn additional finalized payment was detected for an already-settled intent.

Note the asymmetry between the two planes. On the notification plane, a duplicate is its own class — duplicate_payment_incident, with finality_outcome null — delivered alongside the canonical payment_finalized (paid) record. On the status projection, the same event surfaces as status FAILED with finality_outcome duplicate_payment. Both describe one fact: an extra payment on an already-settled intent. Full notification rules are in the Event catalog.

On this page