Skip to main content

Debt API

Created: January 27, 2025This documentation provides comprehensive information about the Debt API endpoints, including customer debt tracking, invoice management, and payment processing capabilities.
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.
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.

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>
All endpoints require store-level access. The x-store-id header must match a store the authenticated user has access to.

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
{
  "customers": [
    {
      "id": "customer-uuid-123",
      "firstName": "Layla",
      "lastName": "Hassan",
      "userName": "[email protected]",
      "totalDueAmount": 1250.75,
      "numberOfInvoices": 3
    },
    {
      "id": "customer-uuid-456",
      "firstName": "Ahmed",
      "lastName": "Benali",
      "userName": "[email protected]",
      "totalDueAmount": 850.50,
      "numberOfInvoices": 2
    }
  ]
}

Response Fields

FieldTypeDescription
customersarrayArray of customers with outstanding debt
customers[].idstringUnique customer identifier
customers[].firstNamestring | nullCustomer’s first name
customers[].lastNamestring | nullCustomer’s last name
customers[].userNamestring | nullCustomer’s username or email
customers[].totalDueAmountnumberTotal outstanding debt amount across all invoices
customers[].numberOfInvoicesnumberCount 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

curl -X GET "https://joptic.jethings.com/debt/customers" \
  -H "x-store-id: your-store-id" \
  -H "Authorization: Bearer <token>"

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

ParameterTypeRequiredDescription
customerIdstring✅ YesThe ID of the customer

Query Parameters

ParameterTypeRequiredDefaultDescription
onlyOutstandingbooleanNofalseIf true, returns only invoices with outstanding balances

Success Response

Status Code: 200 OK
{
  "customer": {
    "id": "customer-uuid-123",
    "firstName": "Layla",
    "lastName": "Hassan",
    "userName": "[email protected]"
  },
  "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

FieldTypeDescription
customerobjectCustomer information
customer.idstringCustomer identifier
customer.firstNamestring | nullCustomer’s first name
customer.lastNamestring | nullCustomer’s last name
customer.userNamestring | nullCustomer’s username or email
invoicesarrayArray of customer invoices
invoices[].idstringInvoice identifier
invoices[].ttcstringTotal tax included (invoice total)
invoices[].totalPaidnumberTotal amount paid towards this invoice
invoices[].outstandingAmountnumberRemaining unpaid amount (ttc - totalPaid)
invoices[].createdAtstringInvoice creation timestamp (ISO 8601)
invoices[].storeIdstring | nullStore ID associated with the invoice
invoices[].isPosInvoicebooleanWhether this is a POS invoice
invoices[].doc_statusstringDocument status (e.g., “Submitted”, “Paid”)

Error Responses

404 Not Found - Customer not found
{
  "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

# 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>"

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

ParameterTypeRequiredDescription
customerIdstring✅ YesThe ID of the customer

Request Body

FieldTypeRequiredDescription
amountnumber✅ YesPayment amount (must be positive, minimum 0.01)

Request Body Example

{
  "amount": 500.00
}

Success Response

Status Code: 200 OK
{
  "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

FieldTypeDescription
successbooleanIndicates if the payment was successful
paymentsCreatedarrayArray of payment entries and allocations created
paymentsCreated[].paymentEntryobjectPayment entry record
paymentsCreated[].paymentAllocationobjectPayment allocation linking payment to invoice
paymentsCreated[].invoiceIdstringID of the invoice that was paid
paymentsCreated[].amountPaidnumberAmount paid towards this invoice
remainingAmountnumberRemaining payment amount if payment exceeded total debt

Special Cases

No Unpaid Invoices:
{
  "success": true,
  "message": "No unpaid invoices found for this customer",
  "paymentsCreated": [],
  "remainingAmount": 500.00
}

Error Responses

400 Bad Request - Invalid payment amount
{
  "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

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
  }'

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

ParameterTypeRequiredDescription
customerIdstring✅ YesThe ID of the customer
invoiceIdstring✅ YesThe ID of the invoice to pay

Request Body

FieldTypeRequiredDescription
amountnumber✅ YesPayment amount (must be positive, minimum 0.01)

Request Body Example

{
  "amount": 250.00
}

Success Response

Status Code: 200 OK
{
  "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

FieldTypeDescription
successbooleanIndicates if the payment was successful
messagestring | nullOptional message (e.g., “Invoice is already fully paid”)
paymentEntryobject | nullPayment entry record (null if invoice already paid)
paymentAllocationobject | nullPayment allocation record (null if invoice already paid)
amountPaidnumberActual amount paid (may be less than requested if invoice has less outstanding)
remainingOutstandingnumberRemaining outstanding amount after payment

Special Cases

Invoice Already Fully Paid:
{
  "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:
{
  "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
{
  "statusCode": 400,
  "message": ["amount must be a positive number", "amount must not be less than 0.01"],
  "error": "Bad Request"
}
Or:
{
  "statusCode": 400,
  "message": "Invoice does not have a storeId",
  "error": "Bad Request"
}
404 Not Found - Invoice not found or doesn’t belong to customer
{
  "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

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
  }'

Important Notes

Payment Processing

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.
  • 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
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
  • 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

Debt Calculation

Outstanding Amount

Calculated as: ttc - totalPaid
outstandingAmount = invoiceTotal - paymentsMade

Total Debt

Sum of all outstanding amounts across all invoices for a customer
totalDebt = Σ(outstandingAmount)

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

1

Get Customers with Debt

Use GET /debt/customers to retrieve all customers who have outstanding balances
2

View Customer Invoices

Use GET /debt/customers/:customerId/invoices to see all invoices and their payment status
3

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)
4

Verify Payment

Check the response to confirm payment amounts and remaining balances
This API provides comprehensive debt management for optical stores, enabling efficient tracking of customer balances, invoice management, and flexible payment processing options.