Skip to content

Card Declines

Beta

The Card Declines API is in Beta. Additive changes are normal, and breaking changes may be made with notice while the resource incorporates customer feedback. See Versioning and compatibility.

The Transactions API tells you a card payment failed. This resource tells you why, in words you can hand to whoever is asking.

GET /api/v1/transactions/{transaction_id}/declined-authorizations

Every declined attempt on a card transaction comes back with the reasons it was declined, a plain-language explanation, and the recommended_actions a person can take. The wording matches what the card decline email tells the cardholder, so the API and the email give the same answer.

When a transaction has declines

Card transactions can carry a declined attempt and still be pending or settled. A merchant that raises an authorization mid-stay - a hotel, a car rental, a fuel pump - sends an incremental authorization, and that increment can be declined after the first one succeeded. So the resource gates on transaction type, not on status, and you should not assume status: failed is the only place declines live.

SituationResponse
A card transaction with declined attempts200 with one entry per attempt, oldest first
A card transaction where nothing was declined200 with declined_authorizations: []
A transaction that is not a card transaction400 - wires, ACH, and checks cannot carry card declines
No transaction with that id in your business404
Cards data could not be read503

transaction_id is the same identifier GET /api/v1/transactions returns, and this sub-resource lives on the same v1 surface as its parent transaction.

What an attempt carries

FieldWhat it tells you
amountThe amount of this authorization attempt, in minor units. This is the attempt's own amount, not the transaction's net amount - an incremental authorization is worth less than the transaction it belongs to.
reasonsWhy the attempt was declined. Never empty. More than one reason can apply to a single attempt: a card can hit its own limit and a blocked merchant category in the same authorization.

Each reason carries three things:

FieldWhat it tells you
codeA stable identifier such as card_locked or card_limit_reached.
explanationOne or two sentences a person can read, matching what the decline email tells the cardholder. Constant per code, and carries no transaction data.
recommended_actionsWhat to do next, in the order to try it. Empty when there is no customer-side remedy - a cash withdrawal is declined because no Rho card supports one, and there is nothing to change.

Common workflows

Answering "why did this decline"

curl "https://rhoapi.rho.co/api/v1/transactions/{transaction_id}/declined-authorizations" \
  -H "Authorization: Bearer $RHO_API_TOKEN"
{
  "declined_authorizations": [
    {
      "amount": { "amount": 10000, "currency": "USD" },
      "reasons": [
        {
          "code": "card_locked",
          "explanation": "Your card was declined because it's locked.",
          "recommended_actions": [
            {
              "code": "unlock_card",
              "description": "Unlock your card to continue using it. You can do it on the card's detail page in your Rho dashboard or mobile app."
            }
          ]
        }
      ]
    }
  ]
}

Showing declines alongside a transaction list

There is no batch path. List transactions, keep the card ones you care about, and call this resource per transaction. That is one extra call each, which is fine for a support lookup on a handful of transactions and worth telling us about if you are doing it across a whole page.

Scopes

transactions:read. This is a sub-resource of a transaction the token can already read, so it needs no second grant.

Reference

Full endpoint catalogue - paths, parameters, response shapes, and the complete code lists - lives in the API Reference.