---
updatedAt: 2026-08-16T03:25:05.000Z
agentTools:
  projectIndex: https://docs.wirexapp.com/llms.txt
---

# ACH Bank Details

Get ACH bank account details for receiving USD transfers.

## Before You Start

Read the following guides before proceeding:

| Guide                                         | Why                                        |
| --------------------------------------------- | ------------------------------------------ |
| [Getting Started](https://docs.wirexapp.com/docs/retail-getting-started) | Platform overview and setup                |
| [Api Basics](https://docs.wirexapp.com/docs/retail-api-basics)           | Required headers and request configuration |
| [Authentication](https://docs.wirexapp.com/docs/retail-authentication)   | How to obtain access tokens                |
| [Onboarding](https://docs.wirexapp.com/docs/retail-onboarding)           | User and wallet registration               |
| [KYC](https://docs.wirexapp.com/docs/retail-kyc)                         | KYC verification requirements              |
| [Recipients](https://docs.wirexapp.com/docs/retail-recipients)           | Recipient management                       |

***

## Overview

Users residing in supported countries can receive USD transfers via ACH. ACH accounts require activation, the same as [SEPA](https://docs.wirexapp.com/docs/retail-sepa-bank-details). Incoming ACH transfers are automatically converted to the user's unified balance (WUSD).

***

## Checking ACH Availability

Before activating an ACH account, verify that the user has access by checking their capabilities.

```
GET /api/v2/user
```

The response includes the `AchAccount` capability:

```json
{
  "capabilities": [
    {
      "type": "AchAccount",
      "status": "ActivationNotStarted"
    }
  ]
}
```

### Capability Status

| Status                 | Description                                          |
| ---------------------- | ---------------------------------------------------- |
| `Active`               | ACH account is provisioned and ready to use          |
| `ActivationNotStarted` | Available but requires activation via API            |
| `InProgress`           | Activation requested, waiting for provisioning       |
| `NotFulfilled`         | User needs to complete additional verification first |
| `NotAvailable`         | Not available for user's country of residence        |

See [Bank Account Availability](https://docs.wirexapp.com/docs/bank-account-availability) for supported countries.

***

## Activate ACH Account

When capability status is `ActivationNotStarted`, call this endpoint to provision the account.

```
POST /api/v1/bank/accounts
```

### Request Body

| Field          | Type   | Required | Description   |
| -------------- | ------ | -------- | ------------- |
| `account_type` | string | Yes      | Must be `Ach` |

### Code Examples

```javascript
const response = await fetch(`${baseUrl}/api/v1/bank/accounts`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'X-User-Wallet': userEoaAddress,
    'X-Chain-Id': chainId,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    account_type: 'Ach'
  })
});

const result = await response.json();
console.log('Details ID:', result.details_id);
```
```python
response = requests.post(
    f"{base_url}/api/v1/bank/accounts",
    headers={
        "Authorization": f"Bearer {access_token}",
        "X-User-Wallet": user_eoa_address,
        "X-Chain-Id": chain_id,
        "Content-Type": "application/json"
    },
    json={
        "account_type": "Ach"
    }
)

result = response.json()
print("Details ID:", result["details_id"])
```
```go
body := map[string]string{
    "account_type": "Ach",
}

jsonBody, _ := json.Marshal(body)
req, _ := http.NewRequest("POST", baseURL+"/api/v1/bank/accounts", bytes.NewBuffer(jsonBody))
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)
req.Header.Set("Content-Type", "application/json")

resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

var result BankAccountActivateResponse
json.NewDecoder(resp.Body).Decode(&result)
```

### Response

```json
{
  "details_id": "8d5a65eb59d94afea64374d45591fe9f"
}
```

After activation, the capability status changes to `InProgress`. You will receive a webhook when the account is ready.

***

## Get Bank Accounts

Retrieve the user's bank account details including ACH information.

```
GET /api/v1/bank/accounts
```

### Query Parameters

| Parameter     | Type    | Description                         |
| ------------- | ------- | ----------------------------------- |
| `page_number` | integer | Page number, 0-indexed (default: 0) |
| `page_size`   | integer | Items per page (default: 25)        |

### Code Examples

```javascript
const response = await fetch(`${baseUrl}/api/v1/bank/accounts`, {
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'X-User-Wallet': userEoaAddress,
    'X-Chain-Id': chainId
  }
});
const { accounts } = await response.json();

const achAccount = accounts.find(a => a.account_type === 'Ach');
if (achAccount) {
  console.log('Account Number:', achAccount.details.account_number);
  console.log('Routing Number:', achAccount.details.routing_number);
}
```
```python
response = requests.get(
    f"{base_url}/api/v1/bank/accounts",
    headers={
        "Authorization": f"Bearer {access_token}",
        "X-User-Wallet": user_eoa_address,
        "X-Chain-Id": chain_id
    }
)
accounts = response.json()["accounts"]

ach_account = next((a for a in accounts if a["account_type"] == "Ach"), None)
if ach_account:
    print("Account Number:", ach_account["details"]["account_number"])
    print("Routing Number:", ach_account["details"]["routing_number"])
```
```go
req, _ := http.NewRequest("GET", baseURL+"/api/v1/bank/accounts", nil)
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("X-User-Wallet", userEoaAddress)
req.Header.Set("X-Chain-Id", chainId)

resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

var result struct {
    Accounts []BankAccountResponse `json:"accounts"`
}
json.NewDecoder(resp.Body).Decode(&result)

for _, account := range result.Accounts {
    if account.AccountType == "Ach" {
        fmt.Println("Account Number:", account.Details.AccountNumber)
        fmt.Println("Routing Number:", account.Details.RoutingNumber)
    }
}
```

### Response

```json
{
  "accounts": [
    {
      "id": "1334726cbd7641c09b4124e3e52f53fe:8d5a65eb59d94afea64374d45591fe9f",
      "currency": "USD",
      "status": "Active",
      "account_holder": "Alex Grey",
      "account_type": "Ach",
      "details": {
        "account_number": "8310931284",
        "routing_number": "026073150"
      }
    }
  ]
}
```

### Response Fields

| Field                    | Description                                                                                                                                                                                 |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                     | Composite identifier in format `{account_id}:{details_id}`. The `account_id` corresponds to the account `id` from webhooks, and `details_id` corresponds to the details `id` from webhooks. |
| `currency`               | Account currency (USD for ACH)                                                                                                                                                              |
| `status`                 | Account status: `Active`, `Pending`, `Blocked`, `Closed`                                                                                                                                    |
| `account_holder`         | Name on the account                                                                                                                                                                         |
| `account_type`           | `Ach` for ACH accounts                                                                                                                                                                      |
| `details.account_number` | Bank account number for receiving transfers                                                                                                                                                 |
| `details.routing_number` | ABA routing number                                                                                                                                                                          |

***

## Account Status

| Status    | Description                       |
| --------- | --------------------------------- |
| `Pending` | Account details being provisioned |
| `Active`  | Ready to receive transfers        |
| `Blocked` | Temporarily suspended             |
| `Closed`  | Permanently closed                |

***

## Receiving ACH Transfers

To receive an ACH transfer:

1. Activate the ACH account if not already active
2. Retrieve the user's ACH account details using the endpoint above
3. Provide the account number and routing number to the sender
4. Monitor incoming transfers via the [Activities webhook](https://docs.wirexapp.com/docs/retail-webhooks)

### Important Notes

* Incoming USD is automatically converted to WUSD in the user's unified balance
* ACH transfers typically settle within 1-3 business days

***

## Webhooks

### Bank Account Updates

Wirex sends webhook notifications when bank account details are created or updated.

**Endpoint:** `POST {your_webhook_base_url}/webhook/accounts/fiat`

#### Account Created

```json
{
  "change_type": "Created",
  "id": "1334726cbd7641c09b4124e3e52f53fe",
  "account_type": "Fiat",
  "currency": "USD",
  "status": "Active",
  "balance": {
    "amount": 0,
    "available_amount": 0
  },
  "details": [],
  "owner_type": "Personal",
  "created_at": "2024-01-15T10:00:00Z"
}
```

#### Details Changed (ACH Details Added)

```json
{
  "change_type": "DetailsChanged",
  "id": "1334726cbd7641c09b4124e3e52f53fe",
  "account_type": "Fiat",
  "currency": "USD",
  "status": "Active",
  "balance": {
    "amount": 0,
    "available_amount": 0
  },
  "details": [
    {
      "id": "8d5a65eb59d94afea64374d45591fe9f",
      "type": "Ach",
      "status": "Pending",
      "transport_currency": "USD"
    }
  ],
  "owner_type": "Personal"
}
```

### Incoming ACH Transfer

When an ACH transfer is received, you receive an activity webhook.

**Endpoint:** `POST {your_webhook_base_url}/v2/webhooks/activities`

```json
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "user_address": "0x7e1Cc1685D68D486b22D3880030C24434E3b90a9",
  "type": "AchPush",
  "status": "Completed",
  "direction": "Inbound",
  "source": {
    "type": "AchBankAccount",
    "bank_account": {
      "account_number": "",
      "routing_number": "026073150",
      "owner_name": "Alex Grey",
      "is_business": false
    }
  },
  "destination": {
    "type": "Wallet",
    "wallet": {
      "address": "0xAAFF0821A09A1Aac28B72dD3Ff410A7ea5FEb874"
    }
  },
  "source_amount": {
    "amount": 500.00,
    "currency": "USD"
  },
  "destination_amount": {
    "amount": 500.00,
    "token_symbol": "WUSD",
    "token_address": "0x0774164DC20524Bb239b39D1DC42573C3E4C6976"
  },
  "operations": [
    {
      "hash": "0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234",
      "operation_amount": {
        "amount": 500.00,
        "token_symbol": "WUSD",
        "token_address": "0x0774164DC20524Bb239b39D1DC42573C3E4C6976"
      },
      "transaction_amount": {
        "amount": 500.00,
        "currency": "USD"
      },
      "rate": {
        "ticker": "USD/WUSD",
        "rate": 1
      }
    }
  ],
  "created_at": "2024-01-01T08:00:00.000Z",
  "activity_steps": [
    {
      "type": "Initiated",
      "status": "Completed",
      "created_at": "2024-01-01T08:00:00.000Z",
      "completed_at": "2024-01-01T08:00:00.000Z"
    },
    {
      "type": "BankIn",
      "status": "Completed",
      "created_at": "2024-01-01T08:00:00.000Z",
      "completed_at": "2024-01-01T08:05:00.000Z"
    },
    {
      "type": "CryptoIn",
      "status": "Completed",
      "created_at": "2024-01-01T08:05:00.000Z",
      "completed_at": "2024-01-01T08:05:15.000Z"
    }
  ]
}
```

***

## Error Handling

### Validation Errors

| Error Reason         | Description                                      |
| -------------------- | ------------------------------------------------ |
| `ErrorNotFound`      | User not found or not verified                   |
| `ErrorInvalidStatus` | User account not active                          |
| `ErrorInvalidField`  | Invalid account type or capability not available |

### Error Response Format

```json
{
  "error_reason": "ErrorInvalidField",
  "error_description": "Account capability does not need activation or is not available",
  "error_category": {
    "category": "CategoryValidationFailure",
    "http_status_code": 400
  },
  "error_details": [
    {
      "key": "field",
      "details": "account_type"
    }
  ]
}
```