Reports API
The Reports API manages scheduled quality, governance, task, SLA, FinOps, and custom reports for a space.
All endpoints below are served under the public API base path:
/api/v1.0
Scope And Permissions
Report schedules are space-scoped. Every route requires an authenticated user with access to the target space:
/api/v1.0/spaces/{slug}/reports
Creating a schedule also checks the tenant tier limit for collaboration.max_report_schedules. If the limit has been reached, create another schedule only after increasing the limit or deleting an existing schedule.
Report schedules can optionally include organization_id. When this field is set, built-in report generators produce organization-level rollups where supported. The endpoint remains space-scoped; the organization setting changes the generated report data.
Endpoint Overview
| Method | Endpoint | Description |
|---|---|---|
POST | /spaces/{slug}/reports | Create a report schedule. |
GET | /spaces/{slug}/reports | List schedules in the space. |
GET | /spaces/{slug}/reports/{schedule_id} | Get one schedule. |
PATCH | /spaces/{slug}/reports/{schedule_id} | Update schedule settings. |
DELETE | /spaces/{slug}/reports/{schedule_id} | Delete a schedule. |
POST | /spaces/{slug}/reports/{schedule_id}/preview | Generate report data without sending email. |
POST | /spaces/{slug}/reports/{schedule_id}/send-now | Generate and send the report immediately. |
GET | /spaces/{slug}/reports/{schedule_id}/export/pdf | Export the current report data as PDF. |
GET | /spaces/{slug}/reports/{schedule_id}/export/xlsx | Export the current report data as XLSX. |
GET | /spaces/{slug}/reports/templates | List custom report templates. |
POST | /spaces/{slug}/reports/templates | Create a custom report template. |
PATCH | /spaces/{slug}/reports/templates/{template_id} | Update a custom report template. |
DELETE | /spaces/{slug}/reports/templates/{template_id} | Delete a custom report template. |
Report Types
report_type must be one of:
| Value | Generated content |
|---|---|
quality_health | Quality check totals, latest execution status counts, and pass rate. |
governance_coverage | Product governance assignment coverage and unassigned product counts. |
my_tasks | Pending unread notifications for the schedule creator. |
sla_compliance | SLA contract compliance counts, breach state, and recent contract details. |
finops_chargeback | AI cost allocation for the recent reporting window, grouped by domain. |
custom | Sections assembled from a report template. Requires template_id on create. |
report_type is set when the schedule is created. The update endpoint does not accept report_type; create a new schedule when the report family needs to change.
Schedule Fields
| Field | Type | Notes |
|---|---|---|
name | string | Required on create. |
report_type | enum | Required on create. See Report Types. |
frequency | daily, weekly, monthly | Required on create. |
delivery_day | integer or null | Weekly schedules use 0 for Monday through 6 for Sunday. Monthly schedules use day 1 through 28. Daily schedules ignore this field. |
delivery_hour | integer | UTC hour, 0 through 23. Defaults to 9. |
is_active | boolean | Defaults to true. Inactive schedules are not selected by the scheduler. |
filters | object or null | Report-specific filters. |
recipients | string array | Email recipients used by scheduled delivery and send-now. |
template_id | UUID or null | Required for custom reports. |
organization_id | UUID or null | Generates organization-level data for supported built-in reports. |
attach_pdf | boolean | Include a PDF attachment when sending email. |
attach_xlsx | boolean | Include an XLSX attachment when sending email. |
Responses also include id, space_id, created_by_id, last_sent_at, created_at, and updated_at.
Create Schedule
POST /api/v1.0/spaces/{slug}/reports
{
"name": "Weekly Quality Health",
"report_type": "quality_health",
"frequency": "weekly",
"delivery_day": 0,
"delivery_hour": 9,
"is_active": true,
"recipients": ["quality-team@example.com"],
"filters": {
"domain": "risk"
},
"attach_pdf": true,
"attach_xlsx": false
}
{
"id": "0e1c02f7-1d0f-4b15-96db-23516096c3f3",
"space_id": "64bcfa65-2e1f-4c97-9a5f-c582a0b26d03",
"created_by_id": "1b8f697c-14d1-442a-a80f-90434255d941",
"name": "Weekly Quality Health",
"report_type": "quality_health",
"frequency": "weekly",
"delivery_day": 0,
"delivery_hour": 9,
"is_active": true,
"filters": {
"domain": "risk"
},
"recipients": ["quality-team@example.com"],
"template_id": null,
"organization_id": null,
"attach_pdf": true,
"attach_xlsx": false,
"last_sent_at": null,
"created_at": "2026-06-29T08:30:00Z",
"updated_at": "2026-06-29T08:30:00Z"
}
For custom reports, first create a template and then reference it from the schedule:
{
"name": "Monthly Stewardship Pack",
"report_type": "custom",
"frequency": "monthly",
"delivery_day": 1,
"delivery_hour": 8,
"template_id": "f3efed57-5591-4975-a416-80e7a2b653e0",
"recipients": ["stewards@example.com"]
}
List Schedules
GET /api/v1.0/spaces/{slug}/reports?limit=50&offset=0
Query parameters:
| Parameter | Type | Notes |
|---|---|---|
limit | integer | Defaults to 100. Minimum 1, maximum 500. |
offset | integer | Defaults to 0. |
Response:
{
"items": [
{
"id": "0e1c02f7-1d0f-4b15-96db-23516096c3f3",
"name": "Weekly Quality Health",
"report_type": "quality_health",
"frequency": "weekly",
"delivery_day": 0,
"delivery_hour": 9,
"is_active": true,
"recipients": ["quality-team@example.com"],
"last_sent_at": null
}
],
"total": 1
}
Schedule objects include the full schedule response fields described in Schedule Fields.
Get Schedule
GET /api/v1.0/spaces/{slug}/reports/{schedule_id}
Returns the full schedule response. A schedule from another space is treated as not found.
Update Schedule
PATCH /api/v1.0/spaces/{slug}/reports/{schedule_id}
{
"frequency": "monthly",
"delivery_day": 15,
"delivery_hour": 7,
"recipients": [
"quality-team@example.com",
"governance-leads@example.com"
],
"attach_pdf": true,
"attach_xlsx": true
}
The update endpoint accepts schedule settings such as name, frequency, delivery timing, active state, filters, recipients, template, organization scope, and attachment flags. It does not update report_type.
Fields omitted from the payload keep their current values. Fields sent as null are ignored by the update service for optional scalar fields.
Delete Schedule
DELETE /api/v1.0/spaces/{slug}/reports/{schedule_id}
Returns 204 No Content after deleting the schedule.
Preview Report
POST /api/v1.0/spaces/{slug}/reports/{schedule_id}/preview
Preview generates the same report data used by send and export workflows, but does not send email or update delivery timestamps.
Example response for a quality health report:
{
"report_title": "Quality Health Report",
"space_id": "64bcfa65-2e1f-4c97-9a5f-c582a0b26d03",
"total_checks": 24,
"passing": 20,
"warning": 2,
"failing": 2,
"pass_rate": 83.33,
"generated_at": "2026-06-29T08:35:00.000000Z"
}
Report data varies by report_type. Custom reports return a title, template metadata, generated timestamp, and a sections array assembled from the template.
Send Now
POST /api/v1.0/spaces/{slug}/reports/{schedule_id}/send-now
send-now generates the report immediately and sends it to the schedule's recipients. The schedule must have at least one recipient.
When the background queue is available, the request queues delivery and returns immediately. When the queue is unavailable, the API falls back to direct delivery in the request.
{
"status": "queued",
"sent": 2,
"total_recipients": 2,
"schedule_id": "0e1c02f7-1d0f-4b15-96db-23516096c3f3"
}
sent reflects the number of configured recipients in the queued case. If direct delivery runs and the email provider rejects the message, the API returns a 502 error.
Export Report
PDF and XLSX exports generate current report data for the schedule.
GET /api/v1.0/spaces/{slug}/reports/{schedule_id}/export/pdf
The PDF endpoint returns application/pdf with a content-disposition filename similar to:
report_weekly_quality_health.pdf
GET /api/v1.0/spaces/{slug}/reports/{schedule_id}/export/xlsx
The XLSX endpoint returns:
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Exports are optimized for the built-in report types. Custom reports can be generated and previewed, but spreadsheet sections may fall back to generic output when the template does not match a built-in export schema.
Report Templates
Templates define section lists for custom report schedules.
Allowed section_type values are:
| Value | Section source |
|---|---|
quality_health | Quality health generator. |
governance_coverage | Governance coverage generator. |
sla_compliance | SLA compliance generator. |
issues_summary | Task and notification summary generator. |
finops_chargeback | FinOps chargeback generator. |
List Templates
GET /api/v1.0/spaces/{slug}/reports/templates
Returns an array of templates for the space.
Create Template
POST /api/v1.0/spaces/{slug}/reports/templates
{
"name": "Monthly Stewardship Pack",
"description": "Quality, governance, and SLA sections for data stewards.",
"sections": [
{
"section_type": "quality_health",
"label": "Quality posture",
"filters": {
"domain": "risk"
}
},
{
"section_type": "sla_compliance",
"label": "SLA compliance",
"filters": {}
}
]
}
Response:
{
"id": "f3efed57-5591-4975-a416-80e7a2b653e0",
"name": "Monthly Stewardship Pack",
"description": "Quality, governance, and SLA sections for data stewards.",
"sections": [
{
"section_type": "quality_health",
"label": "Quality posture",
"filters": {
"domain": "risk"
}
},
{
"section_type": "sla_compliance",
"label": "SLA compliance",
"filters": {}
}
]
}
Update Template
PATCH /api/v1.0/spaces/{slug}/reports/templates/{template_id}
The update payload can include name, description, and sections.
Delete Template
DELETE /api/v1.0/spaces/{slug}/reports/templates/{template_id}
Returns 204 No Content after deleting the template.
Failure Cases
| Status | Common cause |
|---|---|
400 | send-now called for a schedule with no recipients. |
404 | The schedule, template, space, or organization-scoped resource cannot be found. |
422 | Invalid UUID, enum value, delivery hour, pagination value, or missing template_id for a custom report. |
502 | Direct email delivery ran in the request and the provider rejected the message. |
Create requests can also fail when the tenant's configured report schedule limit has been reached.