# Billing

Fee schedules, invoices, invoice lines, payments, and statements.

Generated from `apps/api/openapi.json`. HTML version: https://docs.institflow.com/en/reference/billing

27 operations.

## GET /api/v1/billing/summary

Billing dashboard summary: outstanding, collected this month, overdue, by status.

- Operation id: `BillingSummaryController_get_v1`
- Permission: `invoices.read`
- Auth: credential required
- `Idempotency-Key`: not required

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `currency` | string | yes | 3–3 chars |
| `outstanding` | Money | yes |  |
| `collectedThisMonth` | Money | yes |  |
| `overdueCount` | integer | yes | 0–9007199254740991 |
| `overdueTotal` | Money | yes |  |
| `byStatus` | object | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/billing/summary" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## GET /api/v1/fee-schedules

List fee schedules (cursor-paginated).

- Operation id: `FeeSchedulesController_list_v1`
- Permission: `invoices.read`
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `cursor` | query | string | no |  |
| `limit` | query | integer | no | 1–100 · default: 25 |
| `kind` | query | enum: "per_group" \| "per_course" \| "one_off" \| "registration" | no |  |
| `isActive` | query | boolean | no |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | array<object> | yes |  |
| `nextCursor` | string \| null | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/fee-schedules" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## POST /api/v1/fee-schedules

Create a fee schedule.

- Operation id: `FeeSchedulesController_create_v1`
- Permission: `invoices.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `name` | string | yes | 1–150 chars |
| `kind` | enum: "per_group" \| "per_course" \| "one_off" \| "registration" | yes |  |
| `amountMinor` | integer | yes | 0–9007199254740991 |
| `currency` | enum: "ILS" \| "USD" \| "EUR" | yes |  |
| `recurrence` | enum: "once" \| "monthly" \| "per_term" | yes |  |
| `courseId` | string (uuid) | no |  |
| `groupId` | string (uuid) | no |  |
| `dueDay` | integer | no | 1–31 |
| `isActive` | boolean | no | default: true |

```json
{
  "name": "Algebra I",
  "kind": "per_group",
  "amountMinor": 12000,
  "currency": "ILS",
  "recurrence": "once",
  "courseId": "d0e4743a-d0e4-70e4-8e47-d0e4743ad0e4",
  "groupId": "6dc7fce6-6dc7-7dc7-8c7f-6dc7fce66dc7",
  "dueDay": 1,
  "isActive": true
}
```

### Responses

**201** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `name` | string | yes |  |
| `kind` | enum: "per_group" \| "per_course" \| "one_off" \| "registration" | yes |  |
| `amount` | Money | yes |  |
| `recurrence` | enum: "once" \| "monthly" \| "per_term" | yes |  |
| `courseId` | string (uuid) \| null | yes |  |
| `groupId` | string (uuid) \| null | yes |  |
| `dueDay` | integer \| null | yes | 1–31 |
| `isActive` | boolean | yes |  |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/fee-schedules" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "Algebra I",
    "kind": "per_group",
    "amountMinor": 12000,
    "currency": "ILS",
    "recurrence": "once",
    "courseId": "d0e4743a-d0e4-70e4-8e47-d0e4743ad0e4",
    "groupId": "6dc7fce6-6dc7-7dc7-8c7f-6dc7fce66dc7",
    "dueDay": 1,
    "isActive": true
  }'
```

## DELETE /api/v1/fee-schedules/{id}

Delete a fee schedule. Refused (409) if any invoice line still references it.

- Operation id: `FeeSchedulesController_remove_v1`
- Permission: `invoices.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — The fee schedule was deleted.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `ok` | enum: true | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X DELETE "https://your-institute.example/api/v1/fee-schedules/37386ae0-3738-7738-8386-37386ae03738" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## GET /api/v1/fee-schedules/{id}

Get a fee schedule by id.

- Operation id: `FeeSchedulesController_getById_v1`
- Permission: `invoices.read`
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `name` | string | yes |  |
| `kind` | enum: "per_group" \| "per_course" \| "one_off" \| "registration" | yes |  |
| `amount` | Money | yes |  |
| `recurrence` | enum: "once" \| "monthly" \| "per_term" | yes |  |
| `courseId` | string (uuid) \| null | yes |  |
| `groupId` | string (uuid) \| null | yes |  |
| `dueDay` | integer \| null | yes | 1–31 |
| `isActive` | boolean | yes |  |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/fee-schedules/37386ae0-3738-7738-8386-37386ae03738" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## PATCH /api/v1/fee-schedules/{id}

Update a fee schedule.

- Operation id: `FeeSchedulesController_update_v1`
- Permission: `invoices.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `name` | string | no | 1–150 chars |
| `kind` | enum: "per_group" \| "per_course" \| "one_off" \| "registration" | no |  |
| `amountMinor` | integer | no | 0–9007199254740991 |
| `currency` | enum: "ILS" \| "USD" \| "EUR" | no |  |
| `recurrence` | enum: "once" \| "monthly" \| "per_term" | no |  |
| `courseId` | string (uuid) | no |  |
| `groupId` | string (uuid) | no |  |
| `dueDay` | integer | no | 1–31 |
| `isActive` | boolean | no | default: true |

```json
{
  "name": "Algebra I",
  "kind": "per_group",
  "amountMinor": 12000,
  "currency": "ILS",
  "recurrence": "once",
  "courseId": "d0e4743a-d0e4-70e4-8e47-d0e4743ad0e4",
  "groupId": "6dc7fce6-6dc7-7dc7-8c7f-6dc7fce66dc7",
  "dueDay": 1,
  "isActive": true
}
```

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `name` | string | yes |  |
| `kind` | enum: "per_group" \| "per_course" \| "one_off" \| "registration" | yes |  |
| `amount` | Money | yes |  |
| `recurrence` | enum: "once" \| "monthly" \| "per_term" | yes |  |
| `courseId` | string (uuid) \| null | yes |  |
| `groupId` | string (uuid) \| null | yes |  |
| `dueDay` | integer \| null | yes | 1–31 |
| `isActive` | boolean | yes |  |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X PATCH "https://your-institute.example/api/v1/fee-schedules/37386ae0-3738-7738-8386-37386ae03738" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "Algebra I",
    "kind": "per_group",
    "amountMinor": 12000,
    "currency": "ILS",
    "recurrence": "once",
    "courseId": "d0e4743a-d0e4-70e4-8e47-d0e4743ad0e4",
    "groupId": "6dc7fce6-6dc7-7dc7-8c7f-6dc7fce66dc7",
    "dueDay": 1,
    "isActive": true
  }'
```

## POST /api/v1/fee-schedules/{id}/generate

Batch-generate this period's invoices for a "monthly" fee schedule — one per actively-enrolled student, skipping anyone already invoiced for the period. `dryRun: true` previews counts only.

- Operation id: `FeeSchedulesController_generate_v1`
- Permission: `invoices.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `period` | string | yes |  |
| `dryRun` | boolean | yes |  |

```json
{
  "period": "string",
  "dryRun": true
}
```

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `period` | string | yes |  |
| `periodStart` | string (date) | yes |  |
| `periodEnd` | string (date) | yes |  |
| `dueDate` | string (date) | yes |  |
| `dryRun` | boolean | yes |  |
| `eligibleStudentCount` | integer | yes | 0–9007199254740991 |
| `alreadyInvoicedCount` | integer | yes | 0–9007199254740991 |
| `createdInvoiceIds` | array<string (uuid)> | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/fee-schedules/37386ae0-3738-7738-8386-37386ae03738/generate" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "period": "string",
    "dryRun": true
  }'
```

## GET /api/v1/invoices

List invoices (filters: status, studentId, guardianId, overdue, due date range; cursor-paginated).

- Operation id: `InvoicesController_list_v1`
- Permission: `invoices.read`
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `cursor` | query | string | no |  |
| `limit` | query | integer | no | 1–100 · default: 25 |
| `status` | query | enum: "draft" \| "issued" \| "partially_paid" \| "paid" \| "overdue" \| "void" | no |  |
| `studentId` | query | string (uuid) | no |  |
| `guardianId` | query | string (uuid) | no |  |
| `overdue` | query | boolean | no |  |
| `dueDateFrom` | query | string (date) | no |  |
| `dueDateTo` | query | string (date) | no |  |
| `sortBy` | query | enum: "dueDate" \| "total" | no | default: "dueDate" |
| `sortDir` | query | enum: "asc" \| "desc" | no | default: "asc" |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | array<object> | yes |  |
| `nextCursor` | string \| null | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/invoices" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## POST /api/v1/invoices

Create a draft invoice. Totals are always recomputed server-side from `lines`.

- Operation id: `InvoicesController_create_v1`
- Permission: `invoices.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `branchId` | string (uuid) | yes |  |
| `studentId` | string (uuid) | yes |  |
| `payerGuardianId` | string (uuid) | no |  |
| `issueDate` | string (date) | yes |  |
| `dueDate` | string (date) | yes |  |
| `currency` | enum: "ILS" \| "USD" \| "EUR" | yes |  |
| `discountMinor` | integer | no | 0–9007199254740991 · default: 0 |
| `taxMinor` | integer | no | 0–9007199254740991 · default: 0 |
| `notes` | string \| string | no |  |
| `lines` | array<object> | yes |  |

```json
{
  "branchId": "390b8975-390b-790b-80b8-390b8975390b",
  "studentId": "a4a70332-a4a7-74a7-8a70-a4a70332a4a7",
  "payerGuardianId": "4e92fac4-4e92-7e92-892f-4e92fac44e92",
  "issueDate": "2026-03-02",
  "dueDate": "2026-03-02",
  "currency": "ILS",
  "discountMinor": 0,
  "taxMinor": 0,
  "notes": "Prefers afternoon sessions.",
  "lines": [
    {
      "description": "A short, human-readable description.",
      "quantity": 1,
      "unitMinor": 0,
      "enrollmentId": "c8bc7863-c8bc-78bc-8bc7-c8bc7863c8bc",
      "feeScheduleId": "3cfbbfe7-3cfb-7cfb-8fbb-3cfbbfe73cfb",
      "periodStart": "string",
      "periodEnd": "string"
    }
  ]
}
```

### Responses

**201** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `branchId` | string (uuid) | yes |  |
| `number` | string | yes | ≥1 chars |
| `studentId` | string (uuid) | yes |  |
| `payerGuardianId` | string (uuid) \| null | yes |  |
| `status` | enum: "draft" \| "issued" \| "partially_paid" \| "paid" \| "overdue" \| "void" | yes |  |
| `issueDate` | string (date) | yes |  |
| `dueDate` | string (date) | yes |  |
| `subtotal` | Money | yes |  |
| `discount` | Money | yes |  |
| `tax` | Money | yes |  |
| `total` | Money | yes |  |
| `paid` | Money | yes |  |
| `currency` | string | yes | 3–3 chars |
| `notes` | string \| null | yes | 1–2000 chars |
| `version` | integer | yes | -9007199254740991–9007199254740991 |
| `voidedAt` | string (date-time) \| null | yes |  |
| `voidReason` | string \| null | yes | 1–500 chars |
| `pendingPaymentProofCount` | integer | yes | 0–9007199254740991 |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |
| `lines` | array<object> | yes |  |
| `payments` | array<object> | yes |  |
| `paymentProofs` | array<object> | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/invoices" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "branchId": "390b8975-390b-790b-80b8-390b8975390b",
    "studentId": "a4a70332-a4a7-74a7-8a70-a4a70332a4a7",
    "payerGuardianId": "4e92fac4-4e92-7e92-892f-4e92fac44e92",
    "issueDate": "2026-03-02",
    "dueDate": "2026-03-02",
    "currency": "ILS",
    "discountMinor": 0,
    "taxMinor": 0,
    "notes": "Prefers afternoon sessions.",
    "lines": [
      {
        "description": "A short, human-readable description.",
        "quantity": 1,
        "unitMinor": 0,
        "enrollmentId": "c8bc7863-c8bc-78bc-8bc7-c8bc7863c8bc",
        "feeScheduleId": "3cfbbfe7-3cfb-7cfb-8fbb-3cfbbfe73cfb",
        "periodStart": "string",
        "periodEnd": "string"
      }
    ]
  }'
```

## GET /api/v1/invoices/{id}

Get an invoice, with its lines and payments.

- Operation id: `InvoicesController_getById_v1`
- Permission: `invoices.read`
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `branchId` | string (uuid) | yes |  |
| `number` | string | yes | ≥1 chars |
| `studentId` | string (uuid) | yes |  |
| `payerGuardianId` | string (uuid) \| null | yes |  |
| `status` | enum: "draft" \| "issued" \| "partially_paid" \| "paid" \| "overdue" \| "void" | yes |  |
| `issueDate` | string (date) | yes |  |
| `dueDate` | string (date) | yes |  |
| `subtotal` | Money | yes |  |
| `discount` | Money | yes |  |
| `tax` | Money | yes |  |
| `total` | Money | yes |  |
| `paid` | Money | yes |  |
| `currency` | string | yes | 3–3 chars |
| `notes` | string \| null | yes | 1–2000 chars |
| `version` | integer | yes | -9007199254740991–9007199254740991 |
| `voidedAt` | string (date-time) \| null | yes |  |
| `voidReason` | string \| null | yes | 1–500 chars |
| `pendingPaymentProofCount` | integer | yes | 0–9007199254740991 |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |
| `lines` | array<object> | yes |  |
| `payments` | array<object> | yes |  |
| `paymentProofs` | array<object> | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/invoices/37386ae0-3738-7738-8386-37386ae03738" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## PATCH /api/v1/invoices/{id}

Update a draft invoice (draft only). Replaces `lines` entirely. Requires the current `version`.

- Operation id: `InvoicesController_update_v1`
- Permission: `invoices.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `version` | integer | yes | 1–9007199254740991 |
| `branchId` | string (uuid) | no |  |
| `payerGuardianId` | string (uuid) | no |  |
| `issueDate` | string (date) | no |  |
| `dueDate` | string (date) | no |  |
| `currency` | enum: "ILS" \| "USD" \| "EUR" | no |  |
| `discountMinor` | integer | no | 0–9007199254740991 |
| `notes` | enum: "" \| string \| null | no |  |
| `lines` | array<object> | yes |  |

```json
{
  "version": 1,
  "branchId": "390b8975-390b-790b-80b8-390b8975390b",
  "payerGuardianId": "4e92fac4-4e92-7e92-892f-4e92fac44e92",
  "issueDate": "2026-03-02",
  "dueDate": "2026-03-02",
  "currency": "ILS",
  "discountMinor": 0,
  "notes": "",
  "lines": [
    {
      "description": "A short, human-readable description.",
      "quantity": 1,
      "unitMinor": 0,
      "enrollmentId": "c8bc7863-c8bc-78bc-8bc7-c8bc7863c8bc",
      "feeScheduleId": "3cfbbfe7-3cfb-7cfb-8fbb-3cfbbfe73cfb",
      "periodStart": "2026-03-02",
      "periodEnd": "2026-03-02"
    }
  ]
}
```

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `branchId` | string (uuid) | yes |  |
| `number` | string | yes | ≥1 chars |
| `studentId` | string (uuid) | yes |  |
| `payerGuardianId` | string (uuid) \| null | yes |  |
| `status` | enum: "draft" \| "issued" \| "partially_paid" \| "paid" \| "overdue" \| "void" | yes |  |
| `issueDate` | string (date) | yes |  |
| `dueDate` | string (date) | yes |  |
| `subtotal` | Money | yes |  |
| `discount` | Money | yes |  |
| `tax` | Money | yes |  |
| `total` | Money | yes |  |
| `paid` | Money | yes |  |
| `currency` | string | yes | 3–3 chars |
| `notes` | string \| null | yes | 1–2000 chars |
| `version` | integer | yes | -9007199254740991–9007199254740991 |
| `voidedAt` | string (date-time) \| null | yes |  |
| `voidReason` | string \| null | yes | 1–500 chars |
| `pendingPaymentProofCount` | integer | yes | 0–9007199254740991 |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |
| `lines` | array<object> | yes |  |
| `payments` | array<object> | yes |  |
| `paymentProofs` | array<object> | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X PATCH "https://your-institute.example/api/v1/invoices/37386ae0-3738-7738-8386-37386ae03738" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "version": 1,
    "branchId": "390b8975-390b-790b-80b8-390b8975390b",
    "payerGuardianId": "4e92fac4-4e92-7e92-892f-4e92fac44e92",
    "issueDate": "2026-03-02",
    "dueDate": "2026-03-02",
    "currency": "ILS",
    "discountMinor": 0,
    "notes": "",
    "lines": [
      {
        "description": "A short, human-readable description.",
        "quantity": 1,
        "unitMinor": 0,
        "enrollmentId": "c8bc7863-c8bc-78bc-8bc7-c8bc7863c8bc",
        "feeScheduleId": "3cfbbfe7-3cfb-7cfb-8fbb-3cfbbfe73cfb",
        "periodStart": "2026-03-02",
        "periodEnd": "2026-03-02"
      }
    ]
  }'
```

## POST /api/v1/invoices/{id}/issue

Issue a draft invoice: allocates its number, sets issue/due dates, and emits `invoice.issued`.

- Operation id: `InvoicesController_issue_v1`
- Permission: `invoices.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `branchId` | string (uuid) | yes |  |
| `number` | string | yes | ≥1 chars |
| `studentId` | string (uuid) | yes |  |
| `payerGuardianId` | string (uuid) \| null | yes |  |
| `status` | enum: "draft" \| "issued" \| "partially_paid" \| "paid" \| "overdue" \| "void" | yes |  |
| `issueDate` | string (date) | yes |  |
| `dueDate` | string (date) | yes |  |
| `subtotal` | Money | yes |  |
| `discount` | Money | yes |  |
| `tax` | Money | yes |  |
| `total` | Money | yes |  |
| `paid` | Money | yes |  |
| `currency` | string | yes | 3–3 chars |
| `notes` | string \| null | yes | 1–2000 chars |
| `version` | integer | yes | -9007199254740991–9007199254740991 |
| `voidedAt` | string (date-time) \| null | yes |  |
| `voidReason` | string \| null | yes | 1–500 chars |
| `pendingPaymentProofCount` | integer | yes | 0–9007199254740991 |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |
| `lines` | array<object> | yes |  |
| `payments` | array<object> | yes |  |
| `paymentProofs` | array<object> | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/invoices/37386ae0-3738-7738-8386-37386ae03738/issue" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## GET /api/v1/invoices/{id}/payment-proofs

List every payment proof attached to an invoice, with its review status.

- Operation id: `PaymentProofsController_list_v1`
- Permission: `payments.read`
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | array<object> | yes |  |
| `nextCursor` | string \| null | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/invoices/37386ae0-3738-7738-8386-37386ae03738/payment-proofs" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## POST /api/v1/invoices/{id}/payment-proofs/{proofId}/confirm

Confirm a payment proof: records the payment (proof's own amount/date) against the invoice and marks the proof confirmed. Emits `payment.recorded` and `billing.payment_proof.reviewed`.

- Operation id: `PaymentProofsController_confirm_v1`
- Permission: `payments.record`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |
| `proofId` | path | string | yes |  |

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `method` | enum: "cash" \| "bank_transfer" \| "card" \| "other" | no | default: "bank_transfer" |
| `providerRef` | string \| string | no |  |

```json
{
  "method": "bank_transfer",
  "providerRef": "string"
}
```

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `invoiceId` | string (uuid) | yes |  |
| `fileId` | string (uuid) | yes |  |
| `submittedByUserId` | string (uuid) | yes |  |
| `submittedByName` | string \| null | yes | ≥1 chars |
| `amount` | Money | yes |  |
| `paidOn` | string (date) | yes |  |
| `note` | string \| null | yes | 1–500 chars |
| `status` | enum: "submitted" \| "confirmed" \| "rejected" | yes |  |
| `reviewedByUserId` | string (uuid) \| null | yes |  |
| `reviewedByName` | string \| null | yes | ≥1 chars |
| `reviewedAt` | string (date-time) \| null | yes |  |
| `reviewNote` | string \| null | yes | 1–500 chars |
| `paymentId` | string (uuid) \| null | yes |  |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/invoices/37386ae0-3738-7738-8386-37386ae03738/payment-proofs/1a6553ac-1a65-7a65-8655-1a6553ac1a65/confirm" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "method": "bank_transfer",
    "providerRef": "string"
  }'
```

## POST /api/v1/invoices/{id}/payment-proofs/{proofId}/reject

Reject a payment proof with a review note. Emits `billing.payment_proof.reviewed`.

- Operation id: `PaymentProofsController_reject_v1`
- Permission: `payments.record`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |
| `proofId` | path | string | yes |  |

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `reviewNote` | string | yes | 1–500 chars |

```json
{
  "reviewNote": "string"
}
```

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `invoiceId` | string (uuid) | yes |  |
| `fileId` | string (uuid) | yes |  |
| `submittedByUserId` | string (uuid) | yes |  |
| `submittedByName` | string \| null | yes | ≥1 chars |
| `amount` | Money | yes |  |
| `paidOn` | string (date) | yes |  |
| `note` | string \| null | yes | 1–500 chars |
| `status` | enum: "submitted" \| "confirmed" \| "rejected" | yes |  |
| `reviewedByUserId` | string (uuid) \| null | yes |  |
| `reviewedByName` | string \| null | yes | ≥1 chars |
| `reviewedAt` | string (date-time) \| null | yes |  |
| `reviewNote` | string \| null | yes | 1–500 chars |
| `paymentId` | string (uuid) \| null | yes |  |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/invoices/37386ae0-3738-7738-8386-37386ae03738/payment-proofs/1a6553ac-1a65-7a65-8655-1a6553ac1a65/reject" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "reviewNote": "string"
  }'
```

## GET /api/v1/invoices/{id}/payments

List every payment recorded against an invoice.

- Operation id: `InvoicesController_listPayments_v1`
- Permission: `payments.read`
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | array<object> | yes |  |
| `nextCursor` | string \| null | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/invoices/37386ae0-3738-7738-8386-37386ae03738/payments" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## POST /api/v1/invoices/{id}/payments

Record a payment against an invoice. Emits `payment.recorded`.

- Operation id: `InvoicesController_recordPayment_v1`
- Permission: `payments.record`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `amountMinor` | integer | yes | 1–9007199254740991 |
| `currency` | enum: "ILS" \| "USD" \| "EUR" | yes |  |
| `method` | enum: "cash" \| "bank_transfer" \| "card" \| "other" | yes |  |
| `provider` | enum: "manual" \| "stripe" \| "tranzila" \| "other" | no | default: "manual" |
| `providerRef` | string \| string | no |  |
| `receivedAt` | string \| string (date-time) | no |  |
| `note` | string \| string | no |  |

```json
{
  "amountMinor": 12000,
  "currency": "ILS",
  "method": "cash",
  "provider": "manual",
  "providerRef": "string",
  "receivedAt": "string",
  "note": "string"
}
```

### Responses

**201** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `invoiceId` | string (uuid) | yes |  |
| `amount` | Money | yes |  |
| `method` | enum: "cash" \| "bank_transfer" \| "card" \| "other" | yes |  |
| `provider` | enum: "manual" \| "stripe" \| "tranzila" \| "other" | yes |  |
| `providerRef` | string \| null | yes | ≥1 chars |
| `receivedAt` | string (date-time) | yes |  |
| `receivedByUserId` | string (uuid) | yes |  |
| `note` | string \| null | yes | 1–1000 chars |
| `reversedAt` | string (date-time) \| null | yes |  |
| `reversalReason` | string \| null | yes | 1–500 chars |
| `createdAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/invoices/37386ae0-3738-7738-8386-37386ae03738/payments" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "amountMinor": 12000,
    "currency": "ILS",
    "method": "cash",
    "provider": "manual",
    "providerRef": "string",
    "receivedAt": "string",
    "note": "string"
  }'
```

## POST /api/v1/invoices/{id}/remind

Send a payment reminder (the `invoice.overdue` template) to the invoice's payer/guardians. Idempotent per invoice per UTC day — a second call the same day reports `alreadyRemindedToday` instead of re-sending.

- Operation id: `InvoicesController_remind_v1`
- Permission: `invoices.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `invoiceId` | string (uuid) | yes |  |
| `alreadyRemindedToday` | boolean | yes |  |
| `sentAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/invoices/37386ae0-3738-7738-8386-37386ae03738/remind" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## POST /api/v1/invoices/{id}/void

Void an invoice. Refused (409) if it has any active (non-reversed) payments.

- Operation id: `InvoicesController_void_v1`
- Permission: `invoices.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `reason` | string | yes | 1–500 chars |

```json
{
  "reason": "Requested by guardian."
}
```

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `branchId` | string (uuid) | yes |  |
| `number` | string | yes | ≥1 chars |
| `studentId` | string (uuid) | yes |  |
| `payerGuardianId` | string (uuid) \| null | yes |  |
| `status` | enum: "draft" \| "issued" \| "partially_paid" \| "paid" \| "overdue" \| "void" | yes |  |
| `issueDate` | string (date) | yes |  |
| `dueDate` | string (date) | yes |  |
| `subtotal` | Money | yes |  |
| `discount` | Money | yes |  |
| `tax` | Money | yes |  |
| `total` | Money | yes |  |
| `paid` | Money | yes |  |
| `currency` | string | yes | 3–3 chars |
| `notes` | string \| null | yes | 1–2000 chars |
| `version` | integer | yes | -9007199254740991–9007199254740991 |
| `voidedAt` | string (date-time) \| null | yes |  |
| `voidReason` | string \| null | yes | 1–500 chars |
| `pendingPaymentProofCount` | integer | yes | 0–9007199254740991 |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |
| `lines` | array<object> | yes |  |
| `payments` | array<object> | yes |  |
| `paymentProofs` | array<object> | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/invoices/37386ae0-3738-7738-8386-37386ae03738/void" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "reason": "Requested by guardian."
  }'
```

## POST /api/v1/invoices/remind-overdue

Bulk-send a payment reminder to every `overdue` invoice not already reminded today (idempotent per invoice per UTC day).

- Operation id: `InvoicesController_remindOverdue_v1`
- Permission: `invoices.write`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `totalOverdue` | integer | yes | 0–9007199254740991 |
| `reminded` | integer | yes | 0–9007199254740991 |
| `alreadyRemindedToday` | integer | yes | 0–9007199254740991 |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/invoices/remind-overdue" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## GET /api/v1/me/invoices

My own invoices (student: own; guardian: invoices they pay, or their children’s). Cursor-paginated; filterable by `studentId` and `status`.

- Operation id: `PortalController_listMyInvoices_v1`
- Permission: —
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `cursor` | query | string | no |  |
| `limit` | query | integer | no | 1–100 · default: 25 |
| `studentId` | query | string (uuid) | no |  |
| `status` | query | enum: "draft" \| "issued" \| "partially_paid" \| "paid" \| "overdue" \| "void" | no |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | array<object> | yes |  |
| `nextCursor` | string \| null | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/me/invoices" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## GET /api/v1/me/invoices/{id}

One of my own invoices, with its lines, payments and payment proofs.

- Operation id: `PortalController_getMyInvoice_v1`
- Permission: —
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `branchId` | string (uuid) | yes |  |
| `number` | string | yes | ≥1 chars |
| `studentId` | string (uuid) | yes |  |
| `payerGuardianId` | string (uuid) \| null | yes |  |
| `status` | enum: "draft" \| "issued" \| "partially_paid" \| "paid" \| "overdue" \| "void" | yes |  |
| `issueDate` | string (date) | yes |  |
| `dueDate` | string (date) | yes |  |
| `subtotal` | Money | yes |  |
| `discount` | Money | yes |  |
| `tax` | Money | yes |  |
| `total` | Money | yes |  |
| `paid` | Money | yes |  |
| `currency` | string | yes | 3–3 chars |
| `notes` | string \| null | yes | 1–2000 chars |
| `version` | integer | yes | -9007199254740991–9007199254740991 |
| `voidedAt` | string (date-time) \| null | yes |  |
| `voidReason` | string \| null | yes | 1–500 chars |
| `pendingPaymentProofCount` | integer | yes | 0–9007199254740991 |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |
| `lines` | array<object> | yes |  |
| `payments` | array<object> | yes |  |
| `paymentProofs` | array<object> | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/me/invoices/37386ae0-3738-7738-8386-37386ae03738" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## GET /api/v1/me/invoices/{id}/payment-proofs

My own payment proofs attached to one of my own invoices, with their review status.

- Operation id: `PortalController_listMyPaymentProofs_v1`
- Permission: —
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | array<object> | yes |  |
| `nextCursor` | string \| null | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/me/invoices/37386ae0-3738-7738-8386-37386ae03738/payment-proofs" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## POST /api/v1/me/invoices/{id}/payment-proofs

Attach a payment proof (photo + amount + date + note) to one of my own invoices, for a secretary to confirm.

- Operation id: `PortalController_submitMyPaymentProof_v1`
- Permission: —
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `fileId` | string (uuid) | yes |  |
| `amountMinor` | integer | yes | 1–9007199254740991 |
| `currency` | enum: "ILS" \| "USD" \| "EUR" | yes |  |
| `paidOn` | string (date) | yes |  |
| `note` | string \| string | no |  |

```json
{
  "fileId": "0daca32e-0dac-7dac-8aca-0daca32e0dac",
  "amountMinor": 12000,
  "currency": "ILS",
  "paidOn": "2026-03-02",
  "note": "string"
}
```

### Responses

**201** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `invoiceId` | string (uuid) | yes |  |
| `fileId` | string (uuid) | yes |  |
| `submittedByUserId` | string (uuid) | yes |  |
| `submittedByName` | string \| null | yes | ≥1 chars |
| `amount` | Money | yes |  |
| `paidOn` | string (date) | yes |  |
| `note` | string \| null | yes | 1–500 chars |
| `status` | enum: "submitted" \| "confirmed" \| "rejected" | yes |  |
| `reviewedByUserId` | string (uuid) \| null | yes |  |
| `reviewedByName` | string \| null | yes | ≥1 chars |
| `reviewedAt` | string (date-time) \| null | yes |  |
| `reviewNote` | string \| null | yes | 1–500 chars |
| `paymentId` | string (uuid) \| null | yes |  |
| `createdAt` | string (date-time) | yes |  |
| `updatedAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/me/invoices/37386ae0-3738-7738-8386-37386ae03738/payment-proofs" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "fileId": "0daca32e-0dac-7dac-8aca-0daca32e0dac",
    "amountMinor": 12000,
    "currency": "ILS",
    "paidOn": "2026-03-02",
    "note": "string"
  }'
```

## GET /api/v1/me/statement

My own (or one linked child’s) statement: invoices and payments, chronological, with a running balance.

- Operation id: `PortalController_getMyStatement_v1`
- Permission: —
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `studentId` | query | string (uuid) | no |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `studentId` | string (uuid) | yes |  |
| `currency` | string | yes | 3–3 chars |
| `entries` | array<object> | yes |  |
| `balance` | Money | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/me/statement" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## POST /api/v1/payments/{id}/reverse

Reverse a recorded payment, recomputing its invoice’s paid amount/status.

- Operation id: `PaymentsController_reverse_v1`
- Permission: `payments.record`
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `reason` | string | yes | 1–500 chars |

```json
{
  "reason": "Requested by guardian."
}
```

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `invoiceId` | string (uuid) | yes |  |
| `amount` | Money | yes |  |
| `method` | enum: "cash" \| "bank_transfer" \| "card" \| "other" | yes |  |
| `provider` | enum: "manual" \| "stripe" \| "tranzila" \| "other" | yes |  |
| `providerRef` | string \| null | yes | ≥1 chars |
| `receivedAt` | string (date-time) | yes |  |
| `receivedByUserId` | string (uuid) | yes |  |
| `note` | string \| null | yes | 1–1000 chars |
| `reversedAt` | string (date-time) \| null | yes |  |
| `reversalReason` | string \| null | yes | 1–500 chars |
| `createdAt` | string (date-time) | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/payments/37386ae0-3738-7738-8386-37386ae03738/reverse" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "reason": "Requested by guardian."
  }'
```

## GET /api/v1/students/{id}/statement

A student’s invoices + payments, chronological, with a running balance.

- Operation id: `StatementsController_getStatement_v1`
- Permission: `invoices.read`
- Auth: credential required
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Responses

**200** — Success.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `studentId` | string (uuid) | yes |  |
| `currency` | string | yes | 3–3 chars |
| `entries` | array<object> | yes |  |
| `balance` | Money | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/students/37386ae0-3738-7738-8386-37386ae03738/statement" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```
