Skip to content

Analytics API

All endpoints require authentication and analytics:view permission. Date range defaults to the last 90 days when from/to are omitted. Dates use YYYY-MM-DD format.

GET /api/analytics/utilisation

Per-person allocated vs capacity hours over a date range. Capacity is approximated as calendar days x 8 h (no holiday/weekend exclusion). Allocated hours are summed from active allocations overlapping the range.

Query parameters:

ParamTypeDescription
fromstringStart date (default: 90 days ago)
tostringEnd date (default: today)
squad_idstringFilter by squad
user_idstringFilter by user

Response: { data, meta }

Each item in data:

FieldTypeDescription
user_idstringUser ID
namestringUser name
emailstringUser email
squadstring|nullSquad name
capacity_hoursnumberTotal capacity hours in range
allocated_hoursnumberTotal allocated hours in range
utilisation_pctnumberPercentage utilised (0-100+)

GET /api/analytics/utilisation/trends

Weekly utilisation percentages for sparkline/chart rendering. Each bucket represents a Mon-Sun week.

Query parameters:

ParamTypeDescription
fromstringStart date (default: 90 days ago)
tostringEnd date (default: today)
squad_idstringFilter by squad

Response: { data, meta }

Each item in data:

FieldTypeDescription
weekstringHuman-readable week label (e.g. “14 Apr”)
week_startstringISO date of Monday
week_endstringISO date of Sunday
allocated_hoursnumberTotal allocated hours that week
capacity_hoursnumberTotal capacity hours (active employees x 40h)
utilisation_pctnumberPercentage utilised

GET /api/analytics/deals/pipeline

Current pipeline by stage with deal counts, values, and win rate.

Response: { data, summary, meta }

Each item in data:

FieldTypeDescription
stage_idstringPipeline stage ID
stage_namestringStage name
stage_typestringStage type
positionnumberStage position
deal_countnumberNumber of deals in stage
total_valuenumberSum of estimated budgets

summary:

FieldTypeDescription
total_dealsnumberTotal deals across all stages
total_valuenumberTotal pipeline value
win_rate_pctnumberWin rate percentage

GET /api/analytics/deals/velocity

Average days from deal creation to close, grouped by stage. Approximated from created_at to actual_close_date.

Query parameters:

ParamTypeDescription
fromstringStart date (default: 90 days ago)
tostringEnd date (default: today)

Response: { data, meta, _note }

Each item in data:

FieldTypeDescription
stage_namestringPipeline stage name
positionnumberStage position
deal_countnumberClosed deals in this stage
avg_days_to_closenumber|nullAverage days to close

GET /api/analytics/recruitment/funnel

Candidate counts by stage for active applications with stage-to-stage conversion rates.

Query parameters:

ParamTypeDescription
job_idstringFilter by recruitment job

Response: { data, meta }

Each item in data:

FieldTypeDescription
stage_idstringPipeline stage ID
stage_namestringStage name
stage_typestringStage type
positionnumberStage position
candidate_countnumberActive candidates in stage
conversion_rate_pctnumber|nullConversion rate from previous stage

GET /api/analytics/recruitment/time-to-hire

Average days from application to hire, grouped by department.

Query parameters:

ParamTypeDescription
fromstringStart date (default: 90 days ago)
tostringEnd date (default: today)
departmentstringFilter by department

Response: { data, summary, meta }

Each item in data:

FieldTypeDescription
departmentstringDepartment name
hired_countnumberNumber of hires
avg_days_to_hirenumber|nullAverage days to hire
min_daysnumber|nullFastest hire (days)
max_daysnumber|nullSlowest hire (days)

summary:

FieldTypeDescription
total_hirednumberTotal hires in range
avg_days_to_hirenumber|nullOverall average

GET /api/analytics/leave/conflicts

Overlapping approved/pending leave within the same squad. Returns up to 200 conflict pairs.

Query parameters:

ParamTypeDescription
fromstringStart date (default: 90 days ago)
tostringEnd date (default: today)
squad_idstringFilter by squad

Response: { data, meta }

Each item in data:

FieldTypeDescription
leave1_idstringFirst leave request ID
person1_namestringFirst person’s name
squadstringShared squad
leave1_typestringFirst leave type
leave1_startstringFirst leave start date
leave1_endstringFirst leave end date
leave2_idstringSecond leave request ID
person2_namestringSecond person’s name
leave2_typestringSecond leave type
leave2_startstringSecond leave start date
leave2_endstringSecond leave end date

GET /api/analytics/leave/summary

Leave balance and taken summary per active person, grouped by leave type.

Query parameters:

ParamTypeDescription
yearstringYear to filter (default: current year)

Response: { data, meta }

Each item in data:

FieldTypeDescription
person_idstringPerson ID
person_namestringPerson’s full name
squadstring|nullSquad name
leave_balancesarrayArray of { leave_type, balance_hours, entitlement_hours, taken_hours }

GET /api/analytics/budget/alerts

Budgets approaching or exceeding a spend threshold. Burn percentage is calculated as logged hours / budgeted hours.

Query parameters:

ParamTypeDescription
thresholdnumberAlert threshold 0-100 (default: 80)

Response: { data, meta }

Each item in data:

FieldTypeDescription
budget_idstringBudget ID
budget_namestringBudget name
resource_typestringResource type
resource_idstringResource ID
total_amountnumber|nullBudget amount
statusstringBudget status
budgeted_hoursnumberTotal budgeted hours
logged_hoursnumberTotal logged hours
entry_countnumberTime entry count
burn_pctnumberBurn percentage

GET /api/analytics/budget/forecast

Projected hours spend for each budget based on current allocations.

Query parameters:

ParamTypeDescription
fromstringStart date (default: 90 days ago)
tostringEnd date (default: today)

Response: { data, meta }

Each item in data:

FieldTypeDescription
budget_idstringBudget ID
budget_namestringBudget name
total_amountnumber|nullBudget total
statusstringBudget status
forecast_hoursnumberProjected hours from allocations
forecast_vs_budget_pctnumber|nullForecast as percentage of budget

GET /api/analytics/retention/signals

Scored list of retention risk indicators for active employees, sorted by risk score descending.

Signals detected:

  • no_recent_allocations — no active allocations in the last 90 days (+30 pts)
  • long_tenure_5plus_years — employed 5+ years (+20 pts)

Response: { data, meta }

Each item in data:

FieldTypeDescription
person_idstringPerson ID
namestringPerson name
squadstring|nullSquad
start_datestring|nullEmployment start date
risk_scorenumberComposite risk score
risk_factorsstring[]List of detected risk factor keys