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

# Debt API

> Manage customer debt, retrieve invoices, and process payments for outstanding balances

# Debt API

<Note>
  **Created:** January 27, 2025

  This documentation provides comprehensive information about the Debt API endpoints, including customer debt tracking, invoice management, and payment processing capabilities.
</Note>

The Debt API enables optical stores to track customer debt, view invoice details, and process payments for outstanding balances. The API provides endpoints to retrieve customers with debt, view their invoices, and make payments either to specific invoices or distribute payments across all outstanding invoices.

<Note>
  All Debt API endpoints require authentication and store context. Ensure you include the `x-store-id` header and a valid Bearer token for all requests.
</Note>

## Overview

The Debt API provides comprehensive debt management capabilities:

* **Customer Debt Tracking**: Retrieve all customers with outstanding debt amounts and invoice counts
* **Invoice Management**: View customer invoices with payment status and outstanding amounts
* **Payment Processing**: Make payments to specific invoices or distribute payments across multiple invoices
* **Payment History**: Track payment entries and allocations for audit purposes

## Endpoint Details

**Base URL:** `https://joptic.jethings.com`

### Required Headers

```
x-store-id: <store_id>
Authorization: Bearer <token>
```

<Warning>
  All endpoints require store-level access. The `x-store-id` header must match a store the authenticated user has access to.
</Warning>

***

## Get Customers with Debt

**GET** `/debt/customers`

Retrieve a list of all customers who have outstanding debt, including their total due amounts and the number of unpaid invoices.

**Requires Authentication:** Bearer token in Authorization header\
**Requires Header:** `x-store-id`

### Success Response

**Status Code:** `200 OK`

```json theme={null}
{
  "customers": [
    {
      "id": "customer-uuid-123",
      "firstName": "Layla",
      "lastName": "Hassan",
      "userName": "layla@example.com",
      "totalDueAmount": 1250.75,
      "numberOfInvoices": 3
    },
    {
      "id": "customer-uuid-456",
      "firstName": "Ahmed",
      "lastName": "Benali",
      "userName": "ahmed.benali@example.com",
      "totalDueAmount": 850.50,
      "numberOfInvoices": 2
    }
  ]
}
```

### Response Fields

| Field                          | Type             | Description                                       |
| ------------------------------ | ---------------- | ------------------------------------------------- |
| `customers`                    | `array`          | Array of customers with outstanding debt          |
| `customers[].id`               | `string`         | Unique customer identifier                        |
| `customers[].firstName`        | `string \| null` | Customer's first name                             |
| `customers[].lastName`         | `string \| null` | Customer's last name                              |
| `customers[].userName`         | `string \| null` | Customer's username or email                      |
| `customers[].totalDueAmount`   | `number`         | Total outstanding debt amount across all invoices |
| `customers[].numberOfInvoices` | `number`         | Count of invoices with outstanding balances       |

### Notes

* Only customers with at least one invoice that has an outstanding balance are included
* The `totalDueAmount` is calculated as the sum of all outstanding amounts across all unpaid invoices
* Invoices are considered unpaid if `totalPaid < ttc` (total tax included)
* Deleted customers and deleted invoices are automatically excluded

### Example Requests

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://joptic.jethings.com/debt/customers" \
    -H "x-store-id: your-store-id" \
    -H "Authorization: Bearer <token>"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://joptic.jethings.com/debt/customers", {
    method: "GET",
    headers: {
      "x-store-id": "your-store-id",
      Authorization: "Bearer <token>",
    },
  })

  const result = await response.json()
  ```

  ```python Python theme={null}
  import requests

  url = "https://joptic.jethings.com/debt/customers"

  response = requests.get(
      url,
      headers={
          "x-store-id": "your-store-id",
          "Authorization": "Bearer <token>"
      }
  )

  print(response.json())
  ```
</CodeGroup>

***

## Get Customer Invoices

**GET** `/debt/customers/:customerId/invoices`

Retrieve all invoices for a specific customer, including payment status and outstanding amounts. Optionally filter to show only invoices with outstanding balances.

**Requires Authentication:** Bearer token in Authorization header\
**Requires Header:** `x-store-id`

### Path Parameters

| Parameter    | Type     | Required | Description            |
| ------------ | -------- | -------- | ---------------------- |
| `customerId` | `string` | ✅ Yes    | The ID of the customer |

### Query Parameters

| Parameter         | Type      | Required | Default | Description                                                |
| ----------------- | --------- | -------- | ------- | ---------------------------------------------------------- |
| `onlyOutstanding` | `boolean` | No       | `false` | If `true`, returns only invoices with outstanding balances |

### Success Response

**Status Code:** `200 OK`

```json theme={null}
{
  "customer": {
    "id": "customer-uuid-123",
    "firstName": "Layla",
    "lastName": "Hassan",
    "userName": "layla@example.com"
  },
  "invoices": [
    {
      "id": "invoice-uuid-1",
      "ttc": 500.00,
      "totalPaid": 250.00,
      "outstandingAmount": 250.00,
      "createdAt": "2024-01-15T10:00:00.000Z",
      "storeId": "store-uuid",
      "isPosInvoice": false,
      "doc_status": "Submitted"
    },
    {
      "id": "invoice-uuid-2",
      "ttc": 750.75,
      "totalPaid": 0.00,
      "outstandingAmount": 750.75,
      "createdAt": "2024-01-20T14:30:00.000Z",
      "storeId": "store-uuid",
      "isPosInvoice": true,
      "doc_status": "Submitted"
    },
    {
      "id": "invoice-uuid-3",
      "ttc": 300.00,
      "totalPaid": 300.00,
      "outstandingAmount": 0.00,
      "createdAt": "2024-01-10T09:15:00.000Z",
      "storeId": "store-uuid",
      "isPosInvoice": false,
      "doc_status": "Paid"
    }
  ]
}
```

### Response Fields

| Field                          | Type             | Description                                 |
| ------------------------------ | ---------------- | ------------------------------------------- |
| `customer`                     | `object`         | Customer information                        |
| `customer.id`                  | `string`         | Customer identifier                         |
| `customer.firstName`           | `string \| null` | Customer's first name                       |
| `customer.lastName`            | `string \| null` | Customer's last name                        |
| `customer.userName`            | `string \| null` | Customer's username or email                |
| `invoices`                     | `array`          | Array of customer invoices                  |
| `invoices[].id`                | `string`         | Invoice identifier                          |
| `invoices[].ttc`               | `string`         | Total tax included (invoice total)          |
| `invoices[].totalPaid`         | `number`         | Total amount paid towards this invoice      |
| `invoices[].outstandingAmount` | `number`         | Remaining unpaid amount (ttc - totalPaid)   |
| `invoices[].createdAt`         | `string`         | Invoice creation timestamp (ISO 8601)       |
| `invoices[].storeId`           | `string \| null` | Store ID associated with the invoice        |
| `invoices[].isPosInvoice`      | `boolean`        | Whether this is a POS invoice               |
| `invoices[].doc_status`        | `string`         | Document status (e.g., "Submitted", "Paid") |

### Error Responses

**404 Not Found** - Customer not found

```json theme={null}
{
  "statusCode": 404,
  "message": "Customer not found"
}
```

### Notes

* Invoices are sorted by creation date (oldest first)
* When `onlyOutstanding=true`, only invoices where `outstandingAmount > 0` are returned
* The `outstandingAmount` is calculated as `ttc - totalPaid`
* Deleted invoices are automatically excluded

### Example Requests

<CodeGroup>
  ```bash cURL theme={null}
  # Get all invoices
  curl -X GET "https://joptic.jethings.com/debt/customers/customer-uuid-123/invoices" \
    -H "x-store-id: your-store-id" \
    -H "Authorization: Bearer <token>"

  # Get only outstanding invoices
  curl -X GET "https://joptic.jethings.com/debt/customers/customer-uuid-123/invoices?onlyOutstanding=true" \
    -H "x-store-id: your-store-id" \
    -H "Authorization: Bearer <token>"
  ```

  ```javascript JavaScript theme={null}
  // Get all invoices
  const response = await fetch(
    "https://joptic.jethings.com/debt/customers/customer-uuid-123/invoices",
    {
      method: "GET",
      headers: {
        "x-store-id": "your-store-id",
        Authorization: "Bearer <token>",
      },
    }
  )

  // Get only outstanding invoices
  const params = new URLSearchParams({ onlyOutstanding: "true" })
  const responseOutstanding = await fetch(
    `https://joptic.jethings.com/debt/customers/customer-uuid-123/invoices?${params}`,
    {
      method: "GET",
      headers: {
        "x-store-id": "your-store-id",
        Authorization: "Bearer <token>",
      },
    }
  )

  const result = await response.json()
  ```

  ```python Python theme={null}
  import requests

  # Get all invoices
  url = "https://joptic.jethings.com/debt/customers/customer-uuid-123/invoices"

  response = requests.get(
      url,
      headers={
          "x-store-id": "your-store-id",
          "Authorization": "Bearer <token>"
      }
  )

  # Get only outstanding invoices
  params = {"onlyOutstanding": True}
  response_outstanding = requests.get(
      url,
      headers={
          "x-store-id": "your-store-id",
          "Authorization": "Bearer <token>"
      },
      params=params
  )

  print(response.json())
  ```
</CodeGroup>

***

## Pay Customer Debt

**POST** `/debt/customers/:customerId/pay`

Make a payment towards a customer's total debt. The payment is automatically distributed across the customer's unpaid invoices, starting with the oldest invoice first. If the payment amount exceeds the total outstanding debt, the remaining amount is returned.

**Requires Authentication:** Bearer token in Authorization header\
**Requires Header:** `x-store-id`

### Path Parameters

| Parameter    | Type     | Required | Description            |
| ------------ | -------- | -------- | ---------------------- |
| `customerId` | `string` | ✅ Yes    | The ID of the customer |

### Request Body

| Field    | Type     | Required | Description                                     |
| -------- | -------- | -------- | ----------------------------------------------- |
| `amount` | `number` | ✅ Yes    | Payment amount (must be positive, minimum 0.01) |

### Request Body Example

```json theme={null}
{
  "amount": 500.00
}
```

### Success Response

**Status Code:** `200 OK`

```json theme={null}
{
  "success": true,
  "paymentsCreated": [
    {
      "paymentEntry": {
        "id": "payment-entry-uuid-1",
        "paymentAmount": 250.00,
        "postingTime": "2024-01-25T10:00:00.000Z",
        "partyId": "customer-uuid-123",
        "storeId": "store-uuid",
        "partyType": "customer"
      },
      "paymentAllocation": {
        "id": "allocation-uuid-1",
        "amount": 250.00,
        "paymentId": "payment-entry-uuid-1",
        "reference_id": "invoice-uuid-1",
        "refrence_type": "sale"
      },
      "invoiceId": "invoice-uuid-1",
      "amountPaid": 250.00
    },
    {
      "paymentEntry": {
        "id": "payment-entry-uuid-2",
        "paymentAmount": 250.00,
        "postingTime": "2024-01-25T10:00:00.000Z",
        "partyId": "customer-uuid-123",
        "storeId": "store-uuid",
        "partyType": "customer"
      },
      "paymentAllocation": {
        "id": "allocation-uuid-2",
        "amount": 250.00,
        "paymentId": "payment-entry-uuid-2",
        "reference_id": "invoice-uuid-2",
        "refrence_type": "sale"
      },
      "invoiceId": "invoice-uuid-2",
      "amountPaid": 250.00
    }
  ],
  "remainingAmount": 0.00
}
```

### Response Fields

| Field                                 | Type      | Description                                             |
| ------------------------------------- | --------- | ------------------------------------------------------- |
| `success`                             | `boolean` | Indicates if the payment was successful                 |
| `paymentsCreated`                     | `array`   | Array of payment entries and allocations created        |
| `paymentsCreated[].paymentEntry`      | `object`  | Payment entry record                                    |
| `paymentsCreated[].paymentAllocation` | `object`  | Payment allocation linking payment to invoice           |
| `paymentsCreated[].invoiceId`         | `string`  | ID of the invoice that was paid                         |
| `paymentsCreated[].amountPaid`        | `number`  | Amount paid towards this invoice                        |
| `remainingAmount`                     | `number`  | Remaining payment amount if payment exceeded total debt |

### Special Cases

**No Unpaid Invoices:**

```json theme={null}
{
  "success": true,
  "message": "No unpaid invoices found for this customer",
  "paymentsCreated": [],
  "remainingAmount": 500.00
}
```

### Error Responses

**400 Bad Request** - Invalid payment amount

```json theme={null}
{
  "statusCode": 400,
  "message": ["amount must be a positive number", "amount must not be less than 0.01"],
  "error": "Bad Request"
}
```

### Notes

* Payments are distributed across invoices in chronological order (oldest first)
* Each invoice is paid up to its outstanding amount before moving to the next invoice
* If a payment amount exceeds the total outstanding debt, the `remainingAmount` field indicates the excess
* Invoices without a `storeId` are skipped during payment distribution
* Each payment creates a `paymentEntry` and a corresponding `paymentAllocation` record

### Example Requests

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://joptic.jethings.com/debt/customers/customer-uuid-123/pay" \
    -H "x-store-id: your-store-id" \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "amount": 500.00
    }'
  ```

  ```javascript JavaScript theme={null}
  const paymentData = {
    amount: 500.00,
  }

  const response = await fetch(
    "https://joptic.jethings.com/debt/customers/customer-uuid-123/pay",
    {
      method: "POST",
      headers: {
        "x-store-id": "your-store-id",
        Authorization: "Bearer <token>",
        "Content-Type": "application/json",
      },
      body: JSON.stringify(paymentData),
    }
  )

  const result = await response.json()
  ```

  ```python Python theme={null}
  import requests

  url = "https://joptic.jethings.com/debt/customers/customer-uuid-123/pay"

  payment_data = {
      "amount": 500.00
  }

  response = requests.post(
      url,
      headers={
          "x-store-id": "your-store-id",
          "Authorization": "Bearer <token>",
          "Content-Type": "application/json"
      },
      json=payment_data
  )

  print(response.json())
  ```
</CodeGroup>

***

## Pay Invoice

**POST** `/debt/customers/:customerId/invoices/:invoiceId/pay`

Make a payment towards a specific invoice. The payment amount cannot exceed the outstanding balance of the invoice. If the invoice is already fully paid, a success response is returned with no payment created.

**Requires Authentication:** Bearer token in Authorization header\
**Requires Header:** `x-store-id`

### Path Parameters

| Parameter    | Type     | Required | Description                  |
| ------------ | -------- | -------- | ---------------------------- |
| `customerId` | `string` | ✅ Yes    | The ID of the customer       |
| `invoiceId`  | `string` | ✅ Yes    | The ID of the invoice to pay |

### Request Body

| Field    | Type     | Required | Description                                     |
| -------- | -------- | -------- | ----------------------------------------------- |
| `amount` | `number` | ✅ Yes    | Payment amount (must be positive, minimum 0.01) |

### Request Body Example

```json theme={null}
{
  "amount": 250.00
}
```

### Success Response

**Status Code:** `200 OK`

```json theme={null}
{
  "success": true,
  "paymentEntry": {
    "id": "payment-entry-uuid",
    "paymentAmount": 250.00,
    "postingTime": "2024-01-25T10:00:00.000Z",
    "partyId": "customer-uuid-123",
    "storeId": "store-uuid",
    "partyType": "customer"
  },
  "paymentAllocation": {
    "id": "allocation-uuid",
    "amount": 250.00,
    "paymentId": "payment-entry-uuid",
    "reference_id": "invoice-uuid-1",
    "refrence_type": "sale"
  },
  "amountPaid": 250.00,
  "remainingOutstanding": 0.00
}
```

### Response Fields

| Field                  | Type             | Description                                                                     |
| ---------------------- | ---------------- | ------------------------------------------------------------------------------- |
| `success`              | `boolean`        | Indicates if the payment was successful                                         |
| `message`              | `string \| null` | Optional message (e.g., "Invoice is already fully paid")                        |
| `paymentEntry`         | `object \| null` | Payment entry record (null if invoice already paid)                             |
| `paymentAllocation`    | `object \| null` | Payment allocation record (null if invoice already paid)                        |
| `amountPaid`           | `number`         | Actual amount paid (may be less than requested if invoice has less outstanding) |
| `remainingOutstanding` | `number`         | Remaining outstanding amount after payment                                      |

### Special Cases

**Invoice Already Fully Paid:**

```json theme={null}
{
  "success": true,
  "message": "Invoice is already fully paid",
  "paymentEntry": null,
  "paymentAllocation": null,
  "amountPaid": 0,
  "remainingOutstanding": 0
}
```

**Partial Payment (amount exceeds outstanding):**
If you request to pay 500.00 but the invoice only has 250.00 outstanding:

```json theme={null}
{
  "success": true,
  "paymentEntry": {
    "id": "payment-entry-uuid",
    "paymentAmount": 250.00,
    "postingTime": "2024-01-25T10:00:00.000Z",
    "partyId": "customer-uuid-123",
    "storeId": "store-uuid",
    "partyType": "customer"
  },
  "paymentAllocation": {
    "id": "allocation-uuid",
    "amount": 250.00,
    "paymentId": "payment-entry-uuid",
    "reference_id": "invoice-uuid-1",
    "refrence_type": "sale"
  },
  "amountPaid": 250.00,
  "remainingOutstanding": 0.00
}
```

### Error Responses

**400 Bad Request** - Invalid payment amount or missing storeId

```json theme={null}
{
  "statusCode": 400,
  "message": ["amount must be a positive number", "amount must not be less than 0.01"],
  "error": "Bad Request"
}
```

Or:

```json theme={null}
{
  "statusCode": 400,
  "message": "Invoice does not have a storeId",
  "error": "Bad Request"
}
```

**404 Not Found** - Invoice not found or doesn't belong to customer

```json theme={null}
{
  "statusCode": 404,
  "message": "Invoice not found or does not belong to this customer",
  "error": "Not Found"
}
```

### Notes

* The payment amount is automatically capped at the invoice's outstanding amount
* If the requested amount exceeds the outstanding balance, only the outstanding amount is paid
* The `amountPaid` field reflects the actual amount applied to the invoice
* If an invoice is already fully paid, the endpoint returns success with `amountPaid: 0` and no payment records created
* The invoice must have a valid `storeId` for the payment to be processed

### Example Requests

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://joptic.jethings.com/debt/customers/customer-uuid-123/invoices/invoice-uuid-1/pay" \
    -H "x-store-id: your-store-id" \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "amount": 250.00
    }'
  ```

  ```javascript JavaScript theme={null}
  const paymentData = {
    amount: 250.00,
  }

  const response = await fetch(
    "https://joptic.jethings.com/debt/customers/customer-uuid-123/invoices/invoice-uuid-1/pay",
    {
      method: "POST",
      headers: {
        "x-store-id": "your-store-id",
        Authorization: "Bearer <token>",
        "Content-Type": "application/json",
      },
      body: JSON.stringify(paymentData),
    }
  )

  const result = await response.json()
  ```

  ```python Python theme={null}
  import requests

  url = "https://joptic.jethings.com/debt/customers/customer-uuid-123/invoices/invoice-uuid-1/pay"

  payment_data = {
      "amount": 250.00
  }

  response = requests.post(
      url,
      headers={
          "x-store-id": "your-store-id",
          "Authorization": "Bearer <token>",
          "Content-Type": "application/json"
      },
      json=payment_data
  )

  print(response.json())
  ```
</CodeGroup>

***

## Important Notes

### Payment Processing

<AccordionGroup>
  <Accordion title="Payment Distribution">
    When paying customer debt (not a specific invoice), payments are distributed across invoices in chronological order (oldest first). Each invoice is paid up to its outstanding amount before moving to the next invoice.
  </Accordion>

  <Accordion title="Payment Amount Limits">
    * Payment amounts are automatically capped at the outstanding balance
    * For customer debt payments, if the amount exceeds total debt, the excess is returned in `remainingAmount`
    * For invoice payments, if the amount exceeds outstanding, only the outstanding amount is paid
  </Accordion>

  <Accordion title="Payment Records">
    Each successful payment creates:

    * A `paymentEntry` record tracking the payment transaction
    * A `paymentAllocation` record linking the payment to the specific invoice
    * Both records are returned in the response for audit purposes
  </Accordion>

  <Accordion title="Invoice Validation">
    * Invoices must belong to the specified customer
    * Invoices must have a valid `storeId` for payments to be processed
    * Deleted invoices are automatically excluded from all operations
  </Accordion>
</AccordionGroup>

### Debt Calculation

<CardGroup cols={2}>
  <Card title="Outstanding Amount" icon="calculator">
    Calculated as: `ttc - totalPaid`

    <br />

    <code>outstandingAmount = invoiceTotal - paymentsMade</code>
  </Card>

  <Card title="Total Debt" icon="dollar-sign">
    Sum of all outstanding amounts across all invoices for a customer

    <br />

    <code>totalDebt = Σ(outstandingAmount)</code>
  </Card>
</CardGroup>

### Data Filtering

* Only non-deleted customers and invoices are included in results
* Invoices with `ttc` (total tax included) of `null` are excluded
* Customers with no outstanding debt are excluded from the customers list
* Invoices are sorted by creation date (oldest first) for payment distribution

***

## Summary

<Steps>
  <Step title="Get Customers with Debt">
    Use `GET /debt/customers` to retrieve all customers who have outstanding balances
  </Step>

  <Step title="View Customer Invoices">
    Use `GET /debt/customers/:customerId/invoices` to see all invoices and their payment status
  </Step>

  <Step title="Make Payment">
    Choose between:

    * Pay specific invoice: `POST /debt/customers/:customerId/invoices/:invoiceId/pay`
    * Pay customer debt: `POST /debt/customers/:customerId/pay` (distributes across invoices)
  </Step>

  <Step title="Verify Payment">
    Check the response to confirm payment amounts and remaining balances
  </Step>
</Steps>

This API provides comprehensive debt management for optical stores, enabling efficient tracking of customer balances, invoice management, and flexible payment processing options.

***

<CardGroup cols={2}>
  <Card title="Customer API" icon="users" href="/j-optic/customer-api">
    Create and manage optical customers
  </Card>

  <Card title="POS Checkout API" icon="shopping-cart" href="/j-optic/pos-checkout-api">
    Process point of sale transactions
  </Card>
</CardGroup>
