Reports
The Reports API returns analytics and compliance data directly - there's no job queue, no polling, and no report IDs to fetch later. Every endpoint here runs its query and responds with the data (or a PDF/CSV file) in the same request.
Everything lives under /api/reports and uses your dashboard session rather than an API key. Most endpoints require the superadmin, admin, manager, or hr role; /my-tasks and /upcoming-exits are open to any authenticated user since they power the general Mission Control dashboard.
If you need scheduled, recurring delivery instead of querying on demand, see Scheduled reports below - that part genuinely is a job that runs on a schedule and emails or webhooks the result out.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/reports/summary | Offboarding counts, stage/type breakdowns, completion trend |
GET | /api/reports/upcoming-exits | Employees exiting within N days |
GET | /api/reports/my-tasks | The current user's outstanding checklist tasks |
GET | /api/reports/compliance-summary | NDA / exit-interview / legal-hold counts |
GET | /api/reports/offboarding/:id/pdf | Single-employee offboarding PDF |
GET | /api/reports/advanced | Velocity trend, bottleneck tasks, time-by-department |
GET | /api/reports/benchmarks | Org metrics vs. anonymised platform and industry benchmarks |
GET | /api/reports/analytics-pdf | PDF export of the analytics dashboard |
GET | /api/reports/sla-compliance | SLA compliance rates, breach trend, worst offenders |
GET | /api/reports/sla-compliance/export | CSV of every SLA-tracked checklist item |
Summary
GET /api/reports/summary?from=2025-01-01&to=2025-06-30
from/to are optional but must be supplied together (YYYY-MM-DD); omitting them returns all-time figures.
{
"stageCounts": [{ "status": "completed", "cnt": "42" }],
"sepTypeCounts": [{ "separation_type": "resignation", "cnt": "30" }],
"completedByMonth": [{ "month": "Jun 2025", "cnt": "8" }],
"avgCompletionDays": 6.4,
"overdueCount": 3,
"topServices": [{ "service": "slack", "cnt": "40" }],
"checklistStats": { "total": 512, "done": 470 },
"deptBreakdown": [{ "department": "Engineering", "cnt": "18" }]
}Upcoming exits
GET /api/reports/upcoming-exits?days=14
days caps at 60. Returns an array, one row per employee exiting within the window, ordered by exit date:
[
{
"id": "8f4c6d1a-...",
"employee_name": "Jordan Lee",
"department": "Engineering",
"job_title": "Senior Engineer",
"status": "notice_period",
"last_working_day": "2025-07-01",
"days_remaining": 5,
"pending_tasks": 3
}
]My tasks
GET /api/reports/my-tasks
Returns up to 50 of the current user's outstanding checklist items, matched by role against each item's assigned_to field.
Compliance summary
GET /api/reports/compliance-summary
Counts across all currently active (non-completed) offboardings:
{
"total_offboardings": "12",
"nda_signed": "9",
"nda_pending": "3",
"exit_interview_done": "7",
"legal_hold_count": "1"
}Single-employee PDF
GET /api/reports/offboarding/:id/pdf
Requires the pdfExport plan feature. Streams a PDF covering employee details, checklist status, access-revocation status, compliance documents, and any org-defined custom fields with a value set. Returns 404 if the offboarding doesn't exist in your org.
Advanced analytics
GET /api/reports/advanced?from=&to=
{
"velocityTrend": [{ "month": "2025-06", "started": "10", "completed": "8" }],
"timeByDept": [{ "department": "Engineering", "avg_days": "7.2", "cnt": "6" }],
"bottleneckTasks": [{ "task": "Revoke AWS access", "total": "12", "pending": "5", "pending_pct": "42" }],
"avgBySepType": [{ "separation_type": "resignation", "avg_days": "6.1", "cnt": "20" }]
}bottleneckTasks only includes tasks that appear at least twice across active offboardings, ranked by the percentage still incomplete.
Benchmarks
GET /api/reports/benchmarks
Compares your org's completion time and on-time rate against two baselines: an anonymised platform-wide average (computed across all orgs) and a set of static industry figures sourced from SHRM, LinkedIn Talent Trends, and Gartner HR benchmarking data.
The platform-wide average is only shown when at least 50 offboardings exist across the platform in the trailing 12 months - below that, platform.sufficientSample is false and the response falls back to the static industry numbers instead, so a small aggregate can't be used to infer another org's activity.
{
"org": { "avgCompletionDays": 6.4, "total": 42, "completionRate": 88, "onTimeRate": 91, "overdueCount": 2 },
"platform": { "avgCompletionDays": 7.1, "totalOffboardings": 8400, "completionRate": 81, "onTimeRate": 76, "sufficientSample": true },
"industry": { "avgCompletionDays": 8.2, "completionRate": 77, "onTimeRate": 64, "sepTypeDist": { "resignation": 54 }, "deptAvgDays": { "Engineering": 9.1 } },
"orgSepTrend": [{ "month": "Jun 25", "separation_type": "resignation", "cnt": "4" }],
"platformSepDist": [{ "separation_type": "resignation", "cnt": "4500", "pct": "53.6" }],
"orgDeptDuration": [{ "department": "Engineering", "avg_days": "7.2", "cnt": "6" }]
}Analytics PDF
GET /api/reports/analytics-pdf?from=&to=
Requires pdfExport. A PDF version of the summary/advanced dashboard: KPIs, separation-type breakdown, average completion time by department, and bottleneck tasks.
SLA compliance
GET /api/reports/sla-compliance?period=week&from=&to=
Requires the slaComplianceDashboard plan feature. period is week or month (default week); from/to default to the last 90 days and the window can't exceed 2 years.
{
"period": "week",
"from": "2025-04-01",
"to": "2025-06-30",
"totalSlaTracked": 340,
"completedCount": 300,
"onTime": 270,
"breachedTotal": 30,
"overallRate": 90.0,
"byDepartment": [{ "dept": "Engineering", "total": 80, "completed": 72, "onTime": 65, "breached": 7, "rate": 90.3 }],
"byAssignee": [{ "assignee": "it-team", "total": 120, "completed": 110, "onTime": 100, "breached": 10, "rate": 90.9 }],
"breachTrend": [{ "period": "2025-06-01T00:00:00.000Z", "breachCount": 2, "total": 24, "rate": 91.7 }],
"worstItems": [{ "task": "Revoke VPN access", "totalSla": 40, "breaches": 8, "avgSlaHours": 24.5, "breachRate": 20.0 }]
}A checklist item only counts toward these numbers if it has an SLA deadline set - items without one are excluded entirely, not counted as compliant.
SLA compliance export
GET /api/reports/sla-compliance/export
Requires slaComplianceDashboard. Returns a CSV with one row per SLA-tracked checklist item: task, employee name/email/department, assignee, SLA hours, SLA deadline, completed, breached, completed-at, and hours overdue. Values that could be interpreted as spreadsheet formulas are neutralised before export.
Scheduled reports
Recurring report delivery is a separate, genuinely job-based feature under /api/scheduled-reports (requires the scheduledReports plan feature). Unlike everything above, this one really does run asynchronously - on the schedule you configure, not synchronously in the request.
| Method | Path | Description |
|---|---|---|
GET | /api/scheduled-reports | List an org's scheduled reports |
POST | /api/scheduled-reports | Create one (admin/superadmin only) |
PATCH | /api/scheduled-reports/:id | Update it |
DELETE | /api/scheduled-reports/:id | Delete it |
GET / POST / PATCH / DELETE | /api/scheduled-reports/distribution-lists[/:id] | Manage reusable recipient lists |
Creating a schedule
{
"name": "Weekly HR digest",
"type": "weekly_summary",
"schedule": "weekly",
"columns": ["employee_name", "department", "status", "exit_date"],
"grouping": "department",
"date_range": "last_30_days",
"recipients": ["hr-team@acme.com"],
"include_pdf": true
}type is one of weekly_summary, monthly_summary, offboarding_stats, overdue_tasks, or custom. schedule is daily, weekly, or monthly. You need at least one of recipients (up to 50 inline emails) or a distribution_list_id. An optional delivery_webhook can also receive the generated report - it must be a public HTTPS URL; internal/private addresses are rejected. This delivery is a plain unsigned POST ({ report_id, report_name, org_name, generated_at, date_range, summary, row_count }) sent by the scheduler, not the same signed mechanism as Webhooks - there's no X-PurpletGo-Signature header to verify here.
Error responses
These endpoints return plain { "error": "..." } bodies rather than a fixed error-code enum:
| Status | When |
|---|---|
400 | Invalid from/to date, or an invalid date range for SLA compliance |
403 | Role doesn't have reporting access, or the plan doesn't include a gated feature (pdfExport, slaComplianceDashboard) |
404 | Offboarding not found (PDF export) |
500 | Query or PDF generation failed |