List Recruitment Metrics
/requisitions/recruitment-metricsThis endpoint is not available for agency-scoped API keys.
Recruitment metrics are available only for companies with stage tracking enabled in company config. If no accessible company in the request has it enabled, the API returns HTTP 403 with FEATURE_NOT_ENABLED. Do not retry until the configuration changes or you select an accessible company with stage tracking enabled. MCP clients can check availability with describe_open_api_metadata.
Summary
Returns recruitment performance metrics for eligible companies, with configurable metric, grouping, date range, company, project, and agency filters. For metric=timeToFill, duration runs from requisition approval to accepted supplier response. Responses accepted on or after the latest reopening use the reopened date instead of approval. Earlier responses retain their approval-date baseline.
URL Parameters
- None
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| company | string | No | Filter by company id(s). Pass a single id or comma-separated ids. If omitted, data for all companies linked to the API key is returned. |
| page | integer | No | Page number (default 1) |
| limit | integer | No | Records per page (default 50, max 200) |
| project | string | No | Filter by project id |
| agency | string | No | Filter by agency id(s). Pass a single id or comma-separated ids. |
| metric | enum(rows, timeToFill, workersOverHours) | No | Metric mode. Defaults to rows. |
| groupBy | enum(all, company, project, agency, month, week) | No | Aggregation dimension for metric=timeToFill or metric=workersOverHours. Pass a single value or comma-separated values such as company,agency. Defaults to all. |
| hoursThreshold | number | No | Weekly net-hours threshold for metric=workersOverHours. Defaults to 48. |
| from | string | No | Period filter start (YYYY-MM-DD). Applies to requisition created date for rows, supplier date accepted for timeToFill, and week ending for workersOverHours. |
| to | string | No | Period filter end (YYYY-MM-DD). Applies to requisition created date for rows, supplier date accepted for timeToFill, and week ending for workersOverHours. |
| sortBy | enum(createdAt, reqRef) | No | Sort field |
| sortOrder | enum(asc, desc) | No | Sort direction |
| fields | string | No | Comma-separated list of response fields or dot-path nested fields to return |
Request Example
- cURL
- JavaScript
- Python
curl -X GET 'https://api.requidex.com/api/open/v1/requisitions/recruitment-metrics?from=2026-02-01&to=2026-02-28' \
-H 'Authorization: Bearer <API_KEY>' \
-H 'Accept: application/json'
const response = await fetch(
"https://api.requidex.com/api/open/v1/requisitions/recruitment-metrics?from=2026-02-01&to=2026-02-28",
{
method: "GET",
headers: {
Authorization: "Bearer <API_KEY>",
Accept: "application/json",
},
},
);
const json = await response.json();
import requests
response = requests.request(
'GET',
'https://api.requidex.com/api/open/v1/requisitions/recruitment-metrics?from=2026-02-01&to=2026-02-28',
headers={
'Authorization': 'Bearer <API_KEY>',
'Accept': 'application/json',
},
timeout=30,
)
print(response.json())
Response Fields
When metric is omitted or set to rows, the endpoint returns paginated recruitment metric rows. Stage identifiers remain stable; currentStageLabel and stageDates[].label use the hiring company’s configured names. Custom stages are included, and excluded stages retain any recorded dates.
When metric=timeToFill, it returns grouped approved-date to supplier accepted-date day metrics with the 1.5 IQR outlier rule applied per group.
When metric=workersOverHours, it returns grouped worker-week net-hours threshold metrics.
| Field | Type | Description |
|---|---|---|
| assigned | string | Assigned date (DD/MM/YYYY) |
| currentStage | string | Current recruitment stage |
| cvRejected | string | Yes when the submitted worker was rejected, otherwise No |
| cvReviewed | string | CV reviewed date (DD/MM/YYYY) |
| interviewed | string | Interviewed date (DD/MM/YYYY) |
| managerReviewDays | integer | Days from submitted to CV reviewed |
| missingCompliance | string | Missing compliance date (DD/MM/YYYY) |
| offerAccepted | string | Offer accepted date (DD/MM/YYYY) |
| offerMade | string | Offer made date (DD/MM/YYYY) |
| offerRejected | string | Offer rejected date (DD/MM/YYYY) |
| offerToStartDays | integer | Days from offer accepted to requisition start |
| project | string | Project name |
| reqCreated | string | Requisition created date (DD/MM/YYYY) |
| reqReopened | string | Latest reopened date (DD/MM/YYYY), or an empty string if never reopened |
| reqRef | string | Requisition reference |
| reqStart | string | Requisition start date (DD/MM/YYYY) |
| submitted | string | Submitted date (DD/MM/YYYY) |
| supplier | string | Agency name |
| timeToFillDays | integer | Days from requisition creation to offer made, or accepted supplier response when no offer is recorded. Uses the latest reopened date when the target date is on or after reopening |
| timeToInterviewDays | integer | Days from submitted to interviewed |
| timeToOfferAcceptedDays | integer | Days from requisition created to offer accepted |
| timeToOfferDays | integer | Days from submitted to offer made |
| trade | string | Trade name |
| worker | string | Worker name |
Aggregate response fields
For metric=timeToFill, each row contains:
| Field | Type | Description |
|---|---|---|
| group | object | Group keys for the requested groupBy; empty when groupBy=all |
| rawCount | integer | Accepted supplier responses before IQR outlier exclusion |
| excludedOutliers | integer | Responses excluded by the 1.5 IQR rule |
| iqrBounds | object | Lower and upper day bounds used for outlier exclusion |
| values | object | count, averageDays, medianDays, minDays, maxDays, p25Days, and p75Days after outlier exclusion |
For metric=workersOverHours, each row contains:
| Field | Type | Description |
|---|---|---|
| group | object | Group keys for the requested groupBy; empty when groupBy=all |
| values | object | thresholdHours, hoursField, workerWeeks, workersOverThreshold, distinctWorkersOverThreshold, totalHours, averageWeeklyHours, and maxWeeklyHours |
Additional row fields:
| Field | Type | Description |
|---|---|---|
| currentStageLabel | string | Configured name of the current stage |
| interviewRequested | string | First interview request date (DD/MM/YYYY), or empty |
| interviewBooked | string | First interview booking date (DD/MM/YYYY), or empty |
| withdrew | string | First withdrawal date (DD/MM/YYYY), or empty |
| requestToBookingDays | integer/null | Days from interview request to booking |
| bookingToInterviewDays | integer/null | Days from booking to interview |
| timeToWithdrawalDays | integer/null | Days from submission to first withdrawal |
| hasWithdrawn | boolean | Whether this submission has a dated withdrawal entry, even if the worker later returned to another stage |
| stageDates | array[object] | Stage dates in company-configured order, followed by any remaining built-in or historical stages. Show child attributes
|
For row metrics, meta.withdrawalSummary covers all matching worker submissions before pagination:
| Field | Type | Description |
|---|---|---|
| withdrawalSummary | object | Withdrawal summary within the caller’s existing report scope. Show child attributes
|
This counts recorded withdrawal stages, including submissions later moved to another stage. It does not infer withdrawals from rejections or assignment cancellations. Timing fields are null when either required date is missing.
Response Example (200)
{
"success": true,
"data": [
{
"reqRef": "REQ-R1002",
"reqCreated": "20/02/2026",
"reqReopened": "",
"reqStart": "01/03/2026",
"project": "Northern Rail Electrification",
"trade": "Electrician",
"supplier": "Northline Labour Desk",
"worker": "Jordan Worker",
"submitted": "21/02/2026",
"cvReviewed": "21/02/2026",
"interviewed": "",
"offerMade": "",
"offerAccepted": "",
"offerRejected": "",
"assigned": "",
"missingCompliance": "",
"managerReviewDays": 0,
"timeToInterviewDays": null,
"timeToOfferDays": null,
"timeToFillDays": null,
"timeToOfferAcceptedDays": null,
"offerToStartDays": null,
"currentStage": "cvReviewed",
"cvRejected": "No"
}
],
"meta": {
"page": 1,
"limit": 50,
"total": 1
}
}
Aggregate Response Example (200)
{
"success": true,
"data": [
{
"group": {
"agency": {
"id": "67bc36db80a1616ec3f48988",
"name": "Northline Labour Desk"
}
},
"rawCount": 12,
"excludedOutliers": 1,
"iqrBounds": {
"lower": 0,
"upper": 21
},
"values": {
"count": 11,
"averageDays": 7.45,
"medianDays": 6,
"minDays": 1,
"maxDays": 18,
"p25Days": 4,
"p75Days": 10
}
}
],
"meta": {
"total": 1,
"metric": "timeToFill",
"groupBy": "agency",
"dateField": "dateAccepted",
"outlierRule": "IQR_1_5"
}
}
MCP Tool
The MCP server exposes this operation as open_api_list_recruitment_metrics with the inputs company, page, limit, project, agency, metric, groupBy, hoursThreshold, from, to, sortBy, sortOrder, and fields.
Errors
| HTTP Status | Description |
|---|---|
| 400 | Invalid query parameter |
| 401 | Missing, invalid, revoked, or expired API key |
| 403 | Access restriction, or FEATURE_NOT_ENABLED when stage tracking is requested but unavailable |
| 405 | Method not allowed on Open API routes |
| 429 | Rate limit exceeded |
| 500 | Unexpected internal error |