Fix a payee that failed setup

Read why a payee came back setup_failed, correct it in place with PATCH, and pay it without saving a duplicate.

Read why a payee came back setup_failed, correct it in place with PATCH, and pay it without saving a duplicate. A payee is an external account, a bank account outside Gravv that a customer pays. See the Glossary.

Who it is for. Any business whose SEPA, Faster Payments, SWIFT or US payee came back setup_failed.

Status. Available.

Money example

  1. A SWIFT payee for a 7,500.00 USD supplier payment fails setup with error_message these account details could not be accepted.
  2. The supplier confirms that the account number ends in 8, not 9.
  3. You correct the payee. It goes back to pending, then active, and you send the 7,500.00 USD.

Before you start

You need the payee id. You cannot save the same payee again. A failed payee still counts as a duplicate, so a new create request returns the failed payee's id.

Find out what is required

Read the payee and its error_message:

curl --request GET \
 --url https://api.gravv.xyz/v1/external-accounts/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
 --header 'Api-Key: <API_KEY>'
const response = await fetch("https://api.gravv.xyz/v1/external-accounts/f47ac10b-58cc-4372-a567-0e02b2c3d479", {
method: "GET",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
},
});
console.log(response.status, await response.json());
import os

import requests

response = requests.get(
"https://api.gravv.xyz/v1/external-accounts/f47ac10b-58cc-4372-a567-0e02b2c3d479",
headers={
    "Api-Key": os.environ["GRAVV_API_KEY"],
},
)
print(response.status_code, response.json())
{
  "data": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "payee_type": "swift",
    "account_number": "1012345679",
    "account_name": "ADEBAYO TEXTILES LTD",
    "bic": "ZEIBNGLA",
    "customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "currency": "USD",
    "account_owner_type": "business",
    "status": "setup_failed",
    "date_created": "2026-10-13T10:00:00.000Z",
    "error_message": "these account details could not be accepted"
  },
  "error": null
}
error_message What to do
these account details could not be accepted (sometimes … for the <rail> rail) A detail is wrong. Check each field with the payee
account setup did not complete (attempt N of 10) Setup kept failing to complete. Check the fields, or retry with no changes
recipient setup failed Check the fields, or retry with no changes

Steps

1. Correct the payee

Send only the fields that change. Gravv keeps a field you leave out, clears a field you send as null, and sets a field you send with a value. Never send "" to clear a field. PATCH needs no Idempotency-Key.

curl --request PATCH \
 --url https://api.gravv.xyz/v1/external-accounts/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
 --header 'Api-Key: <API_KEY>' \
 --header 'Content-Type: application/json' \
 --data '
{
"account_number": "1012345678"
}
'
const response = await fetch("https://api.gravv.xyz/v1/external-accounts/f47ac10b-58cc-4372-a567-0e02b2c3d479", {
method: "PATCH",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"account_number": "1012345678"
}),
});
console.log(response.status, await response.json());
import os

import requests

response = requests.patch(
"https://api.gravv.xyz/v1/external-accounts/f47ac10b-58cc-4372-a567-0e02b2c3d479",
headers={
    "Api-Key": os.environ["GRAVV_API_KEY"],
    "Content-Type": "application/json",
},
json={
    "account_number": "1012345678",
},
)
print(response.status_code, response.json())
{
  "data": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "payee_type": "swift",
    "account_number": "1012345678",
    "account_name": "ADEBAYO TEXTILES LTD",
    "bic": "ZEIBNGLA",
    "customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "currency": "USD",
    "account_owner_type": "business",
    "status": "pending",
    "date_created": "2026-10-13T10:00:00.000Z"
  },
  "error": null
}

To retry setup with no changes, for example after attempt 10 of 10, send {}.

2. Wait for the new setup

The PATCH itself sends no event. Wait for external_account.active, or for external_account.setup_failed again. Then pay the payee as its recipe describes.

What can go wrong

Response Why Fix
409 payee <id> is not correctable in its current state (active): invalid state transition You can change banking details only on a setup_failed payee, or on a pending payee whose setup has not started Save a new payee
409 the same message with (pending) Setup has already started Wait for active or setup_failed
409, duplicate The corrected details match another payee Use that payee
409 the address of payee <id> cannot be changed: it is already registered for payouts; create a new payee with the new address Gravv locked the address when it registered the payee for payouts Save a new payee
409 payee <id> was changed by another request while this update was applied; reload it and retry: invalid input Two updates ran at the same time Read the payee, then PATCH again
400 account name cannot be cleared: invalid input You sent "account_name": null Send a value
404 payee <id>: resource not found The id is unknown Check the id
currency, payee_type, phone_number, customer_id or internal_account_id did not change You cannot change these fields, and Gravv ignores them Save a new payee
500 We couldn't update this payee. Please try again later. The server had an error Retry

Webhooks you will receive

Gravv sends no event for the PATCH. After it, Gravv sends external_account.active or external_account.setup_failed.

Testing in sandbox

The PATCH checks and state rules work as in live. Sandbox simulates payee setup, which finishes in a few seconds. So you cannot produce a setup_failed payee in sandbox, and a PATCH sent one second after saving already returns 409 (pending).

Reference

Was this page helpful?