> ## Documentation Index
> Fetch the complete documentation index at: https://docs.finosu.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Get Loan Payment Plan

> Returns the loan's active payment plan: its terms, the cadence rule it was created under, reconciliation totals, every scheduled payment, and the payments made against them.

Responds `200` with `paymentPlan: null` when the loan has no active plan — a normal state (never enrolled, or the plan completed or was cancelled), and deliberately distinct from `404`, which means the loan itself was not found.

Supports `If-None-Match`: an unchanged plan responds `304`, so polling a whole portfolio stays cheap.

## Overview

Returns the loan's **active** payment plan — its terms, the cadence rule it was created under, reconciliation totals, every scheduled payment, and the payments made against them.

Use it to board the payment plan into your own servicing system and to reconcile the payments you have collected against it. When a plan is agreed with a borrower through the borrower portal, an agent, or an automated call, it exists only on the Finosu side until you pull it.

The plan identified is always the current one. Superseded plans are not returned.

## Which scheduled payments to board

`scheduledPayments[].status` is the single field that answers this. Board a scheduled payment **only** when its status is one of:

| status           | meaning                                                               |
| ---------------- | --------------------------------------------------------------------- |
| `PENDING`        | Live, not yet due.                                                    |
| `PARTIALLY_PAID` | Live, partly covered by payments or credit.                           |
| `OVERDUE`        | Live, past its due date and still owed **on this scheduled payment**. |

Every other status means the scheduled payment is **not** a live obligation and must not be boarded:

| status      | meaning                                                                                  | what it tells you about the borrower                 |
| ----------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| `PAID`      | Fully covered.                                                                           | —                                                    |
| `MISSED`    | The charge failed and the amount was rescheduled onto a **different** scheduled payment. | Adverse — a payment was attempted and bounced.       |
| `SKIPPED`   | The borrower asked to skip this scheduled payment and it was forgiven.                   | Borrower-initiated relief, not a failed payment.     |
| `POSTPONED` | Finosu moved the scheduled payment (a schedule rebuild or an operator action).           | Nothing — this is an operational change on our side. |
| `CANCELLED` | The scheduled payment was cancelled and is void.                                         | —                                                    |

<Note>
  `OVERDUE` and `MISSED` both describe non-payment, and the difference matters.
  With `OVERDUE` the money is still owed on that scheduled payment, so keep
  collecting against it. With `MISSED` the amount has already been carried onto a
  later scheduled payment, so collecting against the `MISSED` one would count the
  same money twice.
</Note>

## Reading the money

### `remainingAmount` is a sum over scheduled payments

`totals.remainingAmount` is the sum of `amountRemaining` across scheduled payments whose status is `PENDING`, `PARTIALLY_PAID` or `OVERDUE`.

<Note>
  `remainingAmount` is the balance, already computed from the scheduled payments.

  `creditsApplied` is money that `paidToDate` has already counted. It comes from
  overpayments, where the excess on one scheduled payment is applied to another, so
  subtracting it from `discountedTotal` alongside `paidToDate` would deduct the same
  money twice.

  `remainingAmount` is summed from the scheduled payments, so it stays correct
  however credit arises.
</Note>

### `amountRemaining` is only meaningful on live scheduled payments

Every scheduled payment reports `max(0, scheduledAmount - amountPaid - creditsApplied)`, including ones that are no longer obligations. A `MISSED` or `POSTPONED` scheduled payment therefore shows a non-zero `amountRemaining` even though that amount has moved elsewhere.

Sum `amountRemaining` only across scheduled payments whose status is `PENDING`, `PARTIALLY_PAID` or `OVERDUE`, or use `totals.remainingAmount`, which does this for you.

### `offPlatformPaymentsTotal` is a portion of `paidToDate`

It reports how much of what `paidToDate` already counts was collected outside Finosu (payments with `source: "EXTERNAL"`).

<Note>
  This is a portion of `paidToDate`, not a separate amount to add to it. The
  off-platform payments it reports are already counted there, so adding the two
  together would count each of them twice.
</Note>

### Totals you can verify against the scheduled payments

These identities always hold, so you can check our totals against the detail we give you:

```
paidToDate == sum of scheduledPayments[].amountPaid
paidToDate == sum of payments[] where status == "SUCCESSFUL"
```

### Credits

`creditsApplied` is credit applied to a scheduled payment from the loan's credit balance.

That balance comes from overpayments. When a payment covers more than the scheduled payment it was applied to, the excess is held as credit and later applied to another scheduled payment.

Credit is reported separately from `amountPaid` because the money was already counted once, as a payment against the scheduled payment the overpayment landed on. Counting it again would double it.

## Dates and timing

* **`scheduledPayments[].dueDate` is authoritative** for when a scheduled payment is actually due. It carries a UTC offset and reflects any rescheduling.
* **`cadence` describes the rule the plan was created under**, not the current scheduled payments. Its anchor days derive from the plan's original start date, which does not change when a schedule is rebuilt — so after a reschedule `cadence` can disagree with the actual due dates. Use it to understand the intended pattern; use `dueDate` for real dates.
* **`transactedAt` and `finalizedAt` are Finosu-side timestamps, not bank confirmations.** `transactedAt` is when the payment was submitted or took effect; `finalizedAt` is when Finosu considers it settled. For ACH, neither is a guarantee of when funds moved at your bank. Apply your own settlement rules.

## Identifiers

* **`planId`** identifies the plan and is stable for the life of the plan.
* **`scheduledPaymentId`** and **`paymentId`** are stable Finosu identifiers. Store them if you want to correlate across polls.
* **`reference`** on a payment echoes the external reference you supplied when recording it, so you can join back to your own ledger.

## When there is no plan

A `200` response with `paymentPlan: null` means the loan exists but has no active plan. This is normal — the borrower may never have enrolled, or the plan may have completed or been cancelled.

<Warning>
  Do not treat `paymentPlan: null` as evidence that a plan was broken. A
  completed plan and a cancelled plan both read as `null` here. If your system
  holds an active plan for this loan, stop expecting drafts and flag it for
  review rather than assuming default.
</Warning>

A `404` is different: it means no loan with that reference exists **for your company**. Treat it as an integration error, not a business state.

## Polling efficiently

The response carries an `ETag`. Send it back as `If-None-Match` and an unchanged plan responds `304 Not Modified` with no body, which keeps a nightly sweep across a portfolio cheap.

```bash theme={null}
curl -sD- https://api.finosu.com/loans/L-88213/payment-plan \
  -H "X-API-Key: $FINOSU_API_KEY"

curl -s -o /dev/null -w '%{http_code}\n' \
  https://api.finosu.com/loans/L-88213/payment-plan \
  -H "X-API-Key: $FINOSU_API_KEY" \
  -H 'If-None-Match: W/"<etag from the first call>"'
```

## Example

A biweekly plan viewed in late June, showing five of the eight possible statuses: `PAID` (by two payments, the second of which overpaid it), `MISSED`, `OVERDUE`, `PARTIALLY_PAID` (from the resulting credit), and `PENDING`. `SKIPPED`, `POSTPONED` and `CANCELLED` are not shown here — see the status tables above for all eight.

<Note>
  `scheduledAmount` values may not sum to `discountedTotal`. `scheduledPayments`
  includes scheduled payments that are no longer obligations, whose amounts were
  moved onto others or forgiven, so they can total more than the plan itself. In
  this example the five come to `1033.35` against a `discountedTotal` of `826.68`.
  The difference is the `MISSED` scheduled payment, whose amount now sits on a
  later one.

  `discountedTotal` is the authorized total, and `remainingAmount` the
  outstanding balance.
</Note>

```json theme={null}
{
  "loanId": "L-88213",
  "customerId": "C-4410",
  "paymentPlan": {
    "planId": "L-88213-plan-2",
    "type": "CUSTOM",
    "standing": "PAST_DUE",
    "startDate": "2026-05-15",
    "autopayEnabled": true,
    "createdAt": "2026-05-08T18:22:04.001Z",
    "cadence": {
      "frequency": "BIWEEKLY",
      "dayOfWeek": 5,
      "dayOfMonth": null,
      "semimonthlyDays": null
    },
    "totals": {
      "originalTotal": 1200.0,
      "discountedTotal": 826.68,
      "paidToDate": 300.0,
      "creditsApplied": 93.33,
      "remainingAmount": 526.68,
      "pendingAmount": 0.0,
      "offPlatformPaymentsTotal": 100.0
    },
    "scheduledPayments": [
      {
        "scheduledPaymentId": "1a0b7c22-9d3e-4f10-b5a6-2c8e9f41d700",
        "dueDate": "2026-05-15T07:00:00-05:00",
        "scheduledAmount": 206.67,
        "amountPaid": 300.0,
        "creditsApplied": 0.0,
        "amountRemaining": 0.0,
        "status": "PAID"
      },
      {
        "scheduledPaymentId": "2b1c8d33-ae4f-4021-c6b7-3d9f0a52e811",
        "dueDate": "2026-05-29T07:00:00-05:00",
        "scheduledAmount": 206.67,
        "amountPaid": 0.0,
        "creditsApplied": 0.0,
        "amountRemaining": 206.67,
        "status": "MISSED"
      },
      {
        "scheduledPaymentId": "3c2d9e44-bf50-4132-d7c8-4e0a1b63f922",
        "dueDate": "2026-06-12T07:00:00-05:00",
        "scheduledAmount": 206.67,
        "amountPaid": 0.0,
        "creditsApplied": 0.0,
        "amountRemaining": 206.67,
        "status": "OVERDUE"
      },
      {
        "scheduledPaymentId": "d42b0a81-2c55-4f3b-9e1f-88d0c2b3a614",
        "dueDate": "2026-06-26T07:00:00-05:00",
        "scheduledAmount": 206.67,
        "amountPaid": 0.0,
        "creditsApplied": 93.33,
        "amountRemaining": 113.34,
        "status": "PARTIALLY_PAID"
      },
      {
        "scheduledPaymentId": "e53c1b92-3d66-4a4c-8f20-99e1d3c4b725",
        "dueDate": "2026-07-10T07:00:00-05:00",
        "scheduledAmount": 206.67,
        "amountPaid": 0.0,
        "creditsApplied": 0.0,
        "amountRemaining": 206.67,
        "status": "PENDING"
      }
    ],
    "payments": [
      {
        "paymentId": "5c7e1a90-3b62-4c88-9a11-6d4f2e8b0c31",
        "scheduledPaymentId": "1a0b7c22-9d3e-4f10-b5a6-2c8e9f41d700",
        "amount": 100.0,
        "currency": "USD",
        "status": "SUCCESSFUL",
        "paymentType": "PARTIAL",
        "source": "EXTERNAL",
        "transactedAt": "2026-05-15T09:07:44-05:00",
        "finalizedAt": "2026-05-18T02:11:00Z",
        "reversedAt": null,
        "reference": "LMS-PMT-99101"
      },
      {
        "paymentId": "a71f3d05-8c92-4b1e-9d43-2e6b8f0a5c17",
        "scheduledPaymentId": "1a0b7c22-9d3e-4f10-b5a6-2c8e9f41d700",
        "amount": 200.0,
        "currency": "USD",
        "status": "SUCCESSFUL",
        "paymentType": "OVERPAYMENT",
        "source": "SYSTEM",
        "transactedAt": "2026-05-20T14:22:10-05:00",
        "finalizedAt": "2026-05-21T02:07:00Z",
        "reversedAt": null,
        "reference": null
      },
      {
        "paymentId": "6d8f2b01-4c73-4d99-8b22-7e5a3f9c1d42",
        "scheduledPaymentId": "2b1c8d33-ae4f-4021-c6b7-3d9f0a52e811",
        "amount": 206.67,
        "currency": "USD",
        "status": "FAILED",
        "paymentType": "AUTOPAY",
        "source": "SYSTEM",
        "transactedAt": "2026-05-29T09:03:12-05:00",
        "finalizedAt": null,
        "reversedAt": null,
        "reference": null
      }
    ]
  }
}
```

Reading the example:

**The first scheduled payment** shows `amountPaid: 300.00` against a `scheduledAmount` of `206.67`. It reports only the outcome (`PAID`) — that it took **two** payments, and that the borrower was five days late completing it, is visible only in `payments[]`. Note the first of those payments has `source: "EXTERNAL"`, which is why `offPlatformPaymentsTotal` is `100.00`: money the lender collected and uploaded, already counted inside `paidToDate`.

**The `93.33` excess** (`300.00 - 206.67`) appears as `creditsApplied` on the fourth scheduled payment, which is why it is `PARTIALLY_PAID` with `amountRemaining: 113.34` despite `amountPaid: 0.00`.

**The second scheduled payment is `MISSED`.** Its `FAILED` payment is in `payments[]`, and its amount was carried onto a later scheduled payment. Do not board it, or you would collect the same money twice.

**Checking the balance:** `remainingAmount` (`526.68`) is the sum of `amountRemaining` across the three boardable scheduled payments (`206.67 + 113.34 + 206.67`), and equals `discountedTotal - paidToDate` (`826.68 - 300.00`). It is **not** `discountedTotal - paidToDate - creditsApplied` (`433.35`). That would deduct the `93.33` twice: once as the payment that created it, and again as the credit it became.

## Error Responses

| Status Code | Description                                         |
| ----------- | --------------------------------------------------- |
| 401         | Missing or invalid `X-API-Key`                      |
| 404         | No loan with that reference exists for your company |
| 500         | Unexpected server error                             |


## OpenAPI

````yaml GET /loans/{id}/payment-plan
openapi: 3.1.0
info:
  title: Finosu API
  description: Finosu API
  license:
    name: MIT
  version: 1.0.0
servers: []
security:
  - apiKeyAuth: []
paths:
  /loans/{id}/payment-plan:
    get:
      description: >-
        Returns the loan's active payment plan: its terms, the cadence rule it
        was created under, reconciliation totals, every scheduled payment, and
        the payments made against them.


        Responds `200` with `paymentPlan: null` when the loan has no active plan
        — a normal state (never enrolled, or the plan completed or was
        cancelled), and deliberately distinct from `404`, which means the loan
        itself was not found.


        Supports `If-None-Match`: an unchanged plan responds `304`, so polling a
        whole portfolio stays cheap.
      parameters:
        - name: id
          in: path
          description: External reference ID of the loan
          required: true
          schema:
            type: string
        - name: includeRetired
          in: query
          description: >-
            Include scheduled payments that are no longer live obligations
            (MISSED, SKIPPED, POSTPONED, CANCELLED). Defaults to true so the
            schedule's history stays explicable.
          required: false
          schema:
            type: boolean
            default: true
      responses:
        '200':
          description: The loan's active payment plan, or null if it has none
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentPlanEnvelope'
              example:
                loanId: L-88213
                customerId: C-4410
                paymentPlan:
                  planId: L-88213-plan-2
                  type: CUSTOM
                  standing: PAST_DUE
                  startDate: '2026-05-15'
                  autopayEnabled: true
                  createdAt: '2026-05-08T18:22:04.001Z'
                  cadence:
                    frequency: BIWEEKLY
                    dayOfWeek: 5
                    dayOfMonth: null
                    semimonthlyDays: null
                  totals:
                    originalTotal: 1200
                    discountedTotal: 826.68
                    paidToDate: 300
                    creditsApplied: 93.33
                    remainingAmount: 526.68
                    pendingAmount: 0
                    offPlatformPaymentsTotal: 100
                  scheduledPayments:
                    - scheduledPaymentId: 1a0b7c22-9d3e-4f10-b5a6-2c8e9f41d700
                      dueDate: '2026-05-15T07:00:00-05:00'
                      scheduledAmount: 206.67
                      amountPaid: 300
                      creditsApplied: 0
                      amountRemaining: 0
                      status: PAID
                    - scheduledPaymentId: 2b1c8d33-ae4f-4021-c6b7-3d9f0a52e811
                      dueDate: '2026-05-29T07:00:00-05:00'
                      scheduledAmount: 206.67
                      amountPaid: 0
                      creditsApplied: 0
                      amountRemaining: 206.67
                      status: MISSED
                    - scheduledPaymentId: 3c2d9e44-bf50-4132-d7c8-4e0a1b63f922
                      dueDate: '2026-06-12T07:00:00-05:00'
                      scheduledAmount: 206.67
                      amountPaid: 0
                      creditsApplied: 0
                      amountRemaining: 206.67
                      status: OVERDUE
                    - scheduledPaymentId: d42b0a81-2c55-4f3b-9e1f-88d0c2b3a614
                      dueDate: '2026-06-26T07:00:00-05:00'
                      scheduledAmount: 206.67
                      amountPaid: 0
                      creditsApplied: 93.33
                      amountRemaining: 113.34
                      status: PARTIALLY_PAID
                    - scheduledPaymentId: e53c1b92-3d66-4a4c-8f20-99e1d3c4b725
                      dueDate: '2026-07-10T07:00:00-05:00'
                      scheduledAmount: 206.67
                      amountPaid: 0
                      creditsApplied: 0
                      amountRemaining: 206.67
                      status: PENDING
                  payments:
                    - paymentId: 5c7e1a90-3b62-4c88-9a11-6d4f2e8b0c31
                      scheduledPaymentId: 1a0b7c22-9d3e-4f10-b5a6-2c8e9f41d700
                      amount: 100
                      currency: USD
                      status: SUCCESSFUL
                      paymentType: PARTIAL
                      source: EXTERNAL
                      transactedAt: '2026-05-15T09:07:44-05:00'
                      finalizedAt: '2026-05-18T02:11:00Z'
                      reversedAt: null
                      reference: LMS-PMT-99101
                    - paymentId: a71f3d05-8c92-4b1e-9d43-2e6b8f0a5c17
                      scheduledPaymentId: 1a0b7c22-9d3e-4f10-b5a6-2c8e9f41d700
                      amount: 200
                      currency: USD
                      status: SUCCESSFUL
                      paymentType: OVERPAYMENT
                      source: SYSTEM
                      transactedAt: '2026-05-20T14:22:10-05:00'
                      finalizedAt: '2026-05-21T02:07:00Z'
                      reversedAt: null
                      reference: null
                    - paymentId: 6d8f2b01-4c73-4d99-8b22-7e5a3f9c1d42
                      scheduledPaymentId: 2b1c8d33-ae4f-4021-c6b7-3d9f0a52e811
                      amount: 206.67
                      currency: USD
                      status: FAILED
                      paymentType: AUTOPAY
                      source: SYSTEM
                      transactedAt: '2026-05-29T09:03:12-05:00'
                      finalizedAt: null
                      reversedAt: null
                      reference: null
        '304':
          description: Not modified — the plan is unchanged since the supplied ETag
        '404':
          description: No loan with that reference exists for your company
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    PaymentPlanEnvelope:
      description: Response for `GET /loans/{id}/payment-plan`.
      properties:
        loanId:
          description: The loan's external reference, echoing the request path.
          type: string
        customerId:
          description: The customer's reference id.
          type: string
        paymentPlan:
          anyOf:
            - $ref: '#/components/schemas/PaymentPlan'
            - type: 'null'
          description: >-
            The active payment plan, or `null` if the loan has none. A `null`
            plan is a normal state (never enrolled, or the plan completed or was
            cancelled) and is distinct from a 404, which means the loan itself
            was not found.
      required:
        - loanId
        - customerId
      type: object
    Error:
      required:
        - error
        - message
      type: object
      properties:
        error:
          type: integer
          format: int32
        message:
          type: string
    PaymentPlan:
      description: The loan's currently active payment plan.
      properties:
        planId:
          description: Identifies the plan. Stable for the life of the plan.
          type: string
        type:
          description: >-
            CUSTOM, FIXED, ONE_TIME or SETTLEMENT. Detect a discount by
            comparing originalTotal with discountedTotal rather than relying on
            this value.
          type: string
        standing:
          description: >-
            CURRENT if the borrower is on track, PAST_DUE if any live
            installment is overdue, COMPLETED if all are paid, UNKNOWN if the
            plan has no live installments.
          type: string
        startDate:
          description: >-
            The plan's authored start date. Combined with `cadence.frequency` it
            reproduces the intended series.
          format: date
          type:
            - string
            - 'null'
        autopayEnabled:
          description: >-
            Whether Finosu will automatically draft the scheduled payments.
            Check this before collecting independently, to avoid
            double-drafting.
          type: boolean
        createdAt:
          description: When the plan was created, i.e. when the borrower authorized it.
          format: date-time
          type: string
        cadence:
          $ref: '#/components/schemas/Cadence'
        totals:
          $ref: '#/components/schemas/PlanTotals'
        scheduledPayments:
          description: The plan's installments, ordered by due date.
          items:
            $ref: '#/components/schemas/ScheduledPayment'
          type: array
        payments:
          description: >-
            Payments against this plan, ordered by transaction date. Payments
            made against the loan but not associated with this plan are not
            included.
          items:
            $ref: '#/components/schemas/Payment'
          type: array
      required:
        - planId
        - type
        - standing
        - autopayEnabled
        - createdAt
        - cadence
        - totals
        - scheduledPayments
        - payments
      type: object
    Cadence:
      description: |-
        The repeating rule the plan was created under.

        Describes the *rule*, not the current rows. Anchor days derive from the
        plan's authored start date, which does not change when a schedule is
        rebuilt — so after a reschedule these can disagree with the actual due
        dates. `scheduledPayments[].dueDate` is authoritative for real timing.
      properties:
        frequency:
          description: WEEKLY, BIWEEKLY, SEMIMONTHLY or MONTHLY.
          type:
            - string
            - 'null'
        dayOfWeek:
          description: ISO day of week (Monday=1). Populated for WEEKLY and BIWEEKLY.
          maximum: 7
          minimum: 1
          type:
            - integer
            - 'null'
        dayOfMonth:
          description: Day of month, 1-31. Populated for MONTHLY.
          maximum: 31
          minimum: 1
          type:
            - integer
            - 'null'
        semimonthlyDays:
          description: >-
            The two days of month, ascending. Populated for SEMIMONTHLY. Always
            either both days or `null` — a partially recorded rule is reported
            as `null` rather than a one-element list.
          items:
            type: integer
          maxItems: 2
          minItems: 2
          type:
            - array
            - 'null'
      type: object
    PlanTotals:
      description: Reconciliation totals for the plan.
      properties:
        originalTotal:
          anyOf:
            - type: number
            - pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
              type: string
            - type: 'null'
          description: >-
            What was owed when the plan was created. `null` means no baseline
            was recorded — it does not mean there was no discount.
        discountedTotal:
          anyOf:
            - type: number
            - pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
              type: string
          description: What the borrower agreed to pay under this plan.
        paidToDate:
          anyOf:
            - type: number
            - pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
              type: string
          description: >-
            Cash attributed to scheduled payments, any source. Equals the sum of
            `scheduledPayments[].amountPaid`, and the sum of successful
            `payments[]` that have an `scheduledPaymentId`.
        creditsApplied:
          anyOf:
            - type: number
            - pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
              type: string
          description: Total credit applied across the plan's scheduled payments. Not cash.
        remainingAmount:
          anyOf:
            - type: number
            - pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
              type: string
          description: >-
            What is still owed: the sum of `amountRemaining` across scheduled
            payments whose status is PENDING, PARTIALLY_PAID or OVERDUE. Do not
            compute this as discountedTotal - paidToDate - creditsApplied; that
            double-counts credit that originated from an overpayment.
        pendingAmount:
          anyOf:
            - type: number
            - pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
              type: string
          description: Payments in flight (status PENDING) against this plan.
        offPlatformPaymentsTotal:
          anyOf:
            - type: number
            - pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
              type: string
          description: >-
            The portion of `paidToDate` that was collected outside Finosu
            (payments with source EXTERNAL). A subset of paidToDate, never an
            addition to it.
      required:
        - discountedTotal
        - paidToDate
        - creditsApplied
        - remainingAmount
        - pendingAmount
        - offPlatformPaymentsTotal
      type: object
    ScheduledPayment:
      description: One installment of the plan.
      properties:
        scheduledPaymentId:
          description: >-
            Finosu identifier for this scheduled payment. Join target for
            `payments[].scheduledPaymentId`.
          type: string
        dueDate:
          description: >-
            When this installment is due, with UTC offset. Authoritative for
            actual timing — unlike `cadence`, it reflects any rescheduling.
          format: date-time
          type: string
        scheduledAmount:
          anyOf:
            - type: number
            - pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
              type: string
          description: The authorized amount for this installment.
        amountPaid:
          anyOf:
            - type: number
            - pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
              type: string
          description: Cash applied to this installment. Excludes returned/refunded.
        creditsApplied:
          anyOf:
            - type: number
            - pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
              type: string
          description: >-
            Credit applied to this installment from the loan's credit balance.
            Kept separate from cash because a credit satisfies an obligation
            with no money movement.
        amountRemaining:
          anyOf:
            - type: number
            - pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
              type: string
          description: >-
            max(0, scheduledAmount - amountPaid - creditsApplied). Only
            meaningful when `status` is PENDING, PARTIALLY_PAID or OVERDUE. A
            MISSED or POSTPONED row reports a non-zero value whose obligation
            has moved elsewhere, so summing across all rows overstates the
            balance.
        status:
          description: >-
            PENDING, PARTIALLY_PAID, OVERDUE, PAID, CANCELLED, MISSED, SKIPPED
            or POSTPONED. Board only rows whose status is PENDING,
            PARTIALLY_PAID or OVERDUE.
          type: string
      required:
        - scheduledPaymentId
        - dueDate
        - scheduledAmount
        - amountPaid
        - creditsApplied
        - amountRemaining
        - status
      type: object
    Payment:
      description: >-
        A payment against this plan.


        Flat and plan-level rather than nested under a scheduled payment: one
        payment

        can overpay row A and have its surplus credited to row B, and nesting
        hides

        that relationship. `scheduledPaymentId` carries the attribution instead.
      properties:
        paymentId:
          description: Finosu identifier for this payment.
          type: string
        scheduledPaymentId:
          description: The scheduled payment this was applied to.
          type: string
        amount:
          anyOf:
            - type: number
            - pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
              type: string
          description: Payment amount.
        currency:
          description: ISO currency code.
          type: string
        status:
          description: >-
            One of PENDING, SUCCESSFUL, FAILED, REFUNDED, RETURNED.
            RETURNED/REFUNDED mean the money came back and does not count toward
            amounts paid.
          type: string
        paymentType:
          description: One of REGULAR, AUTOPAY, PARTIAL, OVERPAYMENT, PAYOFF, PAY_IN_FULL.
          type: string
        source:
          description: >-
            SYSTEM if collected through Finosu, EXTERNAL if collected outside
            it. EXTERNAL is what identifies an off-platform payment.
          type: string
        transactedAt:
          description: >-
            Effective/submission date. A Finosu-side timestamp, not a bank
            confirmation.
          format: date-time
          type: string
        finalizedAt:
          description: >-
            When Finosu considers the payment settled. A Finosu-side timestamp,
            not a bank confirmation.
          format: date-time
          type:
            - string
            - 'null'
        reversedAt:
          description: Set when the payment was returned or refunded.
          format: date-time
          type:
            - string
            - 'null'
        reference:
          description: >-
            The external reference supplied with the payment, for payments the
            lender recorded themselves. The join key back into their ledger.
          type:
            - string
            - 'null'
      required:
        - paymentId
        - scheduledPaymentId
        - amount
        - currency
        - status
        - paymentType
        - source
        - transactedAt
      type: object
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key

````