---
title: "Update an external account"
description: "Correct a payee that failed setup, retry its setup, or add details a route needs, without saving a duplicate."
---
This page shows how to correct a payee that failed setup, and how to add details that a route needs. You cannot save a `setup_failed` payee again, because the duplicate check still counts it. Correct it in place with [`PATCH /v1/external-accounts/{external_account_id}`](/api-reference/external-accounts/patch-v1-external-accounts-external-account-id). The payee goes back to `pending`, setup runs again, and you keep the same `id`.

**Example.** A SWIFT payee for a 7,500.00 USD supplier payment fails setup with `error_message` `these account details could not be accepted`. The supplier confirms the account number ends in 8, not 9. You send a PATCH with the new `account_number`. The payee returns to `pending`, then `active`, and you send the payment.

## Read why it failed

```bash title="Retrieve the failed payee request"
curl --request GET \
     --url https://api.gravv.xyz/v1/external-accounts/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
     --header 'Api-Key: <API_KEY>'
```

`error_message` is one of:

| `error_message` | What it means |
| :-- | :-- |
| `these account details could not be accepted` (sometimes `… for the <rail> rail`) | The bank refused the details. 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 unchanged |
| `recipient setup failed` | Setup failed for another reason. Check the fields, or retry unchanged |

## Correct the payee

Send only the fields to change. Gravv keeps a field you leave out, `null` clears it, and a value sets it. The call needs no `Idempotency-Key`. The API always returns HTTP 202:

```bash title="Update an external account request"
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"
}
'
```

```json title="Update an external account response"
{
  "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
}
```

Then wait for `external_account.active` (or `external_account.setup_failed` again). The PATCH itself sends no event.

To retry setup with nothing changed, for example after `attempt 10 of 10`, send an empty body `{}`.

## Add details a route needs

The same call adds details to an active local payee when a route asks for them, such as a PIX key and CPF for Brazil, or `national_id` and `address`:

```bash title="Add missing details request"
curl --request PATCH \
     --url https://api.gravv.xyz/v1/external-accounts/8e65cb04-10e2-4faa-b365-e1e03942b846 \
     --header 'Api-Key: <API_KEY>' \
     --header 'Content-Type: application/json' \
     --data '
{
  "pix_key": "maria.souza@example.com",
  "national_id": "529.982.247-25",
  "national_id_type": "CPF",
  "address": {
    "address_line1": "Rua Augusta 1200",
    "city": "Sao Paulo",
    "country": "BR"
  }
}
'
```

The response shows `national_id_type` and a masked `national_id_masked`. Gravv never returns the full id or the PIX key.

## What you can and cannot change

- You can change banking details only on a `setup_failed` payee, or on a `pending` payee whose setup has not started. In any other state, the API returns 409.
- You cannot change `currency`, `payee_type`, `phone_number`, `customer_id` or `internal_account_id`. The API ignores them. To change them, save a new payee.
- You cannot change the address of a payee that is already registered for payouts.

## What can go wrong

| Response | Why | Fix |
| :-- | :-- | :-- |
| 409 `payee <id> is not correctable in its current state (active): invalid state transition` | The payee is `active` (or its setup has started) | Save a new payee |
| 409 `the address of payee <id> cannot be changed: it is already registered for payouts; create a new payee with the new address` | The address is locked | 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 arrived at the same time | Read the payee, then send the PATCH again |
| 409, duplicate | The corrected details match another payee | Use that payee |
| 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. A GET returns 400 for the same case | Check the id |
| 500 `We couldn't update this payee. Please try again later.` | A server error | Retry |

## Testing in sandbox

In sandbox, Gravv simulates payee setup, and setup finishes in seconds. You cannot produce a `setup_failed` payee there, and a PATCH sent a second after saving already returns 409 `(pending)`. The field and state checks work the same as in live.

Related recipe: [Fix a payee that failed setup](/recipes/bank-payouts/fix-a-payee-that-failed-setup).
