> ## Documentation Index
> Fetch the complete documentation index at: https://docs.brale.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# wire or ach_debit to custodial wallet

> Fund stablecoins in custodial wallets via wire or ACH debit transfers, or set up automations for automatic minting.

Brale makes it easy for you to fund stablecoins in custodial wallets via offchain transfer types like `wire`, `ach_debit`, and `fednow_credit`. There are three common ways of funding a custodial wallet at Brale (`type: internal`) using offchain transfers:

* Submit a [Transfer](https://docs.brale.xyz/key-concepts/transfers.md) request with a source `transfer_type` of `wire`
* Submit a [Transfer](https://docs.brale.xyz/key-concepts/transfers.md) request with a source `transfer_type` of `ach_debit`
* Create an [Automation](https://docs.brale.xyz/key-concepts/automations.md), which automatically mints stablecoins to a pre-configured destination wallet when funds are received via ACH, wire, or FedNow.

> [!TIP]
>
> To receive FedNow deposits, use an Automation. You do not create a Transfer for each FedNow deposit. See [Receive FedNow deposits](https://docs.brale.xyz/guides/fednow-inbound.md) and the [FedNow overview](https://docs.brale.xyz/guides/fednow.md).

## Submitting a Transfer request with a source transfer\_type of `wire`

Here is an example of onramping to your own stablecoin (SBC) via wire transfer by calling the Transfers endpoint with the source `transfer_type` of `wire`.

**POST** `https://api.brale.xyz/accounts/account_id/transfers`

```json Request theme={null}
{
  "amount": {
    "value": "100",
    "currency": "USD"
  },
  "source": {
    "value_type": "USD",
    "transfer_type": "wire"
  },
  "destination": {
    "address_id": "2VcUIonJeVQzFoBuC7LdFT0dRe4",
    "value_type": "SBC",
    "transfer_type": "solana"
  }
}
```

```json Response theme={null}
{
  "id": "36JqTWc5Yt2mVr8LpQa0NkH3sDe",
  "status": "pending",
  "amount": {
    "value": "100",
    "currency": "USD"
  },
  "source": {
    "transfer_type": "wire",
    "value_type": "USD"
  },
  "destination": {
    "transfer_type": "solana",
    "value_type": "SBC",
    "address_id": "2VcUIonJeVQzFoBuC7LdFT0dRe4"
  },
  "wire_instructions": {
    // ...Brale bank details
  }
}
```

Initially, the status of the transfer will be `pending`. Once Brale receives the funds at the bank account provided in `wire_instructions` the stablecoins will immediately be minted to the destination wallet.

## Submitting a Transfer request with a source transfer\_type of `ach_debit`

You can initiate ACH debits from Plaid-linked addresses. See [Addresses](https://docs.brale.xyz/key-concepts/addresses.md) for the full flow of linking Plaid accounts as addresses you can pull from. This guide is specifically designed for first party funding of stablecoin mints, into a Brale custodial wallet.

**POST** `https://api.brale.xyz/accounts/account_id/transfers`

```json Request theme={null}
{
  "amount": {
    "value": "100",
    "currency": "USD"
  },
  "source": {
    "address_id": "2MhCCIHulVdXrHiEuQDJvnKbSkl",
    "value_type": "USD",
    "transfer_type": "ach_debit"
  },
  "destination": {
    "address_id": "2VcUIonJeVQzFoBuC7LdFT0dRe4",
    "value_type": "SBC",
    "transfer_type": "canton"
  }
}
```

```json Response theme={null}
{
  "id": "36JqTXd6Zu3nWs9MqRb1OlI4tEf",
  "status": "pending",
  "amount": {
    "value": "100",
    "currency": "USD"
  },
  "source": {
    "address_id": "2MhCCIHulVdXrHiEuQDJvnKbSkl",
    "value_type": "USD",
    "transfer_type": "ach_debit"
  },
  "destination": {
    "address_id": "2VcUIonJeVQzFoBuC7LdFT0dRe4",
    "value_type": "SBC",
    "transfer_type": "canton"
  }
}
```

## Fetching Transfers

Query a transfer that has been created.

**GET** `https://api.brale.xyz/accounts/account_id/transfers/:id`

```json Response theme={null}
{
  "id": "3C0QcbwVywOGyU2HBSenljm5dhU",
  "status": "complete",
  "failure": null,
  "amount": {
    "value": "102.0",
    "currency": "USD"
  },
  "created_at": "2026-04-07T00:01:27.756775Z",
  "updated_at": "2026-04-07T00:01:44.824834Z",
  "source": {
    "transfer_type": "wire",
    "financial_institution_id": "3AjRnbvj9Mq6crkviJv08d0KLB2",
    "value_type": "USD",
    "payment_details": {
      "received_at": "2026-04-07T00:01:24.514000Z",
      "sender_name": "Originator Name",
      "sender_bank_name": "JPMorgan Chase Bank",
      "sender_bank_routing_number": "000000123",
      "payment_reference": "Simulated Wire",
      "imad": "20260406XOIZJDPP953495"
    }
  },
  "destination": {
    "transaction_id": "0x41c66f1d059dad7a55a854e157a1b5b938780c77ba5296e434a02dfb1727fe5e",
    "transfer_type": "base",
    "address_id": "3ARaM0I93ObWOIFDIztsTx4TAsp",
    "value_type": "ARB"
  },
  "note": null,
  "automation_id": "3AjRnDClEzwuCKlRioG3OXMS4pH"
}
```

> [!NOTE]
>
> `source.payment_details` appears when Brale has underlying payment metadata to expose for the source leg of a transfer. Wire transfers typically include the full set of fields (`sender_name`, `sender_bank_name`, `imad`, etc.). ACH transfers may include only a subset — fields may be `null` or omitted depending on available rail metadata, and may include `trace_number` as the ACH trace identifier. See [Transfers — `source.payment_details`](https://docs.brale.xyz/key-concepts/transfers#sourcepayment_details) for the full field reference.

### Wire payment references

If a sender enters a reference in their bank's "Message to receiving bank" field, Brale can expose it in `source.payment_details.payment_reference`. Some banks call this field "Instruction for Creditor Agent." Brale uses it only when the instruction is received and no higher-priority reference is available. An existing memo, Originator-to-Beneficiary Information (OBI), or remittance reference keeps its current precedence.

`payment_reference` is an existing response-only field. It is not a request parameter, and it may be `null` or absent. Availability depends on the metadata the sending bank supplies and Brale receives, so not every inbound wire includes a reference.

Illustrative Transfer response excerpt:

```json Response excerpt theme={null}
{
  "source": {
    "transfer_type": "wire",
    "payment_details": {
      "payment_reference": "CUSTOMER-REF-123"
    }
  }
}
```

## Fiat to Stablecoin Automation (Automatic Onramp)

Automations provide a unique account number and routing number that accepts wire transfers, ACH deposits, and FedNow credits (on accounts with FedNow enabled), and automatically reconciles funds received and mints them to a bound wallet address. See [Receive FedNow deposits](https://docs.brale.xyz/guides/fednow-inbound.md).

Here is an example of onramping to your own stablecoin (SBC) via wire transfer by creating a fiat-to-stablecoin automation.

> [!NOTE]
>
> Automations mint Brale-issued stablecoins, such as `SBC`. USDC is not a supported Automation destination. To deliver USDC, mint a Brale-issued stablecoin with the Automation, then create a separate [swap Transfer](https://docs.brale.xyz/guides/stablecoin-to-stablecoin-swap.md) to USDC. See [Onramp to USDC](https://docs.brale.xyz/key-concepts/automations.md#onramp-to-usdc).

**POST** `https://api.brale.xyz/accounts/account_id/automations`

```json Request theme={null}
{
  "name": "XYZ Onramp",
  "source": {
    "value_type": "USD"
  },
  "destination": {
    "address_id": "35LWXNTO2jem13nXCLyciFdi162",
    "value_type": "SBC",
    "transfer_type": "solana"
  }
}
```

Omit `source.transfer_type`. A USD Automation accepts the inbound rails enabled for its virtual account, and responses may return `source.transfer_type: null`.

Automations are created in a `pending` state and transition to `active` when the virtual account is ready.

When an automation becomes active, the source.funding\_instructions object is populated with the virtual account’s bank details (routing number, account number, beneficiary name, etc.). These are the coordinates you share with your customer to fund the automation.

**GET** `https://api.brale.xyz/accounts/{account_id}/automations/{automation_id}`

```json Response theme={null}
{
  "id": "35kVg1llbsOBYvx9XKr9eOtsD9z",
  "name": "Customer XYZ Automation",
  "status": "active",
  "source": {
    "transfer_type": null,
    "value_type": "USD",
    "funding_instructions": {
      "bank_address": "123 Example St, Example City, NY 10001",
      "beneficiary_address": "25 Main Ave, Suite 100, Example City, IA 50000",
      "beneficiary_name": "Company ABC",
      "routing_number": "000111222",
      "account_number": "000123456789",
      "bank_name": "Example Bank",
      "memo": null
    }
  },
  "destination": {
    "transfer_type": "solana",
    "address_id": "35LWXNTO2jem13nXCLyciFdi162",
    "value_type": "SBC"
  },
  "updated_at": "2025-11-20T15:56:05.017508Z",
  "created_at": "2025-11-20T15:56:03.531196Z"
}
```

> When an automation is no longer needed, archive it by sending `PATCH /accounts/{account_id}/automations/{automation_id}` with `{ "status": "archived" }`. This closes the virtual account and stops future deposits from being processed.

## Test an Automation on testnet

Testnet Automations return placeholder banking coordinates that cannot receive real deposits. Use [Simulate an Automation deposit](https://docs.brale.xyz/api-reference/brale/simulate-automation-deposit.md) to test the full onramp flow without moving real fiat.

Prerequisites:

* Testnet API credentials with the `automations:write` and `network:testnet` scopes. See [Sandbox and Testnet](https://docs.brale.xyz/overview/sandbox-and-testnet.md).
* A custodial wallet address on a testnet chain, such as `base_sepolia` or `solana_devnet`.
* A [webhook subscription](https://docs.brale.xyz/webhooks/quickstart.md) that includes `payment.completed`.

### 1. Create an Automation

**POST** `https://api.brale.xyz/accounts/{account_id}/automations`

```json Request theme={null}
{
  "name": "Testnet Onramp",
  "source": {
    "value_type": "USD"
  },
  "destination": {
    "address_id": "3ARaM0I93ObWOIFDIztsTx4TAsp",
    "value_type": "SBC",
    "transfer_type": "base_sepolia"
  }
}
```

### 2. Wait until the Automation is active

Poll `GET /accounts/{account_id}/automations/{automation_id}` until `status` is `active`. Brale returns `422 automation_not_active` if you simulate a deposit before then.

### 3. Simulate a deposit

**POST** `https://api.brale.xyz/accounts/{account_id}/automations/{automation_id}/simulations/deposits`

```bash theme={null}
curl --request POST \
  --url "https://api.brale.xyz/accounts/${ACCOUNT_ID}/automations/${AUTOMATION_ID}/simulations/deposits" \
  --header "Authorization: Bearer ${AUTH_TOKEN}" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: $(uuidgen)" \
  --data '{
    "amount": { "value": "10.00", "currency": "USD" },
    "transfer_type": "wire"
  }'
```

`transfer_type` accepts `ach`, `wire`, or `fednow`. A `fednow` simulation produces a Transfer with `source.transfer_type: "fednow_credit"`. Brale returns `202 Accepted` with the resulting Transfer. Save its `id`.

Use a new `Idempotency-Key` for each new simulated deposit. Retrying with the same key returns the original response without creating another deposit or mint. See [Idempotency](https://docs.brale.xyz/key-concepts/idempotency.md).

### 4. Receive webhooks

Brale emits the normal `payment.completed` [webhook event](https://docs.brale.xyz/webhooks/webhook-events.md) for the simulated inbound payment. There is no simulation-specific webhook type, so your production handler works unchanged.

### 5. Fetch the Transfer

**GET** `https://api.brale.xyz/accounts/{account_id}/transfers/{transfer_id}`

```json Response theme={null}
{
  "id": "3F1kP8vQ2mZrT6yN0bXcW4hJd7s",
  "status": "complete",
  "failure": null,
  "amount": {
    "value": "10.00",
    "currency": "USD"
  },
  "source": {
    "value_type": "USD",
    "transfer_type": "wire"
  },
  "destination": {
    "address_id": "3ARaM0I93ObWOIFDIztsTx4TAsp",
    "value_type": "SBC",
    "transfer_type": "base_sepolia",
    "transaction_id": "0x41c66f1d059dad7a55a854e157a1b5b938780c77ba5296e434a02dfb1727fe5e"
  },
  "note": null,
  "automation_id": "3AjRnDClEzwuCKlRioG3OXMS4pH",
  "created_at": "2026-09-29T17:00:00.000000Z",
  "updated_at": "2026-09-29T17:00:05.000000Z"
}
```

### 6. Verify the testnet mint

Confirm that `automation_id` matches your Automation and `status` is `complete`. Look up `destination.transaction_id` in a block explorer for the testnet chain to verify the mint.
