# Reconcile settlements

> Pull settlement data from the Payments API, the legacy path, and tie it back to the deposits in your bank account and the orders in your own system.

Source: https://hub.ozow.com/integration-methods/apis/deprecated-integrations/reconcile-settlements/

This guide shows you how to pull settlement data out of the Payments API and tie it back to the
deposits in your bank account and the orders in your own system.

> ℹ️ **You're reading the legacy integration.** This applies if your integration posts to
> `api.ozow.com` and builds a SHA512 hash. Build a new integration against [Reconcile
> settlements](https://hub.ozow.com/integration-methods/apis/settlements/reconcile-settlements.md) on One API instead.

## Where settlements fit

When a customer pays you through Ozow, the money lands with Ozow first. Ozow then transfers what
you're owed to your bank account. That transfer is a settlement.

How payments are grouped into settlements depends on your settlement model and the payment method.
By default Ozow groups transactions together into settlements, but there are several settlement
models, and yours may include a custom arrangement. Your specific setup is agreed during onboarding;
if you're not sure what applies to you, speak to your account manager.

For reconciliation, the practical consequence is: don't hard-code assumptions about how many records
a settlement contains, or how often settlements arrive. Read what the API returns.

There are two separate things to reconcile:

- **Did the customer pay?** Answered by transaction status.
- **Did Ozow pay me?** Answered by settlement data, this guide.

A transaction reaching `Complete` doesn't mean the money has reached you. Settlement happens later,
on a cycle that depends on the payment method. See
[Settlements](https://hub.ozow.com/payment-products/settlements-and-float/settlements.md) for how that works.

If you reconcile occasionally, the [Ozow Dashboard](https://dash.ozow.com) shows all of this with no
development work. Build this when you're reconciling regularly or at volume.

## What you'll build

Two endpoints do the work, and you need both:

| Endpoint | Gives you | Answers |
|---|---|---|
| `GET /secure/settlements` | One row per settlement | What did Ozow pay me? |
| `GET /secure/settlements/getsitesettlements` | One row per settled transaction | Which payments made that up? |

A typical daily job:

1. Fetch your latest settlements and store them.
2. Fetch the transactions behind them for the period.
3. Match each settlement to a deposit on your bank statement.
4. Match each transaction to an order in your system.
5. Flag whatever doesn't match.

The rest of this guide walks through those steps. For complete field lists, all parameters and error
responses, see the [Payments API reference](https://hub.ozow.com/api-reference/payments-api.md).

## Before you start

You'll need your API key from the [Ozow Dashboard](https://dash.ozow.com).

Both endpoints are simple GETs authenticated with your API key in a header:

```http
ApiKey: YOUR_API_KEY
```

---

## Step 1: Fetch your settlements

```endpoint
GET https://api.ozow.com/secure/settlements?count=100
```

Staging: `https://stagingapi.ozow.com/secure/settlements`

The only parameter is `count`, how many of the most recent settlements to return, up to 100.

**cURL**

```bash
curl -X GET "https://api.ozow.com/secure/settlements?count=100" \
  -H "ApiKey: <YOUR_API_KEY>" \
  -H "Accept: application/json"
```

**C#**

```csharp
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("ApiKey", apiKey);
client.DefaultRequestHeaders.Add("Accept", "application/json");

var response = await client.GetAsync("https://api.ozow.com/secure/settlements?count=100");
var body = await response.Content.ReadAsStringAsync();
```

**PHP**

```php
$ch = curl_init('https://api.ozow.com/secure/settlements?count=100');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['ApiKey: ' . $apiKey, 'Accept: application/json'],
]);
$response = curl_exec($ch);
curl_close($ch);
```

**JavaScript**

```javascript
const response = await fetch(
  "https://api.ozow.com/secure/settlements?count=100",
  { headers: { ApiKey: apiKey, Accept: "application/json" } },
);
const data = await response.json();
```

**Python**

```python
import requests

response = requests.get(
    "https://api.ozow.com/secure/settlements",
    params={"count": 100},
    headers={"ApiKey": api_key, "Accept": "application/json"},
)
data = response.json()
```

You get back a settlements array. Three fields do most of the work:

| Field | Use it for |
|---|---|
| `id` | Your primary key, and the join to the transaction detail in step 2 |
| `bankReference` | Matching to the deposit on your bank statement |
| `amount` | The amount actually transferred, in the settlement currency |

`status` will be `Pending` (the settlement was created) or `Complete` (the payment has been initiated).

> ⚠️ `Complete` does not mean the money has arrived. It means Ozow has initiated the payment. Your
> bank statement is the confirmation.

Check the `errors` array in the response before processing the settlements.

### Store what you fetch

This endpoint has no date filter. You can only ask for the latest *n*, capped at 100; so you can't
come back later and request last March.

Poll on a schedule, store every settlement keyed on `id`, and skip the ones you already have. Choose
a frequency where you can't possibly accumulate more than 100 new settlements between runs; daily is
comfortable for most merchants. If you do fall further behind than that, the missing settlements
aren't retrievable here and you'll need the Dashboard or Ozow Support.

---

## Step 2: Fetch the transactions behind them

```endpoint
GET https://api.ozow.com/secure/settlements/getsitesettlements?fromDate=2026-09-01&toDate=2026-09-30
```

Staging: `https://stagingapi.ozow.com/secure/settlements/getsitesettlements`

Both `fromDate` and `toDate` are required, in `yyyy-mm-dd` format. Unlike step 1, this one does take
a date range; so it's where you go for history.

**cURL**

```bash
curl -X GET "https://api.ozow.com/secure/settlements/getsitesettlements?fromDate=2026-09-01&toDate=2026-09-30" \
  -H "ApiKey: <YOUR_API_KEY>" \
  -H "Accept: application/json"
```

**C#**

```csharp
var url =
    "https://api.ozow.com/secure/settlements/getsitesettlements"
    + "?fromDate=2026-09-01&toDate=2026-09-30";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("ApiKey", apiKey);
client.DefaultRequestHeaders.Add("Accept", "application/json");

var response = await client.GetAsync(url);
var body = await response.Content.ReadAsStringAsync();
```

**PHP**

```php
$url = 'https://api.ozow.com/secure/settlements/getsitesettlements'
     . '?fromDate=2026-09-01&toDate=2026-09-30';

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['ApiKey: ' . $apiKey, 'Accept: application/json'],
]);
$response = curl_exec($ch);
curl_close($ch);
```

**JavaScript**

```javascript
const params = new URLSearchParams({
  fromDate: "2026-09-01",
  toDate: "2026-09-30",
});

const response = await fetch(
  `https://api.ozow.com/secure/settlements/getsitesettlements?${params}`,
  { headers: { ApiKey: apiKey, Accept: "application/json" } },
);
const data = await response.json();
```

**Python**

```python
import requests

response = requests.get(
    "https://api.ozow.com/secure/settlements/getsitesettlements",
    params={"fromDate": "2026-09-01", "toDate": "2026-09-30"},
    headers={"ApiKey": api_key, "Accept": "application/json"},
)
data = response.json()
```

You get an array with one entry per settled transaction. The fields you'll use:

| Field | Use it for |
|---|---|
| `settlementId` | Grouping transactions by settlement, joins to `id` from step 1 |
| `transactionReference` | Matching to the order in your own system |
| `transactionId` | Ozow's identifier for the payment, as a fallback join |
| `amount` | The settled amount for that transaction |

Group the rows by `settlementId`. Each group should total that settlement's `amount` from step 1. If
it does, your two views agree and you can reconcile with confidence. If a group does not total its
settlement, contact [support@ozow.com](mailto:support@ozow.com) with the `settlementId`.

---

## Step 3: Match settlements to your bank account

Match on **`bankReference`**. It's Ozow's reference for the settlement and it's what appears on your
statement, which makes it a reliable join. Confirm the `amount` agrees.

Don't match on amount and date alone, two settlements of the same value in the same week is entirely
possible.

## Step 4: Match transactions to your orders

Match on **`transactionReference`** where you set your own reference when creating the payment.
That's the most reliable join, because it's your identifier.

Where you don't have one, match on **`transactionId`**: the Ozow identifier you stored when the
payment completed. If you aren't storing that at payment time, start; reconciliation is much harder
without it.

**Never match on amount alone.** Two customers paying the same amount on the same day is routine,
and amount-matching produces quietly wrong results rather than obvious failures.

## Step 5: Flag what doesn't match

Check both directions:

- **Line items you can't place**: a settled transaction with no matching order
- **Orders you expected to see settled but didn't**: a completed payment that hasn't appeared in any
  settlement

Give the second a tolerance window: a completed transaction that hasn't settled yet is normal, one
that hasn't settled well past its expected cycle isn't.

---

## What not to reconcile against

Three assumptions that produce apparent differences where none exist:

**Refunds don't reduce settlements.** Refunds come out of your
[float](https://hub.ozow.com/payment-products/settlements-and-float/float-top-up.md), not your settlement. A
refunded transaction still settles in full.

**Fees don't reduce settlements either.** Billing is handled separately from settlement.

**Only `Complete` transactions settle.** Cancelled, abandoned, errored, voided and pending
transactions never appear in settlement data.

Settlement periods also won't line up with your accounting periods, a settlement can span a month
boundary. Reconcile by settlement, then map settlements to periods, not the other way round.

## Statuses

Settlement statuses are separate from transaction statuses and reuse many of the same words, so
check which one you're reading before you branch on it. See [Transaction and settlement
statuses](https://hub.ozow.com/integration-methods/statuses.md).

## Next steps

- Full field lists, parameters and error responses; [Payments API reference](https://hub.ozow.com/api-reference/payments-api.md)
- How settlements work, [Settlements](https://hub.ozow.com/payment-products/settlements-and-float/settlements.md)
- Statuses across transactions and settlements, [Transaction and settlement statuses](https://hub.ozow.com/integration-methods/statuses.md)
- Moving to One API, [Migrating to One API](https://hub.ozow.com/integration-methods/apis/deprecated-integrations/migrating-to-one-api.md)