Implementation guides
Bulk payment splits
When you owe a partner across many payments, settling each payment split individually is tedious. A bulk operation groups multiple splits owed to a single partnership into one batch you can track, mark paid together, and export as a statement.
Before you begin
A bulk operation is scoped to one partnership and settles that partner's payment splits. So you'll need:
- A partnership — see the Partnerships API.
- One or more payment splits owed to that partnership.
Bulk operations live under the /v1/bulk endpoint and always return under a data.bulk (list) or data (single) envelope. See the response envelope.
Create a bulk operation
Group splits by passing the partnership, a currency, a type, and the paymentSplits you want to include:
curl -X POST https://api.qualyhq.com/v1/bulk/create \
-H 'Authorization: ApiKey your-api-key-here' \
-H 'X-TENANT-ID: your-tenant-id-here' \
-H 'Content-Type: application/json' \
-d '{
"name": "March partner settlement",
"currency": "AUD",
"type": "group",
"partnership": "6607de740cf5287d324ddba7",
"paymentSplits": ["68762663f57e66320fad2c82", "68762541a4b0db2ef994e8d5"],
"dueAt": "2026-03-31T00:00:00.000Z"
}'
const res = await fetch('https://api.qualyhq.com/v1/bulk/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'ApiKey your-api-key-here',
'X-TENANT-ID': 'your-tenant-id-here',
},
body: JSON.stringify({
name: 'March partner settlement',
currency: 'AUD',
type: 'group',
partnership: '6607de740cf5287d324ddba7',
paymentSplits: ['68762663f57e66320fad2c82', '68762541a4b0db2ef994e8d5'],
dueAt: '2026-03-31T00:00:00.000Z',
}),
});
const { data: bulk } = await res.json();
console.log(bulk._id, bulk.status); // e.g. "…9568" "pending"
use Illuminate\Support\Facades\Http;
$bulk = Http::withHeaders([
'Authorization' => 'ApiKey your-api-key-here',
'X-TENANT-ID' => 'your-tenant-id-here',
])->post('https://api.qualyhq.com/v1/bulk/create', [
'name' => 'March partner settlement',
'currency' => 'AUD',
'type' => 'group',
'partnership' => '6607de740cf5287d324ddba7',
'paymentSplits' => ['68762663f57e66320fad2c82', '68762541a4b0db2ef994e8d5'],
'dueAt' => '2026-03-31T00:00:00.000Z',
])->json('data');
echo $bulk['_id'] . ' ' . $bulk['status'];
| Field | Required | Description |
|---|---|---|
name | Yes | A human-readable label for the batch. |
currency | Yes | The settlement currency (e.g. AUD). All included splits should share it. |
type | Yes | group for a batch you settle internally, or remittance for a cross-border/partner remittance. |
partnership | Yes | The partnership being settled. Accepts an ObjectId or a smart reference. |
paymentSplits | No | ObjectIds of the splits to include in the batch. |
dueAt | No | When the settlement is due. |
A new bulk operation starts with status: "pending".
List and retrieve
List bulk operations (returned under data.bulk), or fetch one by ID:
# List
curl "https://api.qualyhq.com/v1/bulk?limit=20" \
-H 'Authorization: ApiKey your-api-key-here' \
-H 'X-TENANT-ID: your-tenant-id-here'
# Retrieve one
curl "https://api.qualyhq.com/v1/bulk/69b2cff0d0882b77ac419568" \
-H 'Authorization: ApiKey your-api-key-here' \
-H 'X-TENANT-ID: your-tenant-id-here'
const headers = {
'Authorization': 'ApiKey your-api-key-here',
'X-TENANT-ID': 'your-tenant-id-here',
};
const { data } = await fetch('https://api.qualyhq.com/v1/bulk?limit=20', { headers })
.then((r) => r.json());
console.log(data.bulk); // array
const { data: one } = await fetch(
'https://api.qualyhq.com/v1/bulk/69b2cff0d0882b77ac419568',
{ headers },
).then((r) => r.json());
use Illuminate\Support\Facades\Http;
$api = Http::withHeaders([
'Authorization' => 'ApiKey your-api-key-here',
'X-TENANT-ID' => 'your-tenant-id-here',
]);
$list = $api->get('https://api.qualyhq.com/v1/bulk', ['limit' => 20])->json('data.bulk');
$one = $api->get('https://api.qualyhq.com/v1/bulk/69b2cff0d0882b77ac419568')->json('data');
To see which actions are available for a given batch in its current state, call GET /v1/bulk/{bulkOperationId}/options.
Mark a bulk operation as paid
When you've settled the batch, update its status. Valid statuses are pending, due, paid, and canceled. Set paidAt when marking it paid:
curl -X POST https://api.qualyhq.com/v1/bulk/69b2cff0d0882b77ac419568/update \
-H 'Authorization: ApiKey your-api-key-here' \
-H 'X-TENANT-ID: your-tenant-id-here' \
-H 'Content-Type: application/json' \
-d '{ "status": "paid", "paidAt": "2026-03-31T10:00:00.000Z" }'
const res = await fetch(
'https://api.qualyhq.com/v1/bulk/69b2cff0d0882b77ac419568/update',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'ApiKey your-api-key-here',
'X-TENANT-ID': 'your-tenant-id-here',
},
body: JSON.stringify({ status: 'paid', paidAt: '2026-03-31T10:00:00.000Z' }),
},
);
const { data: bulk } = await res.json();
console.log(bulk.status); // "paid"
use Illuminate\Support\Facades\Http;
$bulk = Http::withHeaders([
'Authorization' => 'ApiKey your-api-key-here',
'X-TENANT-ID' => 'your-tenant-id-here',
])->post('https://api.qualyhq.com/v1/bulk/69b2cff0d0882b77ac419568/update', [
'status' => 'paid',
'paidAt' => '2026-03-31T10:00:00.000Z',
])->json('data');
echo $bulk['status']; // "paid"
You can also send any other creatable field (for example name or paymentSplits) to the update endpoint to amend the batch.
Generate a statement PDF
Produce a settlement statement for the batch — handy to send the partner as a record of what was paid:
curl -X POST https://api.qualyhq.com/v1/bulk/69b2cff0d0882b77ac419568/pdf \
-H 'Authorization: ApiKey your-api-key-here' \
-H 'X-TENANT-ID: your-tenant-id-here'
Next steps
- Understand the splits that go into a batch: Creating payment splits.
- Use smart references to pass a partnership by natural key.
- Filter and paginate batches with Querying data.