curl --request POST \
--url https://api.next.orenda.finance/v1/batch-payments \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"action": "verify",
"payments": [
{
"payer": {
"account": {
"type": "uk",
"sortCode": "010203",
"accountNumber": "12345678"
}
},
"payee": {
"name": "Ada Lovelace",
"account": {
"type": "uk",
"sortCode": "040506",
"accountNumber": "87654321"
},
"accountType": "CONSUMER"
},
"reference": "Invoice 1024",
"amount": "150.00"
},
{
"payer": {
"account": {
"type": "iban",
"iban": "DE89370400440532013000"
}
},
"payee": {
"name": "Grace Hopper",
"account": {
"type": "iban",
"iban": "FR7630006000011234567890189",
"bic": "AGRIFRPP"
}
},
"reference": "Invoice 1025",
"amount": "200.00"
}
]
}
'import requests
url = "https://api.next.orenda.finance/v1/batch-payments"
payload = {
"action": "verify",
"payments": [
{
"payer": { "account": {
"type": "uk",
"sortCode": "010203",
"accountNumber": "12345678"
} },
"payee": {
"name": "Ada Lovelace",
"account": {
"type": "uk",
"sortCode": "040506",
"accountNumber": "87654321"
},
"accountType": "CONSUMER"
},
"reference": "Invoice 1024",
"amount": "150.00"
},
{
"payer": { "account": {
"type": "iban",
"iban": "DE89370400440532013000"
} },
"payee": {
"name": "Grace Hopper",
"account": {
"type": "iban",
"iban": "FR7630006000011234567890189",
"bic": "AGRIFRPP"
}
},
"reference": "Invoice 1025",
"amount": "200.00"
}
]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
action: 'verify',
payments: [
{
payer: {account: {type: 'uk', sortCode: '010203', accountNumber: '12345678'}},
payee: {
name: 'Ada Lovelace',
account: {type: 'uk', sortCode: '040506', accountNumber: '87654321'},
accountType: 'CONSUMER'
},
reference: 'Invoice 1024',
amount: '150.00'
},
{
payer: {account: {type: 'iban', iban: 'DE89370400440532013000'}},
payee: {
name: 'Grace Hopper',
account: {type: 'iban', iban: 'FR7630006000011234567890189', bic: 'AGRIFRPP'}
},
reference: 'Invoice 1025',
amount: '200.00'
}
]
})
};
fetch('https://api.next.orenda.finance/v1/batch-payments', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.next.orenda.finance/v1/batch-payments",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'action' => 'verify',
'payments' => [
[
'payer' => [
'account' => [
'type' => 'uk',
'sortCode' => '010203',
'accountNumber' => '12345678'
]
],
'payee' => [
'name' => 'Ada Lovelace',
'account' => [
'type' => 'uk',
'sortCode' => '040506',
'accountNumber' => '87654321'
],
'accountType' => 'CONSUMER'
],
'reference' => 'Invoice 1024',
'amount' => '150.00'
],
[
'payer' => [
'account' => [
'type' => 'iban',
'iban' => 'DE89370400440532013000'
]
],
'payee' => [
'name' => 'Grace Hopper',
'account' => [
'type' => 'iban',
'iban' => 'FR7630006000011234567890189',
'bic' => 'AGRIFRPP'
]
],
'reference' => 'Invoice 1025',
'amount' => '200.00'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.next.orenda.finance/v1/batch-payments"
payload := strings.NewReader("{\n \"action\": \"verify\",\n \"payments\": [\n {\n \"payer\": {\n \"account\": {\n \"type\": \"uk\",\n \"sortCode\": \"010203\",\n \"accountNumber\": \"12345678\"\n }\n },\n \"payee\": {\n \"name\": \"Ada Lovelace\",\n \"account\": {\n \"type\": \"uk\",\n \"sortCode\": \"040506\",\n \"accountNumber\": \"87654321\"\n },\n \"accountType\": \"CONSUMER\"\n },\n \"reference\": \"Invoice 1024\",\n \"amount\": \"150.00\"\n },\n {\n \"payer\": {\n \"account\": {\n \"type\": \"iban\",\n \"iban\": \"DE89370400440532013000\"\n }\n },\n \"payee\": {\n \"name\": \"Grace Hopper\",\n \"account\": {\n \"type\": \"iban\",\n \"iban\": \"FR7630006000011234567890189\",\n \"bic\": \"AGRIFRPP\"\n }\n },\n \"reference\": \"Invoice 1025\",\n \"amount\": \"200.00\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.next.orenda.finance/v1/batch-payments")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"action\": \"verify\",\n \"payments\": [\n {\n \"payer\": {\n \"account\": {\n \"type\": \"uk\",\n \"sortCode\": \"010203\",\n \"accountNumber\": \"12345678\"\n }\n },\n \"payee\": {\n \"name\": \"Ada Lovelace\",\n \"account\": {\n \"type\": \"uk\",\n \"sortCode\": \"040506\",\n \"accountNumber\": \"87654321\"\n },\n \"accountType\": \"CONSUMER\"\n },\n \"reference\": \"Invoice 1024\",\n \"amount\": \"150.00\"\n },\n {\n \"payer\": {\n \"account\": {\n \"type\": \"iban\",\n \"iban\": \"DE89370400440532013000\"\n }\n },\n \"payee\": {\n \"name\": \"Grace Hopper\",\n \"account\": {\n \"type\": \"iban\",\n \"iban\": \"FR7630006000011234567890189\",\n \"bic\": \"AGRIFRPP\"\n }\n },\n \"reference\": \"Invoice 1025\",\n \"amount\": \"200.00\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.next.orenda.finance/v1/batch-payments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"action\": \"verify\",\n \"payments\": [\n {\n \"payer\": {\n \"account\": {\n \"type\": \"uk\",\n \"sortCode\": \"010203\",\n \"accountNumber\": \"12345678\"\n }\n },\n \"payee\": {\n \"name\": \"Ada Lovelace\",\n \"account\": {\n \"type\": \"uk\",\n \"sortCode\": \"040506\",\n \"accountNumber\": \"87654321\"\n },\n \"accountType\": \"CONSUMER\"\n },\n \"reference\": \"Invoice 1024\",\n \"amount\": \"150.00\"\n },\n {\n \"payer\": {\n \"account\": {\n \"type\": \"iban\",\n \"iban\": \"DE89370400440532013000\"\n }\n },\n \"payee\": {\n \"name\": \"Grace Hopper\",\n \"account\": {\n \"type\": \"iban\",\n \"iban\": \"FR7630006000011234567890189\",\n \"bic\": \"AGRIFRPP\"\n }\n },\n \"reference\": \"Invoice 1025\",\n \"amount\": \"200.00\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"requestId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "PENDING",
"batchId": "b2c3d4e5-0000-1111-2222-333344445555",
"expiresAt": "2026-08-17T09:00:00.000Z"
}
}Multi-customer batch payments
The original single endpoint, multi-customer form. The action field selects the step (verify, initiate, passkey-challenge, submit) exactly as on POST /v1/customers/{customerId}/batch-payments, and the draft behaviour is the same: verify returns the draft’s batchId and expiresAt, submit accepts a batchId to pay one.
Back office only, multi-customer. No customerId in the path: each item’s payer account is resolved globally and authorised per item against the caller, so one batch can pay from the accounts of any customers the caller is responsible for. An account the caller isn’t responsible for, including an unassigned account, is rejected with 401, as is a management role that resolves to no customers. A non-management caller can’t use this route.
The passkey is always the operator’s own. The challenge is issued against the signed-in user, never the customer being paid. The ceremony is identical to the single-customer route; only the tenant the credential is looked up in differs: a customer’s passkey is resolved against their own program (honouring the sandbox flag), a management operator’s against the shared management pool, production only. So a management passkey ceremony always resolves to production, even for a sandbox batch.
No file upload here. A CSV or pain.001 file is accepted only on POST /v1/batch-payments/verify; sending one to this route is a 400. Send payments instead.
curl --request POST \
--url https://api.next.orenda.finance/v1/batch-payments \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"action": "verify",
"payments": [
{
"payer": {
"account": {
"type": "uk",
"sortCode": "010203",
"accountNumber": "12345678"
}
},
"payee": {
"name": "Ada Lovelace",
"account": {
"type": "uk",
"sortCode": "040506",
"accountNumber": "87654321"
},
"accountType": "CONSUMER"
},
"reference": "Invoice 1024",
"amount": "150.00"
},
{
"payer": {
"account": {
"type": "iban",
"iban": "DE89370400440532013000"
}
},
"payee": {
"name": "Grace Hopper",
"account": {
"type": "iban",
"iban": "FR7630006000011234567890189",
"bic": "AGRIFRPP"
}
},
"reference": "Invoice 1025",
"amount": "200.00"
}
]
}
'import requests
url = "https://api.next.orenda.finance/v1/batch-payments"
payload = {
"action": "verify",
"payments": [
{
"payer": { "account": {
"type": "uk",
"sortCode": "010203",
"accountNumber": "12345678"
} },
"payee": {
"name": "Ada Lovelace",
"account": {
"type": "uk",
"sortCode": "040506",
"accountNumber": "87654321"
},
"accountType": "CONSUMER"
},
"reference": "Invoice 1024",
"amount": "150.00"
},
{
"payer": { "account": {
"type": "iban",
"iban": "DE89370400440532013000"
} },
"payee": {
"name": "Grace Hopper",
"account": {
"type": "iban",
"iban": "FR7630006000011234567890189",
"bic": "AGRIFRPP"
}
},
"reference": "Invoice 1025",
"amount": "200.00"
}
]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
action: 'verify',
payments: [
{
payer: {account: {type: 'uk', sortCode: '010203', accountNumber: '12345678'}},
payee: {
name: 'Ada Lovelace',
account: {type: 'uk', sortCode: '040506', accountNumber: '87654321'},
accountType: 'CONSUMER'
},
reference: 'Invoice 1024',
amount: '150.00'
},
{
payer: {account: {type: 'iban', iban: 'DE89370400440532013000'}},
payee: {
name: 'Grace Hopper',
account: {type: 'iban', iban: 'FR7630006000011234567890189', bic: 'AGRIFRPP'}
},
reference: 'Invoice 1025',
amount: '200.00'
}
]
})
};
fetch('https://api.next.orenda.finance/v1/batch-payments', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.next.orenda.finance/v1/batch-payments",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'action' => 'verify',
'payments' => [
[
'payer' => [
'account' => [
'type' => 'uk',
'sortCode' => '010203',
'accountNumber' => '12345678'
]
],
'payee' => [
'name' => 'Ada Lovelace',
'account' => [
'type' => 'uk',
'sortCode' => '040506',
'accountNumber' => '87654321'
],
'accountType' => 'CONSUMER'
],
'reference' => 'Invoice 1024',
'amount' => '150.00'
],
[
'payer' => [
'account' => [
'type' => 'iban',
'iban' => 'DE89370400440532013000'
]
],
'payee' => [
'name' => 'Grace Hopper',
'account' => [
'type' => 'iban',
'iban' => 'FR7630006000011234567890189',
'bic' => 'AGRIFRPP'
]
],
'reference' => 'Invoice 1025',
'amount' => '200.00'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.next.orenda.finance/v1/batch-payments"
payload := strings.NewReader("{\n \"action\": \"verify\",\n \"payments\": [\n {\n \"payer\": {\n \"account\": {\n \"type\": \"uk\",\n \"sortCode\": \"010203\",\n \"accountNumber\": \"12345678\"\n }\n },\n \"payee\": {\n \"name\": \"Ada Lovelace\",\n \"account\": {\n \"type\": \"uk\",\n \"sortCode\": \"040506\",\n \"accountNumber\": \"87654321\"\n },\n \"accountType\": \"CONSUMER\"\n },\n \"reference\": \"Invoice 1024\",\n \"amount\": \"150.00\"\n },\n {\n \"payer\": {\n \"account\": {\n \"type\": \"iban\",\n \"iban\": \"DE89370400440532013000\"\n }\n },\n \"payee\": {\n \"name\": \"Grace Hopper\",\n \"account\": {\n \"type\": \"iban\",\n \"iban\": \"FR7630006000011234567890189\",\n \"bic\": \"AGRIFRPP\"\n }\n },\n \"reference\": \"Invoice 1025\",\n \"amount\": \"200.00\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.next.orenda.finance/v1/batch-payments")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"action\": \"verify\",\n \"payments\": [\n {\n \"payer\": {\n \"account\": {\n \"type\": \"uk\",\n \"sortCode\": \"010203\",\n \"accountNumber\": \"12345678\"\n }\n },\n \"payee\": {\n \"name\": \"Ada Lovelace\",\n \"account\": {\n \"type\": \"uk\",\n \"sortCode\": \"040506\",\n \"accountNumber\": \"87654321\"\n },\n \"accountType\": \"CONSUMER\"\n },\n \"reference\": \"Invoice 1024\",\n \"amount\": \"150.00\"\n },\n {\n \"payer\": {\n \"account\": {\n \"type\": \"iban\",\n \"iban\": \"DE89370400440532013000\"\n }\n },\n \"payee\": {\n \"name\": \"Grace Hopper\",\n \"account\": {\n \"type\": \"iban\",\n \"iban\": \"FR7630006000011234567890189\",\n \"bic\": \"AGRIFRPP\"\n }\n },\n \"reference\": \"Invoice 1025\",\n \"amount\": \"200.00\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.next.orenda.finance/v1/batch-payments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"action\": \"verify\",\n \"payments\": [\n {\n \"payer\": {\n \"account\": {\n \"type\": \"uk\",\n \"sortCode\": \"010203\",\n \"accountNumber\": \"12345678\"\n }\n },\n \"payee\": {\n \"name\": \"Ada Lovelace\",\n \"account\": {\n \"type\": \"uk\",\n \"sortCode\": \"040506\",\n \"accountNumber\": \"87654321\"\n },\n \"accountType\": \"CONSUMER\"\n },\n \"reference\": \"Invoice 1024\",\n \"amount\": \"150.00\"\n },\n {\n \"payer\": {\n \"account\": {\n \"type\": \"iban\",\n \"iban\": \"DE89370400440532013000\"\n }\n },\n \"payee\": {\n \"name\": \"Grace Hopper\",\n \"account\": {\n \"type\": \"iban\",\n \"iban\": \"FR7630006000011234567890189\",\n \"bic\": \"AGRIFRPP\"\n }\n },\n \"reference\": \"Invoice 1025\",\n \"amount\": \"200.00\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"requestId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "PENDING",
"batchId": "b2c3d4e5-0000-1111-2222-333344445555",
"expiresAt": "2026-08-17T09:00:00.000Z"
}
}Authorizations
The caller's access_token from authentication. Management API callers send the id_token. The program and environment come from the token.
Query Parameters
Required on the Management API, where the token carries no program: omitting it returns 400. Customer API callers resolve the program from their token and should omit it; a value sent there is ignored.
Body
The step to run.
verify, initiate, passkey-challenge, submit Management only. Targets a single customer on this path-less route: this is the only way to scope the batch to one customer here. Omit to pay across every customer the caller is responsible for. Ignored on the /v1/customers/{customerId}/... routes, where the path is authoritative and cannot be overridden.
"customer-123"
The payment items. Required for verify, initiate, and submit. Payers may belong to different customers the caller is responsible for.
Show child attributes
Show child attributes
The strong-customer-authentication challenge from initiate. Pass it back on submit.
Show child attributes
Show child attributes
Step-up confirmation (for submit). Set method to passkey, totp, or pin and include that method's fields. pin is a program capability: see Program capabilities.
- Passkey
- 2FA code
- PIN
Show child attributes
Show child attributes
Optional. Mint a fresh UUID for every batch. Not a replay key: a shared key re-runs the batch rather than returning the first result.
Optional. On verify, the draft being re-verified after edits: omit to create a new draft. On submit, the draft to pay; it is checked for expiry and ownership and cannot be paid twice. Absent keeps the pre-draft behaviour.
Legacy step-up credential. Superseded by confirmation.
Legacy TOTP step-up code. Superseded by confirmation.
Legacy passkey session id. Superseded by confirmation.
Legacy passkey assertion. Superseded by confirmation.