Initiate many ACH transfers from own account

Initiate Many ACH Transfers

The POST /api/fundsMovement/v2/ACHTransferMany endpoint enables batch processing of ACH (Automated Clearing House) transfers, allowing multiple payments to be dispatched from a single financial account in one API call. Each transfer in the batch is processed and reported individually, so partial success is possible — failed transfers do not block successful ones. This endpoint is secured with a one-time verification code to protect high-value bulk operations.

Endpoint

POST /api/fundsMovement/v2/ACHTransferMany

Authentication

Bearer token required. Obtain via:

POST https://api.banking.netevia.dev/api/auth/v2

Include in header: Authorization: Bearer {token}
Token lifetime: 10 minutes. Refresh via POST /api/auth/refresh.

When to use

Use this endpoint when a business customer needs to send multiple ACH payments in a single operation, such as processing payroll, paying vendors, or settling invoices in bulk. It is more efficient than calling the single-transfer endpoint repeatedly and provides a per-transfer status breakdown in the response. A one-time verification code (oneTimeCode) must be obtained and supplied with each request for security.

Request Body

FieldTypeRequiredDescription
oneTimeCodestringYes6-digit numeric one-time verification code. Pattern: ^\d{6}$. Obtain via the verification/OTP flow before calling this endpoint.
secureOperationTypestringYesThe type of OTP used. One of: ShortMessageCode, TimeBasedCode, LegacyTimeBasedCode.
transferRequestsarrayNoArray of individual ACH transfer request objects. Each item may be a fundsWithdrawalACHTransferRequest or a unifiedTransferRequest (see nested fields below).
transferRequests[].fromFinancialAccountIdstringYes (per item)ID of the Netevia financial account funds are drawn from.
transferRequests[].toFinancialAccountIdstringYes (per item)ID of the destination financial account (ACH-linked external account or Netevia account).
transferRequests[].amountinteger (int32)NoTransfer amount in cents (USD). Minimum: 1, Maximum: 4294967295.
transferRequests[].currencyCodeintegerNoISO 4217 numeric currency code. Only 840 (USD) is supported.
transferRequests[].memostringNoOptional memo or note attached to the transfer. Maximum 1024 characters.
transferRequests[].typestringNoAccount type for unified transfer requests. One of: Netevia, ACH. Only present when using unifiedTransferRequest items.
{
  "oneTimeCode": "482901",
  "secureOperationType": "ShortMessageCode",
  "transferRequests": [
    {
      "fromFinancialAccountId": "fa_xxxxxxxxxxxxxxxxxx01",
      "toFinancialAccountId": "fa_xxxxxxxxxxxxxxxxxx02",
      "amount": 150000,
      "currencyCode": 840,
      "memo": "Vendor payment - Invoice #1042"
    },
    {
      "fromFinancialAccountId": "fa_xxxxxxxxxxxxxxxxxx01",
      "toFinancialAccountId": "fa_xxxxxxxxxxxxxxxxxx03",
      "amount": 250000,
      "currencyCode": 840,
      "memo": "Payroll - June 2026",
      "type": "ACH"
    }
  ]
}

Response

200 OK

Returns an array of transfer response objects, one per item submitted in transferRequests. Each object reports the outcome of its corresponding transfer.

FieldTypeDescription
idstringUnique identifier for this transfer response entry.
dataobjectPayload containing the ACH transfer details (see nested fields below).
data.initiateFundsWithdrawalACHTransferobjectDetails of the withdrawal leg of the ACH transfer, if applicable.
data.initiateFundsDepositACHTransferobjectDetails of the deposit leg of the ACH transfer, if applicable.
data.transferobjectConsolidated transfer details.
data.*.idstringUnique transfer ID assigned by the platform.
data.*.amount.valueinteger (int64)Transfer amount in cents.
data.*.amount.currencyCodestringCurrency code string (e.g., "USD").
data.*.status.statusstringTransfer status (e.g., PENDING, COMPLETED, FAILED).
data.*.status.statusReasonCodestringReason code qualifying the status, if applicable.
data.*.fromFinancialAccount.idstringID of the source financial account.
data.*.fromFinancialAccount.namestringDisplay name of the source financial account.
data.*.fromFinancialAccount.last4stringLast 4 digits of the source account number.
data.*.fromFinancialAccount.externalBankAccountDetailsobjectExternal bank account details for the source, if applicable.
data.*.fromFinancialAccount.externalBankAccountDetails.last4stringLast 4 digits of external account number.
data.*.fromFinancialAccount.externalBankAccountDetails.typestringExternal account type (e.g., checking, savings).
data.*.fromFinancialAccount.externalBankAccountDetails.routingNumberstringRouting number of the external bank.
data.*.fromFinancialAccount.externalBankAccountDetails.accountNumberstringFull account number (sanitize as XXXXXXXXXX in logs).
data.*.fromFinancialAccount.externalBankAccountDetails.createdAtstring (date-time)When the external account was linked.
data.*.fromFinancialAccount.externalBankAccountDetails.updatedAtstring (date-time)When the external account record was last updated.
data.*.fromFinancialAccount.providerstringProvider used to link the external account (e.g., Finicity, Plaid).
data.*.toFinancialAccountobjectSame structure as fromFinancialAccount for the destination account.
data.*.errorsarrayArray of error objects for this transfer, if it failed.
data.*.errors[].patharray of stringsJSON path pointing to the field that caused the error.
data.*.errors[].codestringMachine-readable error code.
data.*.errors[].descriptionstringHuman-readable description of the error.
errorCodeintegerPlatform-level error code for this transfer entry; absent or null if no error.
[
  {
    "id": "tr_resp_xxxxxxxxxxxxxxxxxx01",
    "data": {
      "initiateFundsWithdrawalACHTransfer": {
        "id": "ach_xxxxxxxxxxxxxxxxxx01",
        "amount": {
          "value": 150000,
          "currencyCode": "USD"
        },
        "status": {
          "status": "PENDING",
          "statusReasonCode": null
        },
        "fromFinancialAccount": {
          "id": "fa_xxxxxxxxxxxxxxxxxx01",
          "name": "Business Checking",
          "last4": "1234",
          "externalBankAccountDetails": null,
          "provider": null
        },
        "toFinancialAccount": {
          "id": "fa_xxxxxxxxxxxxxxxxxx02",
          "name": "Vendor Account",
          "last4": "5678",
          "externalBankAccountDetails": {
            "last4": "5678",
            "type": "checking",
            "routingNumber": "021000021",
            "accountNumber": "XXXXXXXXXX",
            "createdAt": "2026-01-15T10:30:00Z",
            "updatedAt": "2026-01-15T10:30:00Z"
          },
          "provider": "Plaid"
        },
        "errors": []
      },
      "initiateFundsDepositACHTransfer": null,
      "transfer": null
    },
    "errorCode": null
  },
  {
    "id": "tr_resp_xxxxxxxxxxxxxxxxxx02",
    "data": {
      "initiateFundsWithdrawalACHTransfer": null,
      "initiateFundsDepositACHTransfer": null,
      "transfer": {
        "id": "ach_xxxxxxxxxxxxxxxxxx02",
        "amount": {
          "value": 250000,
          "currencyCode": "USD"
        },
        "status": {
          "status": "PENDING",
          "statusReasonCode": null
        },
        "fromFinancialAccount": {
          "id": "fa_xxxxxxxxxxxxxxxxxx01",
          "name": "Business Checking",
          "last4": "1234",
          "externalBankAccountDetails": null,
          "provider": null
        },
        "toFinancialAccount": {
          "id": "fa_xxxxxxxxxxxxxxxxxx03",
          "name": "Payroll Account",
          "last4": "9012",
          "externalBankAccountDetails": null,
          "provider": null
        },
        "errors": []
      }
    },
    "errorCode": null
  }
]

Error Codes

CodeWhen it happens
400Missing required fields (oneTimeCode, secureOperationType), invalid OTP format (not 6 digits), or validation error on one or more transfer items
401Bearer token missing, expired, or invalid
403Caller does not have permission to initiate ACH transfers from the specified financial account
404One or more fromFinancialAccountId or toFinancialAccountId values not found
500Internal server error

Common Mistakes

  • Submitting an oneTimeCode that has already been used or has expired — each request requires a fresh OTP obtained immediately before calling this endpoint.
  • Using a string value for currencyCode in the request body — the schema expects the numeric ISO 4217 code 840 (integer), not the string "USD".
  • Omitting fromFinancialAccountId or toFinancialAccountId on any item in transferRequests — both fields are required per transfer item and will cause that item (or the entire request) to fail validation.
  • Assuming that a 200 response means all transfers succeeded — always inspect each item in the response array for errorCode and data.*.errors to confirm individual transfer outcomes.
  • Setting amount to 0 — the minimum allowed value is 1 (i.e., $0.01 USD).
  • Sending more transfer items than the account's daily ACH limits allow without verifying limits first.

Related Endpoints

  • POST /api/fundsMovement/v2/ACHTransfer — Initiate a single ACH transfer from own account
  • POST /api/fundsMovement/v2/ACHTransferScheduled — Schedule a single ACH transfer for a future date
  • GET /api/fundsMovement/v2/transfers — List transfers for a financial account
  • POST /api/auth/v2 — Obtain a Bearer token for authentication
  • POST /api/auth/refresh — Refresh an existing Bearer token

Example

curl -X POST https://api.banking.netevia.dev/api/fundsMovement/v2/ACHTransferMany \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "oneTimeCode": "482901",
    "secureOperationType": "ShortMessageCode",
    "transferRequests": [
      {
        "fromFinancialAccountId": "fa_xxxxxxxxxxxxxxxxxx01",
        "toFinancialAccountId": "fa_xxxxxxxxxxxxxxxxxx02",
        "amount": 150000,
        "currencyCode": 840,
        "memo": "Vendor payment - Invoice #1042"
      },
      {
        "fromFinancialAccountId": "fa_xxxxxxxxxxxxxxxxxx01",
        "toFinancialAccountId": "fa_xxxxxxxxxxxxxxxxxx03",
        "amount": 250000,
        "currencyCode": 840,
        "memo": "Payroll - June 2026",
        "type": "ACH"
      }
    ]
  }'
Body Params
string
required
length ≥ 1
^\d{6}$
string
enum
required
Allowed:
transferRequests
array | null
transferRequests
Headers
string
enum
Defaults to application/json

Generated from available response content types

Allowed:
string
enum
Defaults to application/json

Generated from available request content types

Allowed:
Response

Language
Credentials
Bearer
JWT
LoadingLoading…
Response
Click Try It! to start a request and see the response here! Or choose an example:
text/plain
application/json
text/json