# Finance & settlements

> API reference · Wathiqaty Insurer API v1 (draft)

Every captured payment freezes its breakdown: gross (tax-inclusive) = net + taxes, and Wathiqaty's commission is a share of the net. Commission accrues on the ledger at capture and is reversed in proportion on refunds. Wathiqaty requests settlement of the balance periodically; you pay and upload the proof.

Base URL: `https://sandbox-api.wathiqaty.com/api/v1` (sandbox), `https://api.wathiqaty.com/api/v1` (production).

- List captured payments: `GET /partner/finance/payments`
- List commission ledger entries: `GET /partner/finance/ledger`
- Get the commission balance: `GET /partner/finance/balance`
- List settlements: `GET /partner/commission-settlements`
- Get a settlement: `GET /partner/commission-settlements/{id}`
- Get an upload URL for the proof: `POST /partner/commission-settlements/{id}/proof-upload-url`
- Submit payment proof: `POST /partner/commission-settlements/{id}/proof`

## List captured payments

`GET /partner/finance/payments`

- Auth: Bearer token, scope `finance:read`

### Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `paidFrom` | date | no | Captured on or after (Cairo date). |
| `paidTo` | date | no | Captured on or before (Cairo date). |
| `policyId` | uuid | no | For this policy. |
| `page` | integer | no | Page number, from 1. Default 1. |
| `size` | integer | no | Items per page, 1–100. Default 20. |
| `sortOrder` | string | no | Default `desc`. Use `asc` with `sortBy=updatedAt` for a change feed. One of: `asc`, `desc`. |

### Request examples

```bash
curl -X GET "https://sandbox-api.wathiqaty.com/api/v1/partner/finance/payments" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

```js
const res = await fetch("https://sandbox-api.wathiqaty.com/api/v1/partner/finance/payments", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${accessToken}`,
  },
})
const { data, error } = await res.json()
if (!res.ok) throw new Error(`${res.status} ${error.code}`)
```

```python
import requests

res = requests.get(
    "https://sandbox-api.wathiqaty.com/api/v1/partner/finance/payments",
    headers={
        "Authorization": f"Bearer {access_token}",
    },
    timeout=30,
)
payload = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {payload['error']['code']}")
data = payload["data"]
```

```csharp
using var req = new HttpRequestMessage(HttpMethod.Get,
    "https://sandbox-api.wathiqaty.com/api/v1/partner/finance/payments");
req.Headers.TryAddWithoutValidation("Authorization", $"Bearer {accessToken}");
using var res = await http.SendAsync(req);
var json = await res.Content.ReadAsStringAsync();
res.EnsureSuccessStatusCode();
```

### Response 200

A page of payments.

```json
{
  "status": "success",
  "data": {
    "items": [
      {
        "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
        "policyId": "6f1c2d3e-4b5a-4c69-8d7e-1f2a3b4c5d6e",
        "paidAt": "2026-11-05T09:15:00.000Z",
        "gross": "9500.00",
        "taxes": [
          {
            "name": "VAT",
            "rate": "14.00",
            "amount": "1166.67"
          }
        ],
        "net": "8333.33",
        "commission": "833.33",
        "insurerNet": "7500.00",
        "refunded": "0.00"
      }
    ],
    "meta": {
      "page": 1,
      "size": 20,
      "totalItems": 1,
      "totalPages": 1,
      "hasNextPage": false,
      "hasPreviousPage": false
    }
  },
  "error": null,
  "metadata": {
    "timestamp": "2026-11-05T09:15:02.481Z",
    "path": "/api/v1/partner/…",
    "method": "GET",
    "requestId": "8d7e2c1a-41f0-4a4e-9a55-6f0b3c2d1e77"
  }
}
```

## List commission ledger entries

`GET /partner/finance/ledger`

- Auth: Bearer token, scope `finance:read`

Append-only: `accrual` (+), `reversal` (−), `settlement_paid` (−).

### Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `from` | date | no | On or after. |
| `to` | date | no | On or before. |
| `page` | integer | no | Page number, from 1. Default 1. |
| `size` | integer | no | Items per page, 1–100. Default 20. |
| `sortOrder` | string | no | Default `desc`. Use `asc` with `sortBy=updatedAt` for a change feed. One of: `asc`, `desc`. |

### Request examples

```bash
curl -X GET "https://sandbox-api.wathiqaty.com/api/v1/partner/finance/ledger" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

```js
const res = await fetch("https://sandbox-api.wathiqaty.com/api/v1/partner/finance/ledger", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${accessToken}`,
  },
})
const { data, error } = await res.json()
if (!res.ok) throw new Error(`${res.status} ${error.code}`)
```

```python
import requests

res = requests.get(
    "https://sandbox-api.wathiqaty.com/api/v1/partner/finance/ledger",
    headers={
        "Authorization": f"Bearer {access_token}",
    },
    timeout=30,
)
payload = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {payload['error']['code']}")
data = payload["data"]
```

```csharp
using var req = new HttpRequestMessage(HttpMethod.Get,
    "https://sandbox-api.wathiqaty.com/api/v1/partner/finance/ledger");
req.Headers.TryAddWithoutValidation("Authorization", $"Bearer {accessToken}");
using var res = await http.SendAsync(req);
var json = await res.Content.ReadAsStringAsync();
res.EnsureSuccessStatusCode();
```

### Response 200

A page of entries.

```json
{
  "status": "success",
  "data": {
    "items": [
      {
        "id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
        "type": "accrual",
        "amount": "833.33",
        "paymentId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
        "createdAt": "2026-11-05T09:15:01.000Z"
      },
      {
        "id": "6f7a8b9c-0d1e-4f2a-9b3c-4d5e6f7a8b9c",
        "type": "reversal",
        "amount": "-620.27",
        "paymentId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
        "createdAt": "2026-11-22T10:00:01.000Z"
      }
    ],
    "meta": {
      "page": 1,
      "size": 20,
      "totalItems": 2,
      "totalPages": 1,
      "hasNextPage": false,
      "hasPreviousPage": false
    }
  },
  "error": null,
  "metadata": {
    "timestamp": "2026-11-05T09:15:02.481Z",
    "path": "/api/v1/partner/…",
    "method": "GET",
    "requestId": "8d7e2c1a-41f0-4a4e-9a55-6f0b3c2d1e77"
  }
}
```

## Get the commission balance

`GET /partner/finance/balance`

- Auth: Bearer token, scope `finance:read`

### Request examples

```bash
curl -X GET "https://sandbox-api.wathiqaty.com/api/v1/partner/finance/balance" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

```js
const res = await fetch("https://sandbox-api.wathiqaty.com/api/v1/partner/finance/balance", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${accessToken}`,
  },
})
const { data, error } = await res.json()
if (!res.ok) throw new Error(`${res.status} ${error.code}`)
```

```python
import requests

res = requests.get(
    "https://sandbox-api.wathiqaty.com/api/v1/partner/finance/balance",
    headers={
        "Authorization": f"Bearer {access_token}",
    },
    timeout=30,
)
payload = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {payload['error']['code']}")
data = payload["data"]
```

```csharp
using var req = new HttpRequestMessage(HttpMethod.Get,
    "https://sandbox-api.wathiqaty.com/api/v1/partner/finance/balance");
req.Headers.TryAddWithoutValidation("Authorization", $"Bearer {accessToken}");
using var res = await http.SendAsync(req);
var json = await res.Content.ReadAsStringAsync();
res.EnsureSuccessStatusCode();
```

### Response 200

What you owe Wathiqaty now.

```json
{
  "status": "success",
  "data": {
    "commissionDue": "184500.00",
    "currency": "EGP",
    "lastSettledAt": "2026-11-03T12:00:00.000Z"
  },
  "error": null,
  "metadata": {
    "timestamp": "2026-11-05T09:15:02.481Z",
    "path": "/api/v1/partner/…",
    "method": "GET",
    "requestId": "8d7e2c1a-41f0-4a4e-9a55-6f0b3c2d1e77"
  }
}
```

## List settlements

`GET /partner/commission-settlements`

- Auth: Bearer token, scope `finance:read`

### Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | string | no | Settlement status. One of: `requested`, `proof_submitted`, `confirmed`, `rejected`, `cancelled`. |
| `page` | integer | no | Page number, from 1. Default 1. |
| `size` | integer | no | Items per page, 1–100. Default 20. |
| `sortOrder` | string | no | Default `desc`. Use `asc` with `sortBy=updatedAt` for a change feed. One of: `asc`, `desc`. |

### Request examples

```bash
curl -X GET "https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

```js
const res = await fetch("https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${accessToken}`,
  },
})
const { data, error } = await res.json()
if (!res.ok) throw new Error(`${res.status} ${error.code}`)
```

```python
import requests

res = requests.get(
    "https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements",
    headers={
        "Authorization": f"Bearer {access_token}",
    },
    timeout=30,
)
payload = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {payload['error']['code']}")
data = payload["data"]
```

```csharp
using var req = new HttpRequestMessage(HttpMethod.Get,
    "https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements");
req.Headers.TryAddWithoutValidation("Authorization", $"Bearer {accessToken}");
using var res = await http.SendAsync(req);
var json = await res.Content.ReadAsStringAsync();
res.EnsureSuccessStatusCode();
```

### Response 200

A page of settlements.

```json
{
  "status": "success",
  "data": {
    "items": [
      {
        "id": "e4f5a6b7-c8d9-4e0f-9a1b-2c3d4e5f6a7b",
        "status": "requested",
        "periodFrom": "2026-11-01",
        "periodTo": "2026-11-30",
        "amount": "184500.00",
        "platformBankAccount": {
          "bank": "National Bank of Egypt",
          "iban": "EG380019000500000000263180002"
        },
        "proof": null,
        "requestedAt": "2026-12-01T07:00:00.000Z",
        "updatedAt": "2026-12-01T07:00:00.000Z"
      }
    ],
    "meta": {
      "page": 1,
      "size": 20,
      "totalItems": 1,
      "totalPages": 1,
      "hasNextPage": false,
      "hasPreviousPage": false
    }
  },
  "error": null,
  "metadata": {
    "timestamp": "2026-11-05T09:15:02.481Z",
    "path": "/api/v1/partner/…",
    "method": "GET",
    "requestId": "8d7e2c1a-41f0-4a4e-9a55-6f0b3c2d1e77"
  }
}
```

## Get a settlement

`GET /partner/commission-settlements/{id}`

- Auth: Bearer token, scope `finance:read`

### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid | yes | The settlement's Wathiqaty id. |

### Request examples

```bash
curl -X GET "https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements/{id}" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

```js
const res = await fetch("https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements/{id}", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${accessToken}`,
  },
})
const { data, error } = await res.json()
if (!res.ok) throw new Error(`${res.status} ${error.code}`)
```

```python
import requests

res = requests.get(
    "https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements/{id}",
    headers={
        "Authorization": f"Bearer {access_token}",
    },
    timeout=30,
)
payload = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {payload['error']['code']}")
data = payload["data"]
```

```csharp
using var req = new HttpRequestMessage(HttpMethod.Get,
    "https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements/{id}");
req.Headers.TryAddWithoutValidation("Authorization", $"Bearer {accessToken}");
using var res = await http.SendAsync(req);
var json = await res.Content.ReadAsStringAsync();
res.EnsureSuccessStatusCode();
```

### Response 200

The settlement.

```json
{
  "status": "success",
  "data": {
    "id": "e4f5a6b7-c8d9-4e0f-9a1b-2c3d4e5f6a7b",
    "status": "requested",
    "periodFrom": "2026-11-01",
    "periodTo": "2026-11-30",
    "amount": "184500.00",
    "platformBankAccount": {
      "bank": "National Bank of Egypt",
      "iban": "EG380019000500000000263180002"
    },
    "proof": null,
    "requestedAt": "2026-12-01T07:00:00.000Z",
    "updatedAt": "2026-12-01T07:00:00.000Z"
  },
  "error": null,
  "metadata": {
    "timestamp": "2026-11-05T09:15:02.481Z",
    "path": "/api/v1/partner/…",
    "method": "GET",
    "requestId": "8d7e2c1a-41f0-4a4e-9a55-6f0b3c2d1e77"
  }
}
```

### Errors

| Status | Code | When |
| --- | --- | --- |
| 404 | `not_found` | Settlement doesn't exist or isn't your company's. |

Plus the generic errors any route can return: [Errors](/guides/errors.md).

## Get an upload URL for the proof

`POST /partner/commission-settlements/{id}/proof-upload-url`

- Auth: Bearer token, scope `finance:write`

Returns a presigned POST. Send the file straight to `url` as `multipart/form-data` with every entry of `fields` first, then `file`. PDF, PNG or JPEG, up to 10 MB, within 15 minutes.

### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid | yes | The settlement's Wathiqaty id. |

### Body (JSON)

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fileName` | string | yes | Original file name. |
| `contentType` | string | yes | MIME type. One of: `application/pdf`, `image/png`, `image/jpeg`. |

### Request examples

```bash
curl -X POST "https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements/{id}/proof-upload-url" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"fileName":"transfer.pdf","contentType":"application/pdf"}'
```

```js
const res = await fetch("https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements/{id}/proof-upload-url", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${accessToken}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "fileName": "transfer.pdf",
    "contentType": "application/pdf"
  }),
})
const { data, error } = await res.json()
if (!res.ok) throw new Error(`${res.status} ${error.code}`)
```

```python
import requests

res = requests.post(
    "https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements/{id}/proof-upload-url",
    headers={
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json",
    },
    json={
      "fileName": "transfer.pdf",
      "contentType": "application/pdf"
    },
    timeout=30,
)
payload = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {payload['error']['code']}")
data = payload["data"]
```

```csharp
using var req = new HttpRequestMessage(HttpMethod.Post,
    "https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements/{id}/proof-upload-url");
req.Headers.TryAddWithoutValidation("Authorization", $"Bearer {accessToken}");
req.Content = new StringContent(
    """
    {
      "fileName": "transfer.pdf",
      "contentType": "application/pdf"
    }
    """,
    Encoding.UTF8, "application/json");
using var res = await http.SendAsync(req);
var json = await res.Content.ReadAsStringAsync();
res.EnsureSuccessStatusCode();
```

### Response 201

Where to upload.

```json
{
  "status": "success",
  "data": {
    "url": "https://uploads.wathiqaty.com/",
    "fields": {
      "key": "settlements/e4f5…/transfer.pdf",
      "Policy": "eyJ…",
      "X-Amz-Signature": "…"
    },
    "fileKey": "settlements/e4f5…/transfer.pdf",
    "expiresAt": "2026-12-02T09:15:00.000Z"
  },
  "error": null,
  "metadata": {
    "timestamp": "2026-11-05T09:15:02.481Z",
    "path": "/api/v1/partner/…",
    "method": "POST",
    "requestId": "8d7e2c1a-41f0-4a4e-9a55-6f0b3c2d1e77"
  }
}
```

### Errors

| Status | Code | When |
| --- | --- | --- |
| 404 | `not_found` | Settlement doesn't exist or isn't your company's. |

Plus the generic errors any route can return: [Errors](/guides/errors.md).

## Submit payment proof

`POST /partner/commission-settlements/{id}/proof`

- Auth: Bearer token, scope `finance:write`
- `Idempotency-Key`: optional

`requested` (or `rejected`) → `proof_submitted`. Wathiqaty confirms or rejects it (`settlement.confirmed` / `settlement.rejected`).

### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid | yes | The settlement's Wathiqaty id. |

### Body (JSON)

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `fileKey` | string | yes | `fileKey` from the upload URL, after uploading. |
| `transferReference` | string | yes | Bank transfer reference. |
| `transferredAt` | date-time | yes | When you paid. |

### Request examples

```bash
curl -X POST "https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements/{id}/proof" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"fileKey":"settlements/e4f5…/transfer.pdf","transferReference":"NBE-0098812","transferredAt":"2026-12-02T08:00:00Z"}'
```

```js
const res = await fetch("https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements/{id}/proof", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${accessToken}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    "fileKey": "settlements/e4f5…/transfer.pdf",
    "transferReference": "NBE-0098812",
    "transferredAt": "2026-12-02T08:00:00Z"
  }),
})
const { data, error } = await res.json()
if (!res.ok) throw new Error(`${res.status} ${error.code}`)
```

```python
import requests, uuid

res = requests.post(
    "https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements/{id}/proof",
    headers={
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
      "fileKey": "settlements/e4f5…/transfer.pdf",
      "transferReference": "NBE-0098812",
      "transferredAt": "2026-12-02T08:00:00Z"
    },
    timeout=30,
)
payload = res.json()
if not res.ok:
    raise RuntimeError(f"{res.status_code} {payload['error']['code']}")
data = payload["data"]
```

```csharp
using var req = new HttpRequestMessage(HttpMethod.Post,
    "https://sandbox-api.wathiqaty.com/api/v1/partner/commission-settlements/{id}/proof");
req.Headers.TryAddWithoutValidation("Authorization", $"Bearer {accessToken}");
req.Headers.TryAddWithoutValidation("Idempotency-Key", Guid.NewGuid().ToString());
req.Content = new StringContent(
    """
    {
      "fileKey": "settlements/e4f5…/transfer.pdf",
      "transferReference": "NBE-0098812",
      "transferredAt": "2026-12-02T08:00:00Z"
    }
    """,
    Encoding.UTF8, "application/json");
using var res = await http.SendAsync(req);
var json = await res.Content.ReadAsStringAsync();
res.EnsureSuccessStatusCode();
```

### Response 200

The settlement.

```json
{
  "status": "success",
  "data": {
    "id": "e4f5a6b7-c8d9-4e0f-9a1b-2c3d4e5f6a7b",
    "status": "proof_submitted",
    "periodFrom": "2026-11-01",
    "periodTo": "2026-11-30",
    "amount": "184500.00",
    "platformBankAccount": {
      "bank": "National Bank of Egypt",
      "iban": "EG380019000500000000263180002"
    },
    "proof": null,
    "requestedAt": "2026-12-01T07:00:00.000Z",
    "updatedAt": "2026-12-01T07:00:00.000Z"
  },
  "error": null,
  "metadata": {
    "timestamp": "2026-11-05T09:15:02.481Z",
    "path": "/api/v1/partner/…",
    "method": "POST",
    "requestId": "8d7e2c1a-41f0-4a4e-9a55-6f0b3c2d1e77"
  }
}
```

### Errors

| Status | Code | When |
| --- | --- | --- |
| 404 | `not_found` | Settlement doesn't exist or isn't your company's. |
| 400 | `bad_request` | Not allowed in the current status (`details.from`, `details.to`). |
| 422 | `file_not_uploaded` | Nothing was uploaded under `fileKey`. |

Plus the generic errors any route can return: [Errors](/guides/errors.md).
