# Bulk payment splits

> Group many partner payment splits into one settlement, mark it paid, and generate a statement PDF.

When you owe a partner across many payments, settling each [payment split](/docs/guides/creating-payment-splits.md) 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](/docs/guides/creating-payment-splits.md). So you'll need:

- A **partnership** — see the [Partnerships API](https://v1-spec.qualyhq.com/#post-/v1/partnerships/create).
- 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](/docs/queries.md#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**

```bash
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"
  }'
```

**JavaScript**

```javascript
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"
```

**PHP (Laravel)**

```php
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](/docs/smart-references.md). |
| `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:

**cURL**

```bash
# 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'
```

**JavaScript**

```javascript
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());
```

**PHP (Laravel)**

```php
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**

```bash
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" }'
```

**JavaScript**

```javascript
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"
```

**PHP (Laravel)**

```php
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:

```bash
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](/docs/guides/creating-payment-splits.md).
- Use [smart references](/docs/smart-references.md) to pass a partnership by natural key.
- Filter and paginate batches with [Querying data](/docs/queries.md).
