Skip to content

Performance API

List review cycles. Non-executive users only see open/closed cycles.

Permission: view:performance

Create a new review cycle.

Permission: manage:performance

Body:

{
"type": "quarterly",
"name": "Q1 2026 Review",
"period_start": "2026-01-01",
"period_end": "2026-03-31",
"due_date": "2026-04-15"
}

Get cycle detail with review progress stats (total, completed, draft, self_assessment, in_review, ready_for_review).

Permission: view:performance

Update cycle fields (name, dates, status).

Permission: manage:performance

Body:

{
"status": "open"
}

Delete a draft cycle. Returns 400 if cycle is not in draft status.

Permission: manage:performance

Returns goals from the current user’s most recent completed review. Used by the dashboard to display current goals.

Permission: view:performance

Response:

{
"goals": [
{
"id": "goal-1",
"review_id": "review-abc",
"goal": "Complete AI certification",
"success_measures": "Certificate obtained",
"support_needed": "Course budget",
"status": "completed",
"sort_order": 0
}
],
"cycle_name": "Q4 2025 Review"
}

Returns { "goals": [], "cycle_name": "" } if the user has no completed reviews.

List reviews, scoped by access level. Supports filtering.

Permission: view:performance

Query params:

  • cycle_id — filter by cycle
  • status — filter by review status

Create a review for a user in an open cycle. Snapshots the user’s review template KPI items into review_kpi_ratings.

Permission: update:performance

Body:

{
"cycle_id": "cycle-abc",
"user_id": "user-xyz",
"reviewer_id": "user-reviewer"
}
  • reviewer_id defaults to the requesting user if omitted
  • Returns 409 if a review already exists for the user in this cycle

Full review detail with KPI ratings and goals.

Permission: view:performance

Response:

{
"review": {
"id": "review-abc",
"status": "in_review",
"user_name": "Jane Smith",
"reviewer_name": "John Manager",
"cycle_name": "Q1 2026 Review",
"cycle_type": "quarterly",
"kpi_pass_count": null,
"kpi_total_count": null,
"strengths": "...",
"growth_areas": "...",
"discussion_topics": "..."
},
"kpi_ratings": [
{
"id": "kpi-1",
"area": "performance",
"label": "Billable hours target",
"rating": "achieving",
"notes": null,
"sort_order": 0
}
],
"goals": [
{
"id": "goal-1",
"goal": "Complete AI certification",
"success_measures": "Certificate obtained",
"support_needed": "Course budget",
"status": null,
"sort_order": 0
}
],
"previous_reviews": [
{
"review": {
"id": "prev-review-1",
"cycle_name": "Q4 2025 Review",
"reviewer_notes": "Strong quarter.",
"action_items": "Continue AI focus."
},
"kpi_ratings": [{ "template_item_id": "tpl-1", "rating": "achieving" }],
"goals": [{ "id": "goal-old", "goal": "Learn React", "status": "completed" }]
}
],
"kpi_aggregation": null
}

For annual reviews, previous_reviews contains all completed quarterly reviews within the annual period, and kpi_aggregation provides a per-KPI summary:

{
"kpi_aggregation": {
"tpl-item-1": {
"ratings": { "achieving": 3, "exceeding": 1 },
"most_common": "achieving"
}
}
}

PUT /api/performance/reviews/:id/previous-goals

Section titled “PUT /api/performance/reviews/:id/previous-goals”

Update goal outcomes from previous reviews (mark as completed/not completed).

Permission: update:performance

Body:

{
"outcomes": [
{ "goal_id": "goal-old", "status": "completed" },
{ "goal_id": "goal-old-2", "status": "not_completed" }
]
}

GET /api/performance/reviews/history/:userId

Section titled “GET /api/performance/reviews/history/:userId”

Lightweight trend data: completed reviews with KPI pass counts and goal completion counts.

Permission: view:performance

Response:

{
"history": [
{
"review_id": "review-1",
"cycle_id": "cycle-abc",
"cycle_name": "Q1 2026",
"cycle_type": "quarterly",
"period_start": "2026-01-01",
"period_end": "2026-03-31",
"completed_at": "2026-04-01",
"kpi_pass_count": 8,
"kpi_total_count": 10,
"kpi_passed": 1,
"goal_count": 3,
"goals_completed": 2,
"goals_not_completed": 1
}
]
}

Update review fields, KPI ratings, and goals. On status transition to completed, automatically computes KPI pass/fail.

Permission: update:performance

Body:

{
"status": "completed",
"strengths": "Strong delivery...",
"growth_areas": "Could improve...",
"discussion_topics": "Career progression, training budget",
"reviewer_notes": "Solid quarter.",
"kpi_ratings": [
{ "id": "kpi-1", "rating": "achieving", "notes": "Met target" }
],
"goals": [
{ "goal": "AI cert", "success_measures": "Done", "sort_order": 0 }
]
}

Pass/fail logic on completion:

  • Counts KPIs with “achieving” or “exceeding” as passed
  • Checks mandatory items (via review_template_items.is_mandatory)
  • Requires ≥75% pass rate and all mandatory items passed

Delete a draft review only.

Permission: manage:performance

List pending feedback requests assigned to the current user.

Permission: view:performance

Create an individual feedback request.

Permission: update:performance

Body:

{
"cycle_id": "cycle-abc",
"subject_id": "user-xyz",
"reviewer_id": "user-peer",
"due_date": "2026-04-01"
}

POST /api/performance/feedback/requests/bulk

Section titled “POST /api/performance/feedback/requests/bulk”

Auto-select peers for a subject based on their role and create feedback requests.

Permission: update:performance

Body:

{
"cycle_id": "cycle-abc",
"subject_id": "user-xyz",
"due_date": "2026-04-01"
}

Peer selection logic:

  • Employee/Lead: Squad peers
  • Manager: Other managers + direct reports
  • Head/Executive: Other heads + direct manager reports

Response: { "created": 5, "total_peers": 5 }

Submit feedback for a pending request. Marks the request as submitted.

Permission: view:performance

Body:

{
"request_id": "req-abc",
"organisation_rating": "achieving",
"organisation_comment": "Good time management",
"performance_rating": "exceeding",
"performance_comment": "Consistently exceeds targets",
"communication_rating": "achieving",
"development_rating": "achieving",
"automation_rating": "achieving",
"automation_comment": "Great AI adoption",
"overall_comment": "Strong contributor"
}

GET /api/performance/feedback/summary/:userId

Section titled “GET /api/performance/feedback/summary/:userId”

Anonymized aggregate feedback for a user. Manager+ access only.

Permission: view:performance (manager+ access level required)

Query params:

  • cycle_id — optional filter by cycle

Returns { "sufficient": false, "response_count": 0, "minimum_required": 1 } if no responses.

With sufficient responses:

{
"sufficient": true,
"response_count": 5,
"areas": {
"organisation": {
"ratings": { "achieving": 3, "exceeding": 2 },
"comments": ["Good time management", "..."]
}
},
"overall_comments": ["Strong contributor", "..."]
}

Comments are shuffled for anonymity.

Pending action items for the current user.

Permission: view:performance

Response:

{
"pending_reviews": 2,
"self_assessments": 1,
"pending_feedback": 3,
"open_cycles": 1
}