Codex · III

Statuses & refunds

Transaction statuses

Each transaction row in the dashboard has one of these statuses. The status reflects the most recent event for that transaction; refunds and disputes update the existing row rather than inserting a sibling.

StatusMeaning
succeededPayment completed. Money is in your account (net of provider fees).
pendingPayment is in flight. Common with async payment methods (ACH, some crypto rails) where confirmation takes minutes to hours.
failedPayment did not complete: card declined, expired auth, hard rejection. No money moved.
partialBuyer paid less than invoiced (common when a crypto buyer sends a network-fee-reduced amount). The row's amount reflects what was actually received; check metadata.invoicedAmount for what was requested.
refundedMoney has been returned to the buyer, fully or partially. The row's amount is the refunded amount; refunds can happen days or weeks after the original payment.
disputedThe buyer (or their bank) opened a dispute or chargeback. Check the provider's interface for the response window. The row's metadata.reason carries the provider's classification verbatim.
pending_manualA pay-by-mail transaction is awaiting your physical confirmation. See the next section.
manual_canceledYou clicked Cancel on a pending pay-by-mail row before the buyer's payment arrived.
manual_expiredA pending pay-by-mail row sat for 30 days without confirmation and auto-expired.
manual_revokedYou confirmed receipt of a pay-by-mail payment but later undid the confirmation (e.g., the payment turned out to be invalid). The row moves from succeeded back to this terminal state.

Refunds, disputes, partial payments

Coin Moebius listens for these provider events and updates the original transaction row in the dashboard. Specifically:

  • Refunds: Stripe's charge.refunded event (full or partial refunds, including amount_refunded so partial refunds show the slice that was returned). NOWPayments' refunded IPN. The row's status flips to refunded, the amount reflects the refunded amount, and metadata.originalChargeId / metadata.originalAmount carry the original payment context.
  • Disputes (chargebacks): Stripe's charge.dispute.created event. The row's status flips to disputed. The provider's stated reason passes through to metadata.reason verbatim, you can render it in your own UI however you choose.
  • Partial payments: NOWPayments' partially_paid IPN. The row's status flips to partial. The amount reflects what was actually received (actually_paid); metadata.invoicedAmount is what was requested.

In v1, these events are surfaced in the dashboard and via the /status endpoint. A future release will add email notifications and an outbound webhook forwarder so your own backend can react automatically. For now, set up a small polling job (see the next section) or check the dashboard.

Ready to wire it up?

Free tier covers most sites and never asks for a card.