Invoice Analytics

Retrieve comprehensive analytics and metrics for your invoices, including KPIs, status breakdowns, aging analysis, top customers, and revenue trends.

Endpoints

Summary Analytics

GET
/api/v1/invoices/analytics/summary

Get comprehensive invoice analytics including KPIs, status counts, aging buckets, and top customers.

Revenue Timeseries

GET
/api/v1/invoices/analytics/revenue-timeseries

Get revenue trends over time aggregated by day, week, or month.

Summary Analytics Endpoint

Query Parameters

FieldTypeRequiredDescriptionExample
fromstring
Required
Start date for analytics (ISO 8601 format)2025-11-01T00:00:00Z
tostring
Required
End date for analytics (ISO 8601 format)2025-11-30T23:59:59Z

Code Examples

import requests
url = "http://localhost:8000/api/v1/invoices/analytics/summary"
headers = {
"Authorization": "Bearer your-api-key"
}
params = {
"from": "2025-11-01T00:00:00Z",
"to": "2025-11-30T23:59:59Z"
}
response = requests.get(url, headers=headers, params=params)
analytics = response.json()
print(analytics)

Response Structure

{
  "summary": {
    "status_counts": {
      "draft": 5,
      "sent": 20,
      "paid": 45,
      "overdue": 3,
      "canceled": 2
    },
    "total_invoiced": "5000.00",
    "total_paid": "4200.00",
    "total_outstanding": "700.00",
    "total_overdue": "300.00",
    "collection_rate": 0.857,
    "avg_time_to_pay_days": 5.2
  },
  "aging": {
    "days_0_30": "400.00",
    "days_31_60": "200.00",
    "days_61_90": "100.00",
    "days_90_plus": "0.00"
  },
  "top_customers": [
    {
      "customer_name": "Acme Corp",
      "customer_email": "[email protected]",
      "invoice_count": 10,
      "total_invoiced": "1500.00",
      "total_paid": "1400.00"
    }
  ]
}

Summary Fields

FieldTypeRequiredDescriptionExample
status_countsobject
Required
Count of invoices by status{"draft": 5, "sent": 20, "paid": 45, "overdue": 3, "canceled": 2}
total_invoicedstring (Decimal)
Required
Total amount invoiced (status: sent, paid, or overdue) in the date range5000.00
total_paidstring (Decimal)
Required
Total amount paid in the date range4200.00
total_outstandingstring (Decimal)
Required
Total amount outstanding (status: sent or overdue)700.00
total_overduestring (Decimal)
Required
Total amount overdue300.00
collection_ratefloat
Required
Collection rate calculated as: total_paid / (total_paid + total_outstanding). Range: 0.0 to 1.00.857
avg_time_to_pay_daysfloat | nullOptionalAverage number of days from invoice issued_at to paid_at for paid invoices5.2

Aging Fields

FieldTypeRequiredDescriptionExample
days_0_30string (Decimal)
Required
Amount overdue for 0-30 days400.00
days_31_60string (Decimal)
Required
Amount overdue for 31-60 days200.00
days_61_90string (Decimal)
Required
Amount overdue for 61-90 days100.00
days_90_plusstring (Decimal)
Required
Amount overdue for 90+ days0.00

Top Customers Fields

FieldTypeRequiredDescriptionExample
customer_namestring
Required
Customer nameAcme Corp
customer_emailstring | nullOptionalCustomer email address[email protected]
invoice_countinteger
Required
Number of invoices for this customer10
total_invoicedstring (Decimal)
Required
Total amount invoiced to this customer1500.00
total_paidstring (Decimal)
Required
Total amount paid by this customer1400.00

Revenue Timeseries Endpoint

Query Parameters

FieldTypeRequiredDescriptionExample
fromstring
Required
Start date for analytics (ISO 8601 format)2025-11-01T00:00:00Z
tostring
Required
End date for analytics (ISO 8601 format)2025-11-30T23:59:59Z
granularitystringOptionalTime granularity for aggregation: 'day', 'week', or 'month'day

Code Examples

import requests
url = "http://localhost:8000/api/v1/invoices/analytics/revenue-timeseries"
headers = {
"Authorization": "Bearer your-api-key"
}
params = {
"from": "2025-11-01T00:00:00Z",
"to": "2025-11-30T23:59:59Z",
"granularity": "day"
}
response = requests.get(url, headers=headers, params=params)
timeseries = response.json()
print(timeseries)

Response Structure

{
  "timeseries": [
    {
      "bucket": "2025-11-01",
      "paid_amount": "500.00",
      "paid_count": 5
    },
    {
      "bucket": "2025-11-02",
      "paid_amount": "300.00",
      "paid_count": 3
    }
  ]
}

Timeseries Fields

FieldTypeRequiredDescriptionExample
bucketstring
Required
Date bucket (YYYY-MM-DD format for day, YYYY-MM-DD for week/month representing the start of the period)2025-11-01
paid_amountstring (Decimal)
Required
Total amount paid in this time bucket500.00
paid_countinteger
Required
Number of invoices paid in this time bucket5

Metrics Explanation

Collection Rate

The collection rate measures payment efficiency:

collection_rate = total_paid / (total_paid + total_outstanding)
  • Range: 0.0 to 1.0 (0% to 100%)
  • Higher values indicate better collection performance
  • Only considers invoices that were sent (status: sent, paid, or overdue)

Average Time to Pay

Average number of days between invoice issued_at and paid_at:

  • Calculated only for paid invoices
  • Excludes invoices without both issued_at and paid_at timestamps
  • Returns null if no paid invoices exist in the date range

Aging Buckets

Aging analysis groups outstanding invoices by days overdue:

  • 0-30 days: Recently overdue invoices
  • 31-60 days: Moderately overdue
  • 61-90 days: Significantly overdue
  • 90+ days: Severely overdue

Only includes invoices with status sent or overdue that have a due_at date.

Error Scenarios

400 Bad Request

  • Invalid date format (must be ISO 8601)
  • from date is after to date
  • Invalid granularity value (must be 'day', 'week', or 'month')

401 Unauthorized

  • Missing or invalid API key
  • API key does not have permission to access analytics

500 Internal Server Error

  • Database query failure
  • Service error during analytics calculation

Related Documentation