API Reference
Reports

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

MethodPathDescription
GET/api/reports/summaryOffboarding counts, stage/type breakdowns, completion trend
GET/api/reports/upcoming-exitsEmployees exiting within N days
GET/api/reports/my-tasksThe current user's outstanding checklist tasks
GET/api/reports/compliance-summaryNDA / exit-interview / legal-hold counts
GET/api/reports/offboarding/:id/pdfSingle-employee offboarding PDF
GET/api/reports/advancedVelocity trend, bottleneck tasks, time-by-department
GET/api/reports/benchmarksOrg metrics vs. anonymised platform and industry benchmarks
GET/api/reports/analytics-pdfPDF export of the analytics dashboard
GET/api/reports/sla-complianceSLA compliance rates, breach trend, worst offenders
GET/api/reports/sla-compliance/exportCSV 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.

MethodPathDescription
GET/api/scheduled-reportsList an org's scheduled reports
POST/api/scheduled-reportsCreate one (admin/superadmin only)
PATCH/api/scheduled-reports/:idUpdate it
DELETE/api/scheduled-reports/:idDelete 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:

StatusWhen
400Invalid from/to date, or an invalid date range for SLA compliance
403Role doesn't have reporting access, or the plan doesn't include a gated feature (pdfExport, slaComplianceDashboard)
404Offboarding not found (PDF export)
500Query or PDF generation failed

Related

  • Audit Log - the underlying event trail behind the compliance summary
  • Webhooks - a signed, event-driven alternative to polling these endpoints