Skip to content

Finance API

API endpoints for the Finance module. All endpoints require JWT authentication and are prefixed with /finance.

Authentication

All endpoints require a valid JWT token:

Authorization: Bearer <token>

Role-based access is enforced per endpoint (see the Auth column).

Invoices

MethodPathDescriptionAuth
GET/finance/invoicesList invoices with filtersfinance.read
GET/finance/invoices/{id}Get invoice details with itemsfinance.read
POST/finance/invoices/generateGenerate invoice for a customerfinance.write
PUT/finance/invoices/{id}/statusUpdate invoice statusfinance.write
GET/finance/invoices/{id}/pdfDownload invoice PDFfinance.read
POST/finance/invoices/{id}/sendSend invoice by emailfinance.write

POST /finance/invoices/generate

Generates an invoice from unbilled transactions for a customer within a date range.

Request:

json
{
  "customer_id": 1234,
  "date_from": "2026-02-01",
  "date_to": "2026-02-28",
  "notes": "February 2026 billing"
}

Response (201):

json
{
  "id": 5678,
  "invoice_number": "INV-2026-001234",
  "customer_id": 1234,
  "status": "draft",
  "subtotal": 15000.00,
  "tax_amount": 2400.00,
  "total": 17400.00,
  "items_count": 42,
  "pdf_url": "https://s3.amazonaws.com/envia/invoices/INV-2026-001234.pdf",
  "issued_at": null,
  "due_date": null
}

Errors:

CodeDescription
400Invalid date range or missing fields
404Customer not found
409No unbilled transactions in the given range

GET /finance/invoices

Query Parameters:

ParamTypeRequiredDescription
customer_idnumberNoFilter by customer
statusstringNoFilter by status: draft, issued, paid, overdue, cancelled
date_fromstringNoIssued date range start (YYYY-MM-DD)
date_tostringNoIssued date range end (YYYY-MM-DD)
pagenumberNoPage number (default: 1)
limitnumberNoItems per page (default: 20, max: 100)

Response (200):

json
{
  "data": [
    {
      "id": 5678,
      "invoice_number": "INV-2026-001234",
      "customer_name": "Acme Corp",
      "status": "issued",
      "total": 17400.00,
      "issued_at": "2026-03-01T06:00:00Z",
      "due_date": "2026-03-15"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 156
  }
}

Payments

MethodPathDescriptionAuth
GET/finance/paymentsList payments with filtersfinance.read
GET/finance/payments/{id}Get payment detailsfinance.read
POST/finance/paymentsRegister a new paymentfinance.write
DELETE/finance/payments/{id}Cancel a payment (soft delete)finance.admin

POST /finance/payments

Registers a payment and updates the customer balance.

Request:

json
{
  "customer_id": 1234,
  "amount": 17400.00,
  "method": "bank_transfer",
  "reference": "TRF-20260301-ABC123",
  "invoice_id": 5678,
  "notes": "Payment for February invoice"
}

Response (201):

json
{
  "id": 9012,
  "customer_id": 1234,
  "amount": 17400.00,
  "method": "bank_transfer",
  "reference": "TRF-20260301-ABC123",
  "invoice_id": 5678,
  "balance_after": 0.00,
  "created_at": "2026-03-01T14:30:00Z",
  "created_by": {
    "id": 42,
    "name": "Admin User"
  }
}

Errors:

CodeDescription
400Invalid amount or missing fields
404Customer or invoice not found
409Invoice already fully paid

Transactions

MethodPathDescriptionAuth
GET/finance/transactionsList transactions with filtersfinance.read
GET/finance/transactions/{id}Get transaction detailsfinance.read
POST/finance/transactions/adjustmentCreate manual adjustmentfinance.admin

GET /finance/transactions

Query Parameters:

ParamTypeRequiredDescription
customer_idnumberNoFilter by customer
typestringNoFilter: charge, payment, refund, adjustment
date_fromstringNoDate range start
date_tostringNoDate range end
billedbooleanNotrue = billed, false = unbilled
pagenumberNoPage number (default: 1)
limitnumberNoItems per page (default: 50, max: 200)

Balances

MethodPathDescriptionAuth
GET/finance/balancesList all customer balancesfinance.read
GET/finance/balances/{customer_id}Get balance for a customerfinance.read
GET/finance/balances/{customer_id}/summaryBalance summary with breakdownfinance.read

GET /finance/balances/{customer_id}/summary

Returns a detailed balance breakdown for a customer.

Response (200):

json
{
  "customer_id": 1234,
  "customer_name": "Acme Corp",
  "current_balance": -5200.00,
  "breakdown": {
    "total_charges": 125000.00,
    "total_payments": 119800.00,
    "total_adjustments": 0.00,
    "total_refunds": 0.00
  },
  "unbilled_amount": 5200.00,
  "overdue_invoices": 0,
  "last_payment_date": "2026-02-28T10:15:00Z"
}

Reports

MethodPathDescriptionAuth
GET/finance/reports/revenueRevenue report by periodfinance.admin
GET/finance/reports/agingAccounts receivable aging reportfinance.admin
GET/finance/reports/exportExport transactions to Excelfinance.read

GET /finance/reports/export

Query Parameters:

ParamTypeRequiredDescription
customer_idnumberNoFilter by customer
date_fromstringYesExport range start
date_tostringYesExport range end
formatstringNoxlsx (default) or csv

Response: File download (Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)

Common Error Responses

All errors follow the Boom format:

json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Descriptive error message"
}
StatusWhen
400Validation failed (Joi schema)
401Missing or invalid JWT
403Insufficient permissions for the action
404Resource not found
409Business rule conflict (e.g., duplicate payment, no unbilled transactions)

Envia Admin