Reports Routes
Table of Contents
Overview
The Reports API provides powerful analytics and reporting capabilities for your BAASIX application. It offers two main functionalities:
- Report Generation - Create detailed reports with grouping, aggregation, and relational data
- Statistics Generation - Generate multiple statistics from different collections in a single request
Both endpoints leverage the same query structure as the Items API, ensuring consistency and familiarity.
Generate Report
Generate detailed reports from a specific collection with support for aggregation, grouping, and relational fields.
- URL:
/reports/:collection - Method:
POST - Auth required: Yes
URL Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| collection | string | Yes | Name of the collection |
Request Body
The request body supports all standard ItemsService query parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| fields | array | No | Fields to include (supports dot notation) |
| filter | object | No | Filter conditions |
| sort | object | No | Sort criteria |
| limit | number | No | Maximum number of results |
| page | number | No | Page number for pagination |
| aggregate | object | No | Aggregation functions |
| groupBy | array | No | Fields to group by (supports date functions) |
Optimization Features
The Reports API automatically optimizes queries based on the request:
- Simple Reports - No groupBy: Direct pass-through to ItemsService
- Grouped Reports - With groupBy but no relational fields: Single optimized query
- Complex Reports - With groupBy and relational fields: Two-step optimization approach
Success Response
- Code: 200 OK
- Content:
{
"data": [
{
"categoryId": 1,
"avg_price": 849.99,
"product_count": "2",
"category": {
"id": 1,
"name": "Electronics",
"description": "Electronic devices"
}
}
],
"totalCount": 3
}Error Responses
-
Code: 400 Bad Request
- Content:
{ "error": { "message": "Invalid query parameters" } }
- Content:
-
Code: 401 Unauthorized
- Content:
{ "error": { "message": "Authentication required" } }
- Content:
-
Code: 403 Forbidden
- Content:
{ "error": { "message": "Insufficient permissions" } }
- Content:
-
Code: 404 Not Found
- Content:
{ "error": { "message": "Model not found" } }
- Content:
-
Code: 500 Internal Server Error
- Content:
{ "error": { "message": "Error generating report" } }
- Content:
Generate Statistics
Generate multiple statistics from different collections in a single request.
- URL:
/reports/stats - Method:
POST - Auth required: Yes
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| stats | array | Yes | Array of statistics queries |
Each stats object should contain:
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Unique name for this statistic |
| collection | string | Yes | Target collection name |
| query | object | Yes | Query parameters for the report |
Success Response
- Code: 200 OK
- Content:
{
"data": {
"total_products": {
"data": [
{
"count": "6"
}
],
"totalCount": 1
},
"products_by_category": {
"data": [
{
"count": "2",
"avg_price": 849.99,
"categoryId": 1,
"category": {
"id": 1,
"name": "Electronics"
}
}
],
"totalCount": 3
}
},
"totalStats": 2,
"successfulStats": 2
}Error Responses
-
Code: 400 Bad Request
- Content:
{ "error": { "message": "stats array is required and must not be empty" } } - Content:
{ "error": { "message": "Each stats query must have a 'collection' property" } }
- Content:
-
Code: 404 Not Found
- Content:
{ "error": { "message": "Model {collection} not found" } }
- Content:
Date Functions
The Reports API supports advanced date-based grouping using PostgreSQL's EXTRACT function:
Supported Date Functions
| Function | Description | Range |
|---|---|---|
| year | Year (4 digits) | - |
| month | Month number | 1-12 |
| day | Day of month | 1-31 |
| hour | Hour of day | 0-23 |
| minute | Minute of hour | 0-59 |
| week | Week number of year | 1-53 |
| dow | Day of week (Sunday=0) | 0-6 |
| isodow | ISO day of week (Monday=1) | 1-7 |
Date Function Syntax
Use the format: date:{function}:{field}
Examples:
date:year:createdAt- Group by yeardate:month:orderDate- Group by monthdate:dow:createdAt- Group by day of week (0=Sunday)date:isodow:createdAt- Group by ISO day of week (1=Monday)
Advanced Features
Relational Field Support
The Reports API supports dot notation for accessing related data:
{
"fields": ["categoryId", "category.name", "category.description"],
"groupBy": ["categoryId"],
"aggregate": {
"avg_price": { "function": "avg", "field": "price" },
"product_count": { "function": "count", "field": "id" }
}
}Two-Step Optimization
When using relational fields with groupBy, the API automatically uses a two-step approach:
- Step 1: Execute aggregation query with grouping
- Step 2: Fetch relational data using efficient filtering
- Merge: Combine results for optimal performance
Aggregation Functions
All standard aggregation functions are supported:
| Function | Description |
|---|---|
| count | Count of records |
| sum | Sum of numeric values |
| avg | Average of numeric values |
| min | Minimum value |
| max | Maximum value |
| distinct | Count of distinct values |
| array_agg | Array of values |
Examples
Basic Report
Generate a simple product report:
POST /reports/products
Authorization: Bearer <token>
Content-Type: application/json
{
"fields": ["name", "price"],
"filter": { "categoryId": 1 },
"limit": 10
}Grouped Report with Aggregation
Group products by category with average price:
POST /reports/products
Authorization: Bearer <token>
Content-Type: application/json
{
"groupBy": ["categoryId"],
"aggregate": {
"avg_price": { "function": "avg", "field": "price" },
"count": { "function": "count", "field": "*" }
},
"fields": ["categoryId"]
}Report with Relational Data
Group products by category and include category information:
POST /reports/products
Authorization: Bearer <token>
Content-Type: application/json
{
"groupBy": ["categoryId"],
"aggregate": {
"avg_price": { "function": "avg", "field": "price" },
"product_count": { "function": "count", "field": "id" }
},
"fields": ["categoryId", "category.name", "category.description"]
}Date-Based Reporting
Group orders by year and month:
POST /reports/orders
Authorization: Bearer <token>
Content-Type: application/json
{
"groupBy": ["date:year:createdAt", "date:month:createdAt"],
"aggregate": {
"total_amount": { "function": "sum", "field": "amount" },
"order_count": { "function": "count", "field": "id" }
}
}Day of Week Analysis
Analyze orders by day of week:
POST /reports/orders
Authorization: Bearer <token>
Content-Type: application/json
{
"groupBy": ["date:dow:createdAt"],
"aggregate": {
"daily_total": { "function": "sum", "field": "amount" },
"order_count": { "function": "count", "field": "id" }
}
}ISO Day of Week Analysis
Using ISO standard (Monday=1):
POST /reports/orders
Authorization: Bearer <token>
Content-Type: application/json
{
"groupBy": ["date:isodow:createdAt"],
"aggregate": {
"weekly_total": { "function": "sum", "field": "amount" },
"order_count": { "function": "count", "field": "id" }
}
}Complex Report with Relations and Date
Group by category and year with related data:
POST /reports/orders
Authorization: Bearer <token>
Content-Type: application/json
{
"groupBy": ["categoryId", "date:year:createdAt"],
"aggregate": {
"yearly_total": { "function": "sum", "field": "amount" },
"order_count": { "function": "count", "field": "id" }
},
"fields": ["categoryId", "date:year:createdAt", "category.name", "category.description"]
}Multiple Statistics Request
Generate multiple statistics in one request:
POST /reports/stats
Authorization: Bearer <token>
Content-Type: application/json
{
"stats": [
{
"name": "total_products",
"collection": "products",
"query": {
"aggregate": {
"count": { "function": "count", "field": "*" }
}
}
},
{
"name": "orders_by_month",
"collection": "orders",
"query": {
"groupBy": ["date:month:createdAt"],
"aggregate": {
"monthly_total": { "function": "sum", "field": "amount" },
"order_count": { "function": "count", "field": "id" }
}
}
},
{
"name": "products_by_category",
"collection": "products",
"query": {
"groupBy": ["categoryId"],
"aggregate": {
"count": { "function": "count", "field": "id" },
"avg_price": { "function": "avg", "field": "price" }
},
"fields": ["categoryId", "category.name"]
}
}
]
}Date Range with Complex Filtering
Analyze sales data with complex conditions:
POST /reports/orders
Authorization: Bearer <token>
Content-Type: application/json
{
"groupBy": ["date:month:createdAt", "categoryId"],
"aggregate": {
"monthly_revenue": { "function": "sum", "field": "amount" },
"order_count": { "function": "count", "field": "id" },
"avg_order_value": { "function": "avg", "field": "amount" }
},
"filter": {
"AND": [
{ "status": { "eq": "completed" } },
{ "createdAt": { "between": ["2024-01-01", "2024-12-31"] } }
]
},
"fields": ["categoryId", "date:month:createdAt", "category.name"],
"sort": { "monthly_revenue": "desc" }
}Performance Considerations
Query Optimization
- Use specific fields - Only request fields you need
- Leverage indexing - Ensure groupBy fields are indexed
- Limit results - Use appropriate limits for large datasets
- Filter early - Apply filters to reduce dataset size
Two-Step Approach Benefits
- Reduced memory usage - Processes data in optimized chunks
- Better performance - Avoids complex JOINs in aggregation queries
- Scalability - Handles large datasets efficiently
Date Function Performance
- Date functions are computed at the database level for optimal performance
- Consider creating functional indexes for frequently used date extractions:
CREATE INDEX idx_orders_year ON orders (EXTRACT(year FROM created_at)); CREATE INDEX idx_orders_dow ON orders (EXTRACT(dow FROM created_at));
Error Handling
Common Error Scenarios
- Invalid Collection - Returns 404 when collection doesn't exist
- Invalid Query Structure - Returns 400 for malformed queries
- Permission Denied - Returns 403 for insufficient permissions
- Database Errors - Returns 500 for database-related issues
Error Response Format
All errors follow the standard BAASIX error format:
{
"error": {
"message": "Descriptive error message",
"code": "ERROR_CODE",
"details": {}
}
}Related Documentation
- Item Query Reference Guide - Advanced query options
- Item Routes Documentation - Standard CRUD operations
- Schema Reference Guide - Data model definitions
- API Routes Reference - Complete list of all API endpoints