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" }
}
}
typeis one ofINCIDENT,BUG,CHANGE_REQUEST,GENERAL.prioritydefaults toMEDIUMif you omit it.typeMetais keyed by type — only send the block matchingtype. 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" }.
Recommended Hub UX flow
- 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 tomineOnly=true. - Detail view — fetch with
GET /hub/service-requests/:id, render the public timeline (comments + simplified history merged bycreatedAt), and show theticketNumber, currentstatus,priority,assigneeTeam(if set). - 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 toIN_PROGRESS).RESOLVED→ “Confirm & close” (with CSAT), “Reopen”.CLOSED→ “Reopen” (within your reopen window).
- 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”). |