Service Request — Hub Guide

This guide is for Hub integrators. It explains how an organisation user creates and follows a service request from inside the Hub UI.

For the formal API reference, see Service Request Service API. This document is the integration-side spec.

Endpoint summary

Base path /organisation/hub/service-requests (via gateway; internal port 9107)
Auth Authorization: Bearer <accessToken> (the same JWT used elsewhere in the Hub)
Org scoping The server forces organisationId = user.defaultOrganisationId. The Hub never has to send it.
Internal comments Hidden — Hub never sees them.

Prerequisite

The authenticated user must have defaultOrganisationId set. If they don’t, POST /hub/service-requests returns 409 (“User has no default organisation”). The Hub should detect this and either provision the user against an organisation or hide the “Raise a request” entry point.

1. Create a request

POST /hub/service-requests

{
  "type": "BUG",
  "title": "Cannot upload my avatar",
  "description": "Selecting a PNG fails with a 500.",
  "priority": "HIGH",
  "tags": ["avatar"],
  "typeMeta": {
    "bug": { "environment": "PROD", "browser": "Chrome 120" }
  }
}
  • type is one of INCIDENT, BUG, CHANGE_REQUEST, GENERAL.
  • priority defaults to MEDIUM if you omit it.
  • typeMeta is keyed by type — only send the block matching type. Extra blocks are ignored by the schema but rejected by the strict validator, so don’t include them.

Response 201 returns the request including the auto-assigned ticketNumber (e.g. SR-2026-000001). Show this prominently to the user.

2. List the organisation’s requests

GET /hub/service-requests?status=NEW,OPEN,IN_PROGRESS&page=1&pageSize=20&sort=-createdAt

Query param Notes
type Filter to one type.
status Comma-separated.
priority Comma-separated.
tag Exact match.
q Substring search on title/description/ticketNumber.
mineOnly true to restrict to the caller’s own requests.
page, pageSize Pagination (max 100).
sort e.g. -createdAt, priority, -updatedAt.

Internal comments are stripped, and the audit history is reduced to a coarse timeline (action + timestamp only).

3. View a single request

GET /hub/service-requests/:id

A 404 is returned if the request belongs to another organisation — by design indistinguishable from “doesn’t exist”. Don’t surface ID guessing in your UI.

4. Update a request

PATCH /hub/service-requests/:id

Editable only by the original requester, and only while the status is NEW, OPEN, REOPENED, or PENDING_CUSTOMER. Otherwise the API returns 403 or 409.

Editable fields: title, description, category, subCategory, tags, typeMeta.

5. Comment

POST /hub/service-requests/:id/comments

{ "body": "Still happening today on Firefox too." }

All Hub comments are public. They appear in the admin’s view immediately.

6. Attach a file

POST /hub/service-requests/:id/attachments — multipart, field name file. Max 10 MB. Allowed: images, PDFs, text, CSV, JSON, ZIP, Office docs.

7. Cancel

POST /hub/service-requests/:id/cancel — only the requester, only while NEW or OPEN. Optional body: { "note": "no longer needed" }.

8. Confirm resolution (with optional CSAT)

When the admin moves a ticket to RESOLVED, the customer sees a “confirm and close” affordance:

POST /hub/service-requests/:id/confirm-resolution
{ "rating": 5, "comment": "Quick fix, thanks!" }

Both fields are optional. The status moves to CLOSED and closedAt is stamped. The CSAT is stored on customerSatisfactionRating / customerSatisfactionComment.

9. Reopen

POST /hub/service-requests/:id/reopen — for RESOLVED or CLOSED requests. Increments reopenCount, clears resolvedAt and closedAt. Optional { "note": "issue is back after the deploy" }.

  1. List view — the user lands on a list filtered to status ∈ {NEW, OPEN, IN_PROGRESS, PENDING_CUSTOMER, ON_HOLD, REOPENED} sorted -createdAt. Toggle “Mine only” maps to mineOnly=true.
  2. Detail view — fetch with GET /hub/service-requests/:id, render the public timeline (comments + simplified history merged by createdAt), and show the ticketNumber, current status, priority, assigneeTeam (if set).
  3. Action buttons vary by status:
    • NEW / OPEN → Edit, Cancel, Add comment, Add attachment.
    • PENDING_CUSTOMER → Add comment (replying typically prompts the admin to move it back to IN_PROGRESS).
    • RESOLVED → “Confirm & close” (with CSAT), “Reopen”.
    • CLOSED → “Reopen” (within your reopen window).
  4. Notifications — the platform sends an email on creation, status change, and assignee change. The Hub doesn’t have to poll for updates, but a refresh on the detail view is recommended after every user action.

Errors to handle

Status UX action
400 Show inline validation error (response.message + optional errors[]).
401 Re-auth flow.
403 “Only the requester can perform this action.”
404 “Request not found.” (Includes “exists in another org” — don’t leak.)
409 Show response.message (e.g. “Status is already RESOLVED” or “Cannot edit request in status IN_PROGRESS”).