Service Request — Admin Guide

This guide is for the Admin Portal. It walks through the full support lifecycle: triage, assignment, status transitions, internal collaboration, change-request approval, and reporting.

The formal API reference lives in Service Request Service API. This document covers how to use those endpoints from the Admin Portal point of view.

Who this is for

Any user with isAdmin === true. The platform validates admin status server-side on every /admin/service-requests/* call; non-admins receive 403.

Lifecycle overview

NEW ─► OPEN ─► IN_PROGRESS ⇄ PENDING_CUSTOMER ⇄ ON_HOLD
                  │
                  ▼
              RESOLVED ─► CLOSED
                  │
                  └─► REOPENED ─► IN_PROGRESS

Cancellation is admin-only once a ticket is past OPEN. CLOSED can only be reached after RESOLVED. REOPENED bumps reopenCount.

1. Creating a request

Use POST /admin/service-requests when:

  • A customer reaches you outside the Hub (email, phone, chat) — set source to EMAIL / PHONE / API and supply organisationId + onBehalfOfUserId if known.
  • You need to file an internal ticket not tied to any organisation — leave organisationId and onBehalfOfUserId null. The platform records requesterType: ADMIN_ON_BEHALF automatically when either field is populated.

Always pick the right type at creation — it determines which typeMeta block applies and gates change-request approvals later.

2. Triage

Right after creation, set:

  • priority (operational urgency for the team) and, optionally, separate severity + urgency + impact if your team uses ITIL-style scoring.
  • category / subCategory for reporting.
  • tags for search/filter.
  • dueAt to set the SLA target. The slaBreached flag is computed downstream.

Use PATCH /admin/service-requests/:id for any of these. Each change is appended to the history with the actor and old/new values.

3. Assignment

Use POST /admin/service-requests/:id/assign. You can set assigneeId, assigneeTeam, or both. The new assignee receives an email notification (template: AssigneeNotification). Hand-offs (re-assigning) are first-class — every assignment is logged in history.

4. Working the ticket

Move through statuses with POST /admin/service-requests/:id/status:

From Common next steps
NEW OPEN (acknowledged) or IN_PROGRESS (immediately picked up)
OPEN IN_PROGRESS, PENDING_CUSTOMER (waiting on requester), ON_HOLD
IN_PROGRESS PENDING_CUSTOMER, ON_HOLD, RESOLVED
PENDING_CUSTOMER IN_PROGRESS (customer replied), ON_HOLD, RESOLVED
RESOLVED CLOSED (auto on customer confirm) or REOPENED

The endpoint validates allowed transitions and returns 409 with a reason if you try an illegal one. RESOLVED and CLOSED automatically stamp resolvedAt / closedAt.

5. Communication

  • Public reply to the customer: POST /admin/service-requests/:id/comments with isInternal: false. The first such comment sets firstResponseAt (used for SLA reporting).
  • Internal note for your team: same endpoint with isInternal: true. Never visible to the Hub.
  • List comments: GET /admin/service-requests/:id/comments (returns both internal and public).
  • Attachments: multipart POST /admin/service-requests/:id/attachments (field name file, max 10 MB). Useful for screenshots, logs, postmortems.

6. Change requests

For CHANGE_REQUEST tickets, fill out typeMeta.change (proposedChange, justification, riskLevel, rollbackPlan, plannedStartAt/EndAt) via PATCH. Then:

  • POST /admin/service-requests/:id/approve-change with { "decision": "APPROVED" | "REJECTED", "note": "…" }.
  • The endpoint sets typeMeta.change.approvalStatus, approverId, approvedAt, approvalNote.
  • Only CHANGE_REQUEST tickets accept this call (others return 409).

After approval, move the ticket to IN_PROGRESS to start execution.

7. Reporting

GET /admin/service-requests/stats — counts by status, type, priority plus total and SLA-breach count. Accepts optional organisationId and assigneeId filters. Use this for dashboards and team workload views.

For per-row drill-down, GET /admin/service-requests supports filters (status, priority, organisationId, assigneeId, date range, free-text q) and pagination.

8. Audit trail

Every mutating call (status change, edit, assign, comment, attachment, change-decision) appends a history entry. Read it with GET /admin/service-requests/:id/history. Use this to investigate disputes or to build incident postmortems.

9. Soft delete

DELETE /admin/service-requests/:id sets deletedAt; the request stops appearing in default lists. Pass ?includeDeleted=true to GET /admin/service-requests to see soft-deleted items. There is intentionally no undelete API — do that via DB if absolutely required.

Tips

  • Keep internal comments truly internal — don’t paste customer-facing language; the Hub user will never see them.
  • Use tags consistently; they’re the cheapest way to slice reports.
  • For incidents, fill typeMeta.incident.rootCause and postMortemUrl before closing — these become your searchable knowledge base.
  • For BUGs, capture stepsToReproduce exactly as the customer reported them so engineering doesn’t have to ping you.