failed, and Melio settles the money automatically. Here is what happens and how to recover.
What can fail
- Collection - the debit from your internal (funding) account does not go through.
- Delivery - the funds cannot be delivered to the payee, or the transfer is returned.
- Risk review - the payment is declined before any money moves. See Payment lifecycle.
How Melio handles it
Melio does not automatically retry a failed payment. To try again, create a new payment.
The failureReason object
A payment with status: "failed" carries a failureReason object explaining why. It is absent on every other status.
Failure types
This set is fixed - every failure is one of these three.Failure codes
Codes are named after the industry code that produced them, so a code can be matched against a bank return without a translation table:R##_*- a NACHA ACH return code.CARD_*- an ISO 8583 card issuer decline.
Always read
code together with type. The same ACH return can arrive on either leg, so R02_ACCOUNT_CLOSED means your account under failed-to-collect and the payee’s account under failed-to-deliver.ACH return codes
Can appear underfailed-to-collect or failed-to-deliver.
Card decline codes
Appear underfailed-to-collect only, since only the payer funds a payment with a card.
Delivery outcomes
Appear underfailed-to-deliver only. These have no industry code behind them.
Risk decline codes
Appear underrisk-declined only.
A decline is reported as the bare
RISK_DECLINED whenever the underlying reason cannot be disclosed. It does not mean the reason is unknown, and you should not infer anything from it beyond the payment having been declined.Generic codes
Eachtype has one generic code, reported when the specific reason is unavailable or cannot be disclosed. These are the codes to fall back to when you receive one you do not recognize.
RISK_DECLINED is listed under Risk decline codes as well. It is the only code that serves both roles: a reason in its own right and the generic for its type. The two are indistinguishable by design, so never treat its presence as meaning the reason was unavailable.
Handling codes safely
Newcode values are added over time as payment rails and review rules change. To stay forward-compatible:
- Branch on
typefirst. The three types are fixed and cover every failure. - Then branch on the
codevalues you care about. - Treat an unrecognized
codeas the generic code for itstype-COLLECTION_FAILED,DELIVERY_FAILEDorRISK_DECLINED- rather than as an error. - Never parse
message. Show it to a user if useful, but do not match on it.
How you find out
Melio sendsapi.payment.updated; fetch the payment to see it is now failed and read its failureReason.
How to recover
There is no retry on the same payment; recovery is always a newPOST /payments. What to fix first depends on the type:
Test failures in the sandbox
Drive a payment tofailed in a non-production environment with the simulation endpoint, so you can build and verify your handling before going live. It is available in non-production only and returns 404 in production.
fail-collect for a collection failure, fail-deliver for a delivery failure, and risk-decline for a risk decline. action is the only required field; an optional metadata object is echoed to logs and not persisted on the payment. No other fields are accepted - the request is rejected with 400 VALIDATION_ERROR if you send one.
The simulation controls which
type you get, not which code. Use it to verify that your handling reacts correctly to each type and to an unrecognized code; it is not a way to reproduce a specific ACH return.Related: an undeposited check is automatically voided after 90 days, and the payment is refunded like any other delivery failure. It is reported as
CHECK_RETURNED.