Batch Adding External Banking Account Number - Payee
This endpoint allows partners to register multiple external bank accounts as payees in a single batch operation. Each account in the batch is linked by routing number, account number, and account type, and the entire request is secured with a one-time verification code. This approach reduces round-trip overhead when onboarding several payee accounts at once.
Endpoint
POST /api/fundsMovement/batch/externalPayee
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 customer needs to add multiple external bank accounts as payees simultaneously — for example, during initial onboarding of a business customer who pays multiple vendors, or when migrating an existing set of payee accounts into the Netevia platform. The batch operation combines all account additions into a single secure, verified transaction, reducing the number of OTP prompts required compared to adding each payee individually.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
requests | array | No | Array of external account objects to add as payees. Each item is either a base or secured external account request (see sub-fields below). |
requests[].routingNumber | string | Yes | ABA routing number of the external bank. |
requests[].accountNumber | string | Yes | Full account number at the external bank. |
requests[].name | string | Yes | Display name for this payee account. |
requests[].bankAccountType | string | Yes | Account type. Allowed values: SAVINGS, CHECKING. |
requests[].oneTimeCode | string | No (per-item) | Per-item 6-digit OTP for item-level verification (required when using the secured variant). Must match pattern ^\d{6}$. |
requests[].secureOperationType | string | No (per-item) | Verification method used for per-item OTP. Allowed values: ShortMessageCode, TimeBasedCode, LegacyTimeBasedCode. |
oneTimeCode | string | Yes | Top-level 6-digit OTP for the entire batch. Must match pattern ^\d{6}$. |
secureOperationType | string | Yes | Verification method for the top-level OTP. Allowed values: ShortMessageCode, TimeBasedCode, LegacyTimeBasedCode. |
{
"requests": [
{
"routingNumber": "021000021",
"accountNumber": "XXXXXXXXXX",
"name": "Vendor Payroll Account",
"bankAccountType": "CHECKING"
},
{
"routingNumber": "011401533",
"accountNumber": "XXXXXXXXXX",
"name": "Supplier Savings Account",
"bankAccountType": "SAVINGS"
}
],
"oneTimeCode": "847291",
"secureOperationType": "ShortMessageCode"
}Response
200 OK
Returns an array of result objects, one per submitted payee account request.
| Field | Type | Description |
|---|---|---|
[].mainNode | object | Details of the newly created external bank account record. |
[].mainNode.typename | string | GraphQL type name of the result node. |
[].mainNode.id | string | Unique identifier for the created external bank account. |
[].mainNode.name | string | Display name assigned to this payee account. |
[].mainNode.externalBankAccountDetails | object | Detailed account information. |
[].mainNode.externalBankAccountDetails.last4 | string | Last 4 digits of the account number. |
[].mainNode.externalBankAccountDetails.type | string | Account type (e.g., CHECKING, SAVINGS). |
[].mainNode.externalBankAccountDetails.routingNumber | string | ABA routing number of the external bank. |
[].mainNode.externalBankAccountDetails.accountNumber | string | Full account number (may be masked). |
[].mainNode.externalBankAccountDetails.createdAt | string (date-time) | Timestamp when the account details were created. |
[].mainNode.externalBankAccountDetails.updatedAt | string (date-time) | Timestamp when the account details were last updated. |
[].mainNode.accessDeniedErrorMessage | string | Error message if access was denied for this item; null if successful. |
[].mainNode.createdAt | string (date-time) | Timestamp when the payee record was created. |
[].mainNode.updatedAt | string (date-time) | Timestamp when the payee record was last updated. |
[].mainNode.errors | array | Per-item mutation errors, if any. |
[].mainNode.errors[].path | array of strings | Field path where the error occurred. |
[].mainNode.errors[].code | string | Machine-readable error code. |
[].mainNode.errors[].description | string | Human-readable error description. |
[].mutationResult | object | Overall mutation result for this item. |
[].mutationResult.errors | array | Top-level errors for this item's mutation, if any (same structure as mainNode.errors). |
[
{
"mainNode": {
"typename": "AddNonVerifiedExternalUSFinancialBankAccount",
"id": "extacct_01HX9KZQV3MTNR8WPBFYG2C4D",
"name": "Vendor Payroll Account",
"externalBankAccountDetails": {
"last4": "7890",
"type": "CHECKING",
"routingNumber": "021000021",
"accountNumber": "XXXXXXXXXX",
"createdAt": "2026-06-08T14:22:10Z",
"updatedAt": "2026-06-08T14:22:10Z"
},
"accessDeniedErrorMessage": null,
"createdAt": "2026-06-08T14:22:10Z",
"updatedAt": "2026-06-08T14:22:10Z",
"errors": []
},
"mutationResult": {
"errors": []
}
},
{
"mainNode": {
"typename": "AddNonVerifiedExternalUSFinancialBankAccount",
"id": "extacct_02JY0LARGS4NUTS9XQCGZH3E5F",
"name": "Supplier Savings Account",
"externalBankAccountDetails": {
"last4": "3412",
"type": "SAVINGS",
"routingNumber": "011401533",
"accountNumber": "XXXXXXXXXX",
"createdAt": "2026-06-08T14:22:11Z",
"updatedAt": "2026-06-08T14:22:11Z"
},
"accessDeniedErrorMessage": null,
"createdAt": "2026-06-08T14:22:11Z",
"updatedAt": "2026-06-08T14:22:11Z",
"errors": []
},
"mutationResult": {
"errors": []
}
}
]Error Codes
| Code | When it happens |
|---|---|
| 400 | Missing required fields (oneTimeCode, secureOperationType), invalid OTP format (must be exactly 6 digits), invalid bankAccountType (must be SAVINGS or CHECKING), or malformed routing/account number. |
| 401 | Token missing, expired, or invalid. |
| 403 | Insufficient permissions to add external payee accounts. |
| 404 | Customer or financial account context not found. |
| 500 | Internal server error. |
Common Mistakes
- Providing a
oneTimeCodethat does not exactly match the pattern^\d{6}$(e.g., including spaces, letters, or fewer/more than 6 digits) will cause a 400 validation error. - Setting
bankAccountTypeto a value other thanSAVINGSorCHECKING(case-sensitive) will fail validation — do not use lowercase or mixed-case variants. - Omitting the top-level
oneTimeCodeorsecureOperationTypefields, which are required at the batch level even if individual items carry their own OTP fields. - Sending raw, unmasked account numbers in logs or error reports — always sanitize account numbers as
XXXXXXXXXXin any diagnostic output. - Assuming a 200 response means all items succeeded — always inspect each item's
mainNode.errorsandmutationResult.errorsarrays for per-item failures within a successful batch response.
Related Endpoints
POST /api/fundsMovement/externalPayee— Add a single external bank account as a payee.GET /api/fundsMovement/externalPayees— List all external payee accounts for the current customer.DELETE /api/fundsMovement/externalPayee/{id}— Remove a specific external payee account.POST /api/fundsMovement/transfer— Initiate a funds transfer to a registered external payee.
Example
curl -X POST https://api.banking.netevia.dev/api/fundsMovement/batch/externalPayee \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"requests": [
{
"routingNumber": "021000021",
"accountNumber": "XXXXXXXXXX",
"name": "Vendor Payroll Account",
"bankAccountType": "CHECKING"
},
{
"routingNumber": "011401533",
"accountNumber": "XXXXXXXXXX",
"name": "Supplier Savings Account",
"bankAccountType": "SAVINGS"
}
],
"oneTimeCode": "847291",
"secureOperationType": "ShortMessageCode"
}'