---
title: "Save one US account for both ACH and wire"
description: "Save two payees for the same US account, one per rail, and pay each on its own rail."
---
Use this recipe to save two payees for the same US account, one for each rail, and pay each payee on its own rail.

**Who it is for.** An accounts-payable app that pays a vendor by ACH for routine invoices and by wire for urgent ones.

**Status.** Available.

## Money example

1. The vendor is Northwind Supply, with account number 000555777999 and routing number 021000021.
2. The app pays a routine invoice of 1,200.00 USD by ACH to payee A.
3. The app pays an urgent invoice of 25,000.00 USD by wire to payee B, which is the same account.

## Before you start

You need everything in [Pay a US bank account by ACH](/recipes/bank-payouts/pay-a-us-bank-account-by-ach#before-you-start).

## Find out what is required

For US payees, a duplicate has the **same customer, account name, account number, routing number and rail**. A different rail makes a different payee. First, list the payees that already exist:

<CodeGroup>
```bash title="cURL"
curl --request GET \
     --url 'https://api.gravv.xyz/v1/external-accounts?customer_id=7c9e6679-7425-40de-944b-e07fc1f90ae7&search=000555777999' \
     --header 'Api-Key: <API_KEY>'
```
```javascript title="Node"
const response = await fetch("https://api.gravv.xyz/v1/external-accounts?customer_id=7c9e6679-7425-40de-944b-e07fc1f90ae7&search=000555777999", {
  method: "GET",
  headers: {
    "Api-Key": process.env.GRAVV_API_KEY,
  },
});
console.log(response.status, await response.json());
```
```python title="Python"
import os

import requests

response = requests.get(
    "https://api.gravv.xyz/v1/external-accounts?customer_id=7c9e6679-7425-40de-944b-e07fc1f90ae7&search=000555777999",
    headers={
        "Api-Key": os.environ["GRAVV_API_KEY"],
    },
)
print(response.status_code, response.json())
```
</CodeGroup>

The list has no status filter, so check `status` on each item. The API does not return a payee's rail, so match the ids against your own records.

## Steps

### 1. Save payee A for ACH

<CodeGroup>
```bash title="cURL"
curl --request POST \
     --url https://api.gravv.xyz/v1/external-accounts \
     --header 'Api-Key: <API_KEY>' \
     --header 'Content-Type: application/json' \
     --header 'Idempotency-Key: 11dada0c-ecc7-436f-9f1a-d46bc7eb86c3' \
     --data '
{
  "customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "payee_type": "ach_wire",
  "currency": "USD",
  "account_name": "Northwind Supply Inc",
  "account_number": "000555777999",
  "routing_number": "021000021",
  "payment_rail": "ach",
  "account_owner_type": "business",
  "bank_name": "JPMorgan Chase Bank",
  "address": {
    "address_line1": "80 Pine Street",
    "city": "New York",
    "state": "NY",
    "postal_code": "10005",
    "country": "US"
  }
}
'
```
```javascript title="Node"
const response = await fetch("https://api.gravv.xyz/v1/external-accounts", {
  method: "POST",
  headers: {
    "Api-Key": process.env.GRAVV_API_KEY,
    "Content-Type": "application/json",
    "Idempotency-Key": "11dada0c-ecc7-436f-9f1a-d46bc7eb86c3",
  },
  body: JSON.stringify({
    "customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "payee_type": "ach_wire",
    "currency": "USD",
    "account_name": "Northwind Supply Inc",
    "account_number": "000555777999",
    "routing_number": "021000021",
    "payment_rail": "ach",
    "account_owner_type": "business",
    "bank_name": "JPMorgan Chase Bank",
    "address": {
      "address_line1": "80 Pine Street",
      "city": "New York",
      "state": "NY",
      "postal_code": "10005",
      "country": "US"
    }
  }),
});
console.log(response.status, await response.json());
```
```python title="Python"
import os

import requests

response = requests.post(
    "https://api.gravv.xyz/v1/external-accounts",
    headers={
        "Api-Key": os.environ["GRAVV_API_KEY"],
        "Content-Type": "application/json",
        "Idempotency-Key": "11dada0c-ecc7-436f-9f1a-d46bc7eb86c3",
    },
    json={
        "customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
        "payee_type": "ach_wire",
        "currency": "USD",
        "account_name": "Northwind Supply Inc",
        "account_number": "000555777999",
        "routing_number": "021000021",
        "payment_rail": "ach",
        "account_owner_type": "business",
        "bank_name": "JPMorgan Chase Bank",
        "address": {
            "address_line1": "80 Pine Street",
            "city": "New York",
            "state": "NY",
            "postal_code": "10005",
            "country": "US",
        },
    },
)
print(response.status_code, response.json())
```
</CodeGroup>

The response is HTTP 202 with `status` `pending`. Store the id with its rail, for example `{"payee_id": "a1f2…", "rail": "ach"}`.

### 2. Save payee B for wire

Send the same body with `"payment_rail": "wire"` and a **new** `Idempotency-Key`:

<CodeGroup>
```bash title="cURL"
curl --request POST \
     --url https://api.gravv.xyz/v1/external-accounts \
     --header 'Api-Key: <API_KEY>' \
     --header 'Content-Type: application/json' \
     --header 'Idempotency-Key: 762adba6-ce4b-4b4e-99d9-b5effc3e9336' \
     --data '
{
  "customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "payee_type": "ach_wire",
  "currency": "USD",
  "account_name": "Northwind Supply Inc",
  "account_number": "000555777999",
  "routing_number": "021000021",
  "payment_rail": "wire",
  "account_owner_type": "business",
  "bank_name": "JPMorgan Chase Bank",
  "address": {
    "address_line1": "80 Pine Street",
    "city": "New York",
    "state": "NY",
    "postal_code": "10005",
    "country": "US"
  }
}
'
```
```javascript title="Node"
const response = await fetch("https://api.gravv.xyz/v1/external-accounts", {
  method: "POST",
  headers: {
    "Api-Key": process.env.GRAVV_API_KEY,
    "Content-Type": "application/json",
    "Idempotency-Key": "762adba6-ce4b-4b4e-99d9-b5effc3e9336",
  },
  body: JSON.stringify({
    "customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "payee_type": "ach_wire",
    "currency": "USD",
    "account_name": "Northwind Supply Inc",
    "account_number": "000555777999",
    "routing_number": "021000021",
    "payment_rail": "wire",
    "account_owner_type": "business",
    "bank_name": "JPMorgan Chase Bank",
    "address": {
      "address_line1": "80 Pine Street",
      "city": "New York",
      "state": "NY",
      "postal_code": "10005",
      "country": "US"
    }
  }),
});
console.log(response.status, await response.json());
```
```python title="Python"
import os

import requests

response = requests.post(
    "https://api.gravv.xyz/v1/external-accounts",
    headers={
        "Api-Key": os.environ["GRAVV_API_KEY"],
        "Content-Type": "application/json",
        "Idempotency-Key": "762adba6-ce4b-4b4e-99d9-b5effc3e9336",
    },
    json={
        "customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
        "payee_type": "ach_wire",
        "currency": "USD",
        "account_name": "Northwind Supply Inc",
        "account_number": "000555777999",
        "routing_number": "021000021",
        "payment_rail": "wire",
        "account_owner_type": "business",
        "bank_name": "JPMorgan Chase Bank",
        "address": {
            "address_line1": "80 Pine Street",
            "city": "New York",
            "state": "NY",
            "postal_code": "10005",
            "country": "US",
        },
    },
)
print(response.status_code, response.json())
```
</CodeGroup>

### 3. Pay each payee on its own rail

Pay payee A with `"rail": "ach"` and payee B with `"rail": "wire"` inside `destination`, as in [the ACH recipe](/recipes/bank-payouts/pay-a-us-bank-account-by-ach#4-send-the-payout) and [the wire recipe](/recipes/bank-payouts/send-a-us-domestic-wire#3-send-the-wire).

## What can go wrong

| Response | Why | Fix |
| :-- | :-- | :-- |
| 400 `a recipient with the same account name, account number and bank already exists`, with `data.payee_id` | You sent the same rail twice, or an earlier payee on this rail exists, including `deleted` and `setup_failed` payees | Use `data.payee_id`. If it is `setup_failed`, [fix it](/recipes/bank-payouts/fix-a-payee-that-failed-setup) |
| 422 `idempotency_key_reused` on step 2 | You reused the key from step 1 with a changed body | Use a new key for each payee |
| 400 `this payee is registered for ach transfers, not wire — initiate on rail "ach", or add a payee on the wire rail` | You paid payee A on the wire rail | Pay payee B instead, or save payee B first |
| The API accepts two payees for the same vendor with different name spellings | The name is part of the duplicate check | Normalize names on your side |

## Webhooks you will receive

You receive `external_account.created` and `external_account.active` for each payee, then the transfer events as in [the ACH recipe](/recipes/bank-payouts/pay-a-us-bank-account-by-ach#webhooks-you-will-receive).

## Testing in sandbox

Save both payees in sandbox. The duplicate check works the same way as in live, and sandbox simulates payee setup.

## Reference

- [List external accounts](/api-reference/external-accounts/get-v1-external-accounts)
- [Add an external account](/api-reference/external-accounts/post-v1-external-accounts)
- [Create a transfer](/api-reference/transfer/post-v1-transfer)
