Shop It Docs
Developer ResourcesSupport

Support Module API & Integration Guide

REST and websocket contracts for support inquiries, support requests, feedback, and realtime support.

Audience: Web/mobile/admin frontend developers Scope: Support inquiries, support requests, feedback, realtime chat, email verification, and admin conversion flows

Support Module - API & Integration Guide

1. How to Read / Quick Metadata

  • Module: Support
  • Response envelope: successful endpoints return ResponseDto<T>
  • Primary REST base URLs:
    • Public/customer inquiries: /api/support-inquiries
    • Admin inquiries: /api/admin/support-inquiries
    • Mobile support requests: /api/mobile/support-requests
    • Admin support requests: /api/admin/support-requests
    • Mobile feedback: /api/mobile/feedback
    • Admin feedback: /api/admin/feedback
  • Primary websocket namespace: configured by WS_NAMESPACE, default /realtime
  • Guest inquiry auth: Authorization: Bearer si_...
  • Customer/admin auth: Authorization: Bearer <jwt>

2. High-Level Overview

Support API is split into:

  • public/customer inquiry endpoints for homepage live chat and inquiry capture
  • admin inquiry endpoints for staff handling and support ticket conversion
  • mobile support request endpoints for authenticated customer tickets
  • admin support request endpoints for staff ticket handling
  • mobile feedback endpoint for one-way feedback submission
  • admin feedback endpoints for review workflows
  • websocket events for support request and support inquiry message deltas

REST remains the source of truth for full state. Websocket is the live delta and replay layer.

3. Auth Models

SurfaceAuth
POST /api/support-inquiriesOptional customer JWT or guest
GET /api/support-inquiriesCustomer JWT
GET/POST/PATCH /api/support-inquiries/:id...Customer JWT or guest si_... token
/api/admin/support-inquiriesAdmin JWT + admin actor + role permission
/api/mobile/support-requestsCustomer JWT
/api/admin/support-requestsAdmin JWT + admin actor + role permission
/api/mobile/feedbackCustomer JWT
/api/admin/feedbackAdmin JWT + admin actor + role permission
support request websocket roomAdmin JWT or owning customer JWT
support inquiry websocket roomAdmin JWT, owning customer JWT, or matching guest si_... token

4. Core Concepts and Terminology

  • support inquiry: guest/customer chat-style record with tracking code and optional customer link
  • inquiry access token: raw si_... bearer token returned only to guests on inquiry creation
  • tracking code: public inquiry reference such as INQ-8K4P2X
  • system greeting: automatic first inquiry message created by the backend
  • email verification: OTP flow that allows safe customer linking after a guest provides email
  • support request: authenticated customer support ticket
  • feedback submission: one-way customer feedback item for admin review
  • room: websocket subscription target for support message events
  • event envelope: realtime payload wrapper containing eventId, eventType, occurredAt, and data

5. Route Summary

5.1 Public / Customer Support Inquiries

MethodPathAuth
POST/api/support-inquiriesOptional customer JWT or guest
GET/api/support-inquiriesCustomer JWT
GET/api/support-inquiries/:idCustomer JWT or guest inquiry token
GET/api/support-inquiries/:id/messagesCustomer JWT or guest inquiry token
POST/api/support-inquiries/:id/messagesCustomer JWT or guest inquiry token
PATCH/api/support-inquiries/:id/identifyCustomer JWT or guest inquiry token
POST/api/support-inquiries/:id/verify-email/requestCustomer JWT or guest inquiry token
POST/api/support-inquiries/:id/verify-email/confirmCustomer JWT or guest inquiry token

5.2 Admin Support Inquiries

MethodPathPermission
GET/api/admin/support-inquiriesSupportInquiries_READ
GET/api/admin/support-inquiries/:idSupportInquiries_READ
POST/api/admin/support-inquiries/:id/messagesSupportInquiries_UPDATE
PATCH/api/admin/support-inquiries/:id/assignSupportInquiries_UPDATE
PATCH/api/admin/support-inquiries/:id/statusSupportInquiries_UPDATE
POST/api/admin/support-inquiries/:id/link-support-requestSupportInquiries_UPDATE

5.3 Mobile Support Requests

MethodPathAuth
POST/api/mobile/support-requestsCustomer JWT
GET/api/mobile/support-requestsCustomer JWT
GET/api/mobile/support-requests/:idCustomer JWT
POST/api/mobile/support-requests/:id/messagesCustomer JWT

5.4 Admin Support Requests

MethodPathPermission
GET/api/admin/support-requestsSupportRequests_READ
GET/api/admin/support-requests/:idSupportRequests_READ
PATCH/api/admin/support-requests/:id/statusSupportRequests_UPDATE
PATCH/api/admin/support-requests/:id/assignSupportRequests_UPDATE
POST/api/admin/support-requests/:id/messagesSupportRequests_UPDATE

5.5 Feedback

MethodPathAuth / Permission
POST/api/mobile/feedbackCustomer JWT
GET/api/admin/feedbackFeedback_READ
GET/api/admin/feedback/:idFeedback_READ
PATCH/api/admin/feedback/:id/reviewFeedback_UPDATE

6. Support Inquiry Endpoint Details

6.1 Create inquiry

AspectDetails
EndpointPOST /api/support-inquiries
AuthOptional customer JWT or guest
Body DTOCreateSupportInquiryDto
Success DTOCreateSupportInquiryResponseDto
Rate limitIpThrottlerGuard

Request body:

{
  "category": "product",
  "subject": "Question about a thangka painting",
  "message": "Is this piece available in a larger size?",
  "guestName": "Alex Customer",
  "guestEmail": "alex@example.com",
  "guestPhone": "+9779800000000"
}

Response body for guest-created inquiry:

{
  "message": "Support inquiry created successfully",
  "data": {
    "id": 10,
    "trackingCode": "INQ-8K4P2X",
    "customerId": null,
    "guestEmail": "alex@example.com",
    "category": "product",
    "subject": "Question about a thangka painting",
    "status": "open",
    "assignedAdminId": null,
    "supportRequestId": null,
    "lastVisitorMessageAt": "2026-06-04T10:01:00.000Z",
    "lastAdminMessageAt": null,
    "createdAt": "2026-06-04T10:00:00.000Z",
    "updatedAt": "2026-06-04T10:01:00.000Z",
    "guestName": "Alex Customer",
    "guestPhone": "+9779800000000",
    "emailVerifiedAt": null,
    "closedAt": null,
    "messages": [
      {
        "id": 100,
        "supportInquiryId": 10,
        "authorType": "system",
        "authorCustomerId": null,
        "authorAdminId": null,
        "authorName": "System",
        "authorImage": null,
        "body": "Hi, how can we help? You can leave your email so we can follow up.",
        "createdAt": "2026-06-04T10:00:00.000Z"
      },
      {
        "id": 101,
        "supportInquiryId": 10,
        "authorType": "guest",
        "authorCustomerId": null,
        "authorAdminId": null,
        "authorName": "Alex Customer",
        "authorImage": null,
        "body": "Is this piece available in a larger size?",
        "createdAt": "2026-06-04T10:01:00.000Z"
      }
    ],
    "inquiryAccessToken": "si_9f5e1c25b0f4475db9f17be7a8c3a123"
  }
}

Authenticated customer behavior:

  • request uses customer JWT
  • customerId is set
  • inquiryAccessToken is not returned

6.2 List current customer's inquiries

AspectDetails
EndpointGET /api/support-inquiries
AuthCustomer JWT
Query DTOQuerySupportInquiriesDto
Success DTOSupportInquiryListItemResponseDto[] paginated

Query params:

ParamTypeDefaultNotes
pagenumber1inherited from QueryDto
sizenumber20inherited from QueryDto
paginationbooleantrueset false for unpaginated
statusinquiry statusoptionalfilters status
categoryinquiry categoryoptionalfilters category
sortcreatedAt or updatedAtupdatedAtsort field
orderasc or descdescinherited from QueryDto

Guest users do not list inquiries. Guests fetch detail/messages by id with Bearer si_....

6.3 Get inquiry detail

AspectDetails
EndpointGET /api/support-inquiries/:id
AuthCustomer JWT or guest inquiry token
Paramsid integer
Success DTOSupportInquiryDetailResponseDto

Guest header:

Authorization: Bearer si_9f5e1c25b0f4475db9f17be7a8c3a123

Access rules:

  • customer can access only inquiries linked to their customerId
  • guest token can access only its own inquiry
  • admin uses admin inquiry endpoints instead

6.4 Get inquiry messages

AspectDetails
EndpointGET /api/support-inquiries/:id/messages
AuthCustomer JWT or guest inquiry token
Success DTOSupportInquiryMessageResponseDto[]

Messages are returned in chronological order.

6.5 Add inquiry message

AspectDetails
EndpointPOST /api/support-inquiries/:id/messages
AuthCustomer JWT or guest inquiry token
Body DTOCreateSupportInquiryMessageDto
Success DTOSupportInquiryDetailResponseDto
Rate limitIpThrottlerGuard

Request body:

{
  "body": "I would like to know shipping time to Kathmandu."
}

Rules:

  • body is trimmed and must be non-blank
  • closed/spam inquiries reject new messages
  • write emits support.inquiry_message.created

6.6 Identify guest contact

AspectDetails
EndpointPATCH /api/support-inquiries/:id/identify
AuthCustomer JWT or guest inquiry token
Body DTOIdentifySupportInquiryDto
Success DTOSupportInquiryDetailResponseDto
Rate limitIpThrottlerGuard

Request body:

{
  "guestName": "Alex Customer",
  "guestEmail": "alex@example.com",
  "guestPhone": "+9779800000000"
}

Rules:

  • email is normalized to lowercase
  • existing customer match is not disclosed
  • identity is not linked until verification succeeds or user logs in

6.7 Request email verification

AspectDetails
EndpointPOST /api/support-inquiries/:id/verify-email/request
AuthCustomer JWT or guest inquiry token
Bodynone
Success DTOgeneric response
Rate limitIpThrottlerGuard

Success response:

{
  "message": "Support inquiry verification code sent",
  "data": {
    "sent": true
  }
}

Security behavior:

  • response does not reveal whether email exists in customer table
  • frontend should show "If this email can receive messages, a code has been sent"

6.8 Confirm email verification

AspectDetails
EndpointPOST /api/support-inquiries/:id/verify-email/confirm
AuthCustomer JWT or guest inquiry token
Body DTOConfirmSupportInquiryEmailDto
Success DTOSupportInquiryDetailResponseDto
Rate limitIpThrottlerGuard

Request body:

{
  "otp": "123456"
}

Rules:

  • OTP length must be 4 to 12 characters
  • successful verification sets emailVerifiedAt
  • if verified email belongs to a customer, inquiry links to that customerId
  • if email does not belong to a customer, inquiry remains a verified guest contact

7. Admin Inquiry Endpoint Details

7.1 Admin list inquiries

AspectDetails
EndpointGET /api/admin/support-inquiries
AuthAdmin JWT
PermissionSupportInquiries_READ
Query DTOQuerySupportInquiriesAdminDto
Success DTOSupportInquiryListItemResponseDto[] paginated

Query params:

ParamTypeDefaultNotes
pagenumber1inherited from QueryDto
sizenumber20inherited from QueryDto
paginationbooleantruecan be false
statusinquiry statusoptionalfilters by status
categoryinquiry categoryoptionalfilters by category
customerIduuidoptionalfilters linked customer
assignedAdminIduuidoptionalfilters assignee
supportRequestIdintegeroptionalfilters linked ticket
searchstringoptionaltracking code, subject, guest contact
sortcreatedAt or updatedAtupdatedAtsort field
orderasc or descdescinherited from QueryDto

Search examples:

RequestNotes
GET /api/admin/support-inquiries?search=INQ-8K4P2Xtracking code lookup
GET /api/admin/support-inquiries?search=alex@example.comguest email lookup
GET /api/admin/support-inquiries?status=open&category=productactive triage
GET /api/admin/support-inquiries?supportRequestId=24linked inquiry lookup

7.2 Admin get inquiry detail

AspectDetails
EndpointGET /api/admin/support-inquiries/:id
PermissionSupportInquiries_READ
Success DTOSupportInquiryDetailResponseDto

Admin detail includes:

  • guest contact fields
  • linked customerId
  • linked supportRequestId
  • assigned admin id
  • full chronological message history

7.3 Admin add inquiry reply

AspectDetails
EndpointPOST /api/admin/support-inquiries/:id/messages
PermissionSupportInquiries_UPDATE
Body DTOCreateAdminSupportInquiryMessageDto
Success DTOSupportInquiryDetailResponseDto

Request body:

{
  "body": "Thanks, we are checking availability and will update you shortly."
}

Side effects:

  • writes admin message
  • updates lastAdminMessageAt
  • emits support.inquiry_message.created
  • records admin activity

7.4 Admin assign inquiry

AspectDetails
EndpointPATCH /api/admin/support-inquiries/:id/assign
PermissionSupportInquiries_UPDATE
Body DTOAssignSupportInquiryDto
Success DTOSupportInquiryDetailResponseDto

Assign:

{
  "assignedAdminId": "019d2c3e-3ca0-76ae-83ba-53e81e74eed1"
}

Unassign:

{
  "assignedAdminId": null
}

7.5 Admin update inquiry status

AspectDetails
EndpointPATCH /api/admin/support-inquiries/:id/status
PermissionSupportInquiries_UPDATE
Body DTOUpdateSupportInquiryStatusDto
Success DTOSupportInquiryDetailResponseDto

Request body:

{
  "status": "resolved"
}

Allowed statuses:

  • open
  • active
  • waiting
  • linked
  • resolved
  • closed
  • spam

7.6 Admin link/create support request from inquiry

AspectDetails
EndpointPOST /api/admin/support-inquiries/:id/link-support-request
PermissionSupportInquiries_UPDATE
Body DTOLinkSupportInquiryRequestDto
Success DTOSupportInquiryDetailResponseDto

Create new support request:

{
  "subject": "Question about a thangka painting"
}

Link existing support request:

{
  "supportRequestId": 24
}

Rules:

  • inquiry must have customerId
  • existing support request must belong to same customer
  • if new request is created, non-system inquiry messages are copied into ticket history
  • inquiry status becomes linked

8. Support Request Endpoint Details

8.1 Mobile create support request

AspectDetails
EndpointPOST /api/mobile/support-requests
AuthCustomer JWT
Body DTOCreateSupportRequestDto
Success DTOSupportRequestDetailResponseDto

Request body:

{
  "category": "technical",
  "subject": "App crashes on checkout",
  "message": "I cannot complete checkout on Android."
}

Categories:

  • account
  • payment
  • technical
  • other

8.2 Mobile list support requests

AspectDetails
EndpointGET /api/mobile/support-requests
AuthCustomer JWT
Query DTOQuerySupportRequestsDto
Success DTOSupportRequestListItemResponseDto[] paginated

Only the current customer's requests are returned.

8.3 Mobile get support request detail

AspectDetails
EndpointGET /api/mobile/support-requests/:id
AuthCustomer JWT
Success DTOSupportRequestDetailResponseDto

Mobile detail includes:

  • category
  • subject
  • status
  • assignment boolean (isAssigned)
  • resolution metadata
  • chronological messages

8.4 Mobile add support request reply

AspectDetails
EndpointPOST /api/mobile/support-requests/:id/messages
AuthCustomer JWT
Body DTOCreateSupportRequestMessageDto
Success DTOSupportRequestDetailResponseDto

Request body:

{
  "body": "Here is more detail about the issue."
}

Rules:

  • closed requests reject replies
  • resolved requests reopen to open
  • write emits support.request_message.created

8.5 Admin support request list

AspectDetails
EndpointGET /api/admin/support-requests
PermissionSupportRequests_READ
Query DTOQuerySupportRequestsAdminDto
Success DTOSupportRequestListItemResponseDto[] paginated

Query params:

ParamTypeNotes
statusopen, in_progress, resolved, closedoptional
categoryaccount, payment, technical, otheroptional
customerIduuidoptional
assignedAdminIduuidoptional
searchstringsubject match
page, size, pagination, sort, orderinheritedstandard pagination

8.6 Admin support request detail

AspectDetails
EndpointGET /api/admin/support-requests/:id
PermissionSupportRequests_READ
Success DTOSupportRequestDetailResponseDto

Admin detail includes internal author IDs and full message history.

8.7 Admin update support request status

AspectDetails
EndpointPATCH /api/admin/support-requests/:id/status
PermissionSupportRequests_UPDATE
Body DTOUpdateSupportRequestStatusDto
Success DTOSupportRequestDetailResponseDto

Request body:

{
  "status": "resolved",
  "resolutionNote": "Customer confirmed the issue is fixed."
}

Rules:

  • resolutionNote is allowed only for resolved or closed
  • status updates record admin activity

8.8 Admin assign support request

AspectDetails
EndpointPATCH /api/admin/support-requests/:id/assign
PermissionSupportRequests_UPDATE
Body DTOAssignSupportRequestDto
Success DTOSupportRequestDetailResponseDto

Request body:

{
  "assignedAdminId": "019d2c3e-3ca0-76ae-83ba-53e81e74eed1"
}

Use null to clear assignment.

8.9 Admin add support request reply

AspectDetails
EndpointPOST /api/admin/support-requests/:id/messages
PermissionSupportRequests_UPDATE
Body DTOCreateAdminSupportRequestMessageDto
Success DTOSupportRequestDetailResponseDto

Request body:

{
  "body": "Thanks, we are looking into it."
}

Side effects:

  • writes admin message
  • emits support.request_message.created
  • notifies customer
  • records admin activity

9. Feedback Endpoint Details

9.1 Mobile submit feedback

AspectDetails
EndpointPOST /api/mobile/feedback
AuthCustomer JWT
Body DTOCreateFeedbackSubmissionDto
Success DTOFeedbackSubmissionResponseDto

Request body:

{
  "category": "bug_report",
  "subject": "Search is broken",
  "message": "The search screen shows a blank result set."
}

Categories:

  • bug_report
  • feature_request
  • general_feedback

9.2 Admin list feedback

AspectDetails
EndpointGET /api/admin/feedback
PermissionFeedback_READ
Query DTOQueryFeedbackSubmissionsAdminDto
Success DTOFeedbackSubmissionListItemResponseDto[] paginated

Query params:

ParamTypeNotes
statusnew or reviewedoptional
categoryfeedback categoryoptional
customerIduuidoptional
searchstringsubject/message/customer search depending service implementation
sortcreatedAt or updatedAtdefault updatedAt

9.3 Admin feedback detail

AspectDetails
EndpointGET /api/admin/feedback/:id
PermissionFeedback_READ
Success DTOFeedbackSubmissionResponseDto

9.4 Admin review feedback

AspectDetails
EndpointPATCH /api/admin/feedback/:id/review
PermissionFeedback_UPDATE
Bodynone
Success DTOFeedbackSubmissionResponseDto

Side effects:

  • sets status to reviewed
  • sets reviewedByAdminId
  • sets reviewedAt
  • records activity

10. DTO Field Reference

10.1 CreateSupportInquiryDto

FieldTypeRequiredValidationNotes
categoryenumNoinquiry categorydefaults to other
subjectstringYes1-255 chars, trimmedinquiry subject
messagestringNonon-blank when present, trimmedinitial message
guestNamestringNomax 255, trimmedguest display/contact name
guestEmailemailNomax 320, lowercasedcontact email, not identity proof
guestPhonestringNomax 32, trimmedcontact phone

10.2 IdentifySupportInquiryDto

FieldTypeRequiredValidationNotes
guestNamestringNomax 255update guest contact name
guestEmailemailNomax 320update guest email
guestPhonestringNomax 32update guest phone

10.3 CreateSupportInquiryMessageDto

FieldTypeRequiredValidationNotes
bodystringYesnon-blank after triminquiry message body

10.4 ConfirmSupportInquiryEmailDto

FieldTypeRequiredValidationNotes
otpstringYes4-12 charsverification code

10.5 LinkSupportInquiryRequestDto

FieldTypeRequiredValidationNotes
supportRequestIdintegerNomin 1link existing ticket
subjectstringNomax 255subject for new ticket creation

10.6 Support request DTOs

DTOFields
CreateSupportRequestDtocategory, subject, message
CreateSupportRequestMessageDtobody
UpdateSupportRequestStatusDtostatus, resolutionNote?
AssignSupportRequestDto`assignedAdminId?: string

10.7 Feedback DTOs

DTOFields
CreateFeedbackSubmissionDtocategory, subject, message
QueryFeedbackSubmissionsAdminDtostatus?, category?, customerId?, search?, pagination/sort

11. Response Shape Examples

11.1 Support inquiry list item

{
  "id": 10,
  "trackingCode": "INQ-8K4P2X",
  "customerId": "019d2c3e-3ca0-76ae-83ba-53e81e74eed1",
  "guestEmail": "alex@example.com",
  "category": "product",
  "subject": "Question about a thangka painting",
  "status": "active",
  "assignedAdminId": "019d2c3e-3ca0-76ae-83ba-53e81e74eed1",
  "supportRequestId": null,
  "lastVisitorMessageAt": "2026-06-04T10:05:00.000Z",
  "lastAdminMessageAt": "2026-06-04T10:06:00.000Z",
  "createdAt": "2026-06-04T10:00:00.000Z",
  "updatedAt": "2026-06-04T10:06:00.000Z"
}

11.2 Support request detail

{
  "id": 1,
  "customerId": "019d2c3e-3ca0-76ae-83ba-53e81e74eed1",
  "category": "technical",
  "subject": "App crashes on checkout",
  "status": "in_progress",
  "assignedAdminId": "019d2c3e-3ca0-76ae-83ba-53e81e74eed1",
  "resolutionNote": null,
  "resolvedAt": null,
  "closedAt": null,
  "lastCustomerMessageAt": "2026-03-17T10:05:00.000Z",
  "lastAdminMessageAt": "2026-03-17T10:06:00.000Z",
  "messages": [
    {
      "id": 10,
      "supportRequestId": 1,
      "authorType": "customer",
      "authorCustomerId": "019d2c3e-3ca0-76ae-83ba-53e81e74eed1",
      "authorAdminId": null,
      "authorName": "Alex Customer",
      "authorImage": "https://cdn.example.com/customer.png",
      "body": "App crashes on checkout.",
      "createdAt": "2026-03-17T10:04:00.000Z"
    }
  ],
  "createdAt": "2026-03-17T10:00:00.000Z",
  "updatedAt": "2026-03-17T10:06:00.000Z"
}

11.3 Feedback response

{
  "id": 1,
  "customerId": "019d2c3e-3ca0-76ae-83ba-53e81e74eed1",
  "category": "bug_report",
  "subject": "Search is broken",
  "message": "The search screen shows a blank result set.",
  "status": "new",
  "reviewedByAdminId": null,
  "reviewedAt": null,
  "createdAt": "2026-06-04T10:00:00.000Z",
  "updatedAt": "2026-06-04T10:00:00.000Z"
}

12. Enums

12.1 Support inquiry categories

  • account
  • payment
  • technical
  • product
  • order
  • other

12.2 Support inquiry statuses

  • open
  • active
  • waiting
  • linked
  • resolved
  • closed
  • spam

12.3 Support inquiry message author types

  • guest
  • customer
  • admin
  • system

12.4 Support request categories

  • account
  • payment
  • technical
  • other

12.5 Support request statuses

  • open
  • in_progress
  • resolved
  • closed

12.6 Support request message author types

  • customer
  • admin

12.7 Feedback categories

  • bug_report
  • feature_request
  • general_feedback

12.8 Feedback statuses

  • new
  • reviewed

13. Websocket Integration

13.1 Connection auth

Customer/admin JWT:

Authorization: Bearer <jwt>

Guest inquiry token:

Authorization: Bearer si_9f5e1c25b0f4475db9f17be7a8c3a123

The realtime auth guard recognizes si_... tokens and creates a guest support inquiry actor for inquiry-room authorization.

13.2 Client events

EventPayloadNotes
support:join_request_messages{ "supportRequestId": 1 }join ticket room
support:leave_request_messages{ "supportRequestId": 1 }leave ticket room
support:sync_request_messages{ "supportRequestId": 1, "sinceEventId": "...", "limit": 50 }replay ticket events
support:join_inquiry_messages{ "supportInquiryId": 10 }join inquiry room
support:leave_inquiry_messages{ "supportInquiryId": 10 }leave inquiry room
support:sync_inquiry_messages{ "supportInquiryId": 10, "sinceEventId": "...", "limit": 50 }replay inquiry events

13.3 Join response examples

Support request room:

{
  "ok": true,
  "data": {
    "supportRequestId": 1,
    "room": "support:request:1:messages",
    "roomSize": 2
  }
}

Support inquiry room:

{
  "ok": true,
  "data": {
    "supportInquiryId": 10,
    "trackingCode": "INQ-8K4P2X",
    "room": "support:inquiry:10:messages",
    "roomSize": 2
  }
}

13.4 Server event envelope

{
  "eventId": "019d2c3e-3ca0-76ae-83ba-53e81e74eed1",
  "eventType": "support.inquiry_message.created",
  "occurredAt": "2026-06-04T10:06:00.000Z",
  "data": {
    "supportInquiryId": 10,
    "trackingCode": "INQ-8K4P2X",
    "messageId": 102,
    "authorType": "admin",
    "authorCustomerId": null,
    "authorAdminId": "019d2c3e-3ca0-76ae-83ba-53e81e74eed1",
    "body": "Thanks, we are checking availability.",
    "createdAt": "2026-06-04T10:06:00.000Z",
    "actor": {
      "type": "ADMIN",
      "id": "019d2c3e-3ca0-76ae-83ba-53e81e74eed1"
    }
  }
}

13.5 Sync response

{
  "ok": true,
  "data": {
    "room": "support:inquiry:10:messages",
    "events": [],
    "replayedCount": 0,
    "gapDetected": false
  }
}

Reconnect recipe:

  1. Reconnect socket.
  2. Rejoin every visible support room.
  3. Call sync event with last processed eventId.
  4. Deduplicate events by eventId.
  5. If gapDetected is true, refetch REST detail/messages.

14. Integration Diagrams

14.1 Guest inquiry from homepage chat

14.2 Inquiry verification and conversion

14.3 Support request ticket flow

15. Endpoint Reference + Payload Cheatsheet

15.1 Every REST endpoint

MethodPathAuth / PermissionRequest DTO / ParamsSuccess DTONotes
POST/api/support-inquiriesoptional JWT or guestCreateSupportInquiryDtoCreateSupportInquiryResponseDtocreates inquiry, greeting, optional first message, guest token
GET/api/support-inquiriescustomer JWTQuerySupportInquiriesDtoSupportInquiryListItemResponseDto[] paginatedcurrent customer's linked inquiries only
GET/api/support-inquiries/:idcustomer JWT or si_...path id intSupportInquiryDetailResponseDtovalidates ownership/token
GET/api/support-inquiries/:id/messagescustomer JWT or si_...path id intSupportInquiryMessageResponseDto[]chronological messages
POST/api/support-inquiries/:id/messagescustomer JWT or si_...body bodySupportInquiryDetailResponseDtoemits inquiry websocket event
PATCH/api/support-inquiries/:id/identifycustomer JWT or si_...guest name/email/phoneSupportInquiryDetailResponseDtostores contact, does not prove identity
POST/api/support-inquiries/:id/verify-email/requestcustomer JWT or si_...nonegeneric responsesends OTP without account enumeration
POST/api/support-inquiries/:id/verify-email/confirmcustomer JWT or si_...otpSupportInquiryDetailResponseDtoverifies email and links customer if matched
GET/api/admin/support-inquiriesSupportInquiries_READadmin querySupportInquiryListItemResponseDto[] paginatedadmin triage/search
GET/api/admin/support-inquiries/:idSupportInquiries_READpath id intSupportInquiryDetailResponseDtoadmin detail
POST/api/admin/support-inquiries/:id/messagesSupportInquiries_UPDATEbodySupportInquiryDetailResponseDtoadmin reply + realtime + activity
PATCH/api/admin/support-inquiries/:id/assignSupportInquiries_UPDATEassignedAdminIdSupportInquiryDetailResponseDtoassign/unassign inquiry
PATCH/api/admin/support-inquiries/:id/statusSupportInquiries_UPDATEstatusSupportInquiryDetailResponseDtoupdate inquiry lifecycle
POST/api/admin/support-inquiries/:id/link-support-requestSupportInquiries_UPDATEsupportRequestId?, subject?SupportInquiryDetailResponseDtolink/create ticket after verified customer
POST/api/mobile/support-requestscustomer JWTcategory, subject, messageSupportRequestDetailResponseDtocreate authenticated ticket
GET/api/mobile/support-requestscustomer JWTquery filtersSupportRequestListItemResponseDto[] paginatedcurrent customer only
GET/api/mobile/support-requests/:idcustomer JWTpath id intSupportRequestDetailResponseDtovalidates ownership
POST/api/mobile/support-requests/:id/messagescustomer JWTbodySupportRequestDetailResponseDtocustomer reply + realtime
GET/api/admin/support-requestsSupportRequests_READadmin querySupportRequestListItemResponseDto[] paginatedadmin ticket list
GET/api/admin/support-requests/:idSupportRequests_READpath id intSupportRequestDetailResponseDtoadmin ticket detail
PATCH/api/admin/support-requests/:id/statusSupportRequests_UPDATEstatus, resolutionNote?SupportRequestDetailResponseDtostatus update + activity
PATCH/api/admin/support-requests/:id/assignSupportRequests_UPDATEassignedAdminIdSupportRequestDetailResponseDtoassign/unassign
POST/api/admin/support-requests/:id/messagesSupportRequests_UPDATEbodySupportRequestDetailResponseDtoadmin reply + notification + realtime
POST/api/mobile/feedbackcustomer JWTcategory, subject, messageFeedbackSubmissionResponseDtoone-way feedback
GET/api/admin/feedbackFeedback_READadmin queryFeedbackSubmissionListItemResponseDto[] paginatedreview queue
GET/api/admin/feedback/:idFeedback_READpath id intFeedbackSubmissionResponseDtofeedback detail
PATCH/api/admin/feedback/:id/reviewFeedback_UPDATEnoneFeedbackSubmissionResponseDtomark reviewed

15.2 Websocket event cheatsheet

DirectionEventPayloadResponse/Event
client -> serversupport:join_request_messages{ supportRequestId }join ack with room
client -> serversupport:leave_request_messages{ supportRequestId }leave ack
client -> serversupport:sync_request_messages{ supportRequestId, sinceEventId?, limit? }replay events
server -> clientsupport.request_message.createdevent envelopemessage delta
client -> serversupport:join_inquiry_messages{ supportInquiryId }join ack with room + trackingCode
client -> serversupport:leave_inquiry_messages{ supportInquiryId }leave ack
client -> serversupport:sync_inquiry_messages{ supportInquiryId, sinceEventId?, limit? }replay events
server -> clientsupport.inquiry_message.createdevent envelopemessage delta

16. Query Variation Examples

16.1 Customer inquiries

RequestNotes
GET /api/support-inquiriesdefault page 1, size 20
GET /api/support-inquiries?status=activeactive inquiries
GET /api/support-inquiries?category=productproduct inquiries
GET /api/support-inquiries?pagination=falseall current customer's inquiries

16.2 Admin inquiries

RequestNotes
GET /api/admin/support-inquiries?search=INQ-8K4P2Xtracking code lookup
GET /api/admin/support-inquiries?search=alex@example.comguest email lookup
GET /api/admin/support-inquiries?assignedAdminId=019d...assigned queue
GET /api/admin/support-inquiries?status=waiting&sort=updatedAt&order=ascoldest waiting first

16.3 Admin support requests

RequestNotes
GET /api/admin/support-requests?status=openopen tickets
GET /api/admin/support-requests?category=technicaltechnical tickets
GET /api/admin/support-requests?customerId=019d...customer-specific tickets
GET /api/admin/support-requests?search=checkoutsubject search

16.4 Admin feedback

RequestNotes
GET /api/admin/feedback?status=newreview queue
GET /api/admin/feedback?category=bug_reportbug reports
GET /api/admin/feedback?customerId=019d...customer feedback

17. Error Handling

All support API errors use the standard error envelope from the global exception filter.

Example:

{
  "statusCode": 403,
  "errorCode": "SUPPORT_INQUIRY_TOKEN_INVALID",
  "message": "Support inquiry access token is invalid or expired.",
  "timestamp": "2026-06-04T10:00:00.000Z",
  "path": "/api/support-inquiries/10"
}

Representative error map:

HTTPerrorCodeScenario
400SUPPORT_INQUIRY_CLOSEDmessage attempted on closed/spam inquiry
400SUPPORT_INQUIRY_LINK_INVALIDinvalid support request link target
400SUPPORT_INQUIRY_EMAIL_VERIFICATION_INVALIDinvalid OTP or missing email
400SUPPORT_INQUIRY_SUPPORT_REQUEST_REQUIREDconversion requires verified customer
403SUPPORT_INQUIRY_ACCESS_DENIEDJWT/token cannot access inquiry
403SUPPORT_INQUIRY_TOKEN_INVALIDmissing/invalid/expired guest token
404SUPPORT_INQUIRY_NOT_FOUNDinquiry not found
429RATE_LIMIT_EXCEEDEDpublic inquiry write limit exceeded

Frontend guidance:

  • Use errorCode for UI branching.
  • Treat inquiry token errors as expired guest sessions.
  • Treat email verification failures as retry/request-new-code flows.
  • Treat closed inquiry errors as read-only conversation state.

18. Testing Scenarios

18.1 Guest starts support inquiry

  1. Call POST /api/support-inquiries without JWT.
  2. Expect trackingCode, messages, and inquiryAccessToken.
  3. Store token client-side for the chat session.
  4. Fetch GET /api/support-inquiries/:id with Bearer si_....
  5. Expect the same inquiry and full message history.

18.2 Guest sends and receives live messages

  1. Create guest inquiry.
  2. Connect websocket with Bearer si_....
  3. Emit support:join_inquiry_messages.
  4. Post POST /api/support-inquiries/:id/messages.
  5. Expect REST detail response and websocket support.inquiry_message.created.

18.3 Guest email verification

  1. Identify inquiry with guestEmail.
  2. Request verification.
  3. Confirm OTP.
  4. If email belongs to customer, expect customerId on inquiry.
  5. If email does not belong to customer, expect emailVerifiedAt but no customer link.
  6. In both cases, frontend must not learn whether the email matched before confirmation.

18.4 Admin converts inquiry to support request

  1. Admin opens inquiry detail.
  2. Verify customerId exists.
  3. Call POST /api/admin/support-inquiries/:id/link-support-request.
  4. Expect supportRequestId and status linked.
  5. Open /api/admin/support-requests/:supportRequestId.
  6. Verify copied message history.

18.5 Existing mobile support request

  1. Customer calls POST /api/mobile/support-requests.
  2. Customer sees request in GET /api/mobile/support-requests.
  3. Admin sees request in GET /api/admin/support-requests.
  4. Admin replies.
  5. Customer receives websocket event and can refetch detail.

18.6 Feedback review

  1. Customer calls POST /api/mobile/feedback.
  2. Admin lists GET /api/admin/feedback?status=new.
  3. Admin opens detail.
  4. Admin calls PATCH /api/admin/feedback/:id/review.
  5. Expect status=reviewed, reviewedAt, and reviewedByAdminId.

19. Integration Recipes

19.1 Website homepage chat widget

  1. Create inquiry when visitor opens chat or sends first message.
  2. Store id, trackingCode, and inquiryAccessToken.
  3. Show tracking code in the widget.
  4. Use REST to send messages.
  5. Use websocket to receive admin replies.
  6. Prompt for email only as contact/follow-up information.
  7. Use verification endpoints before assuming customer identity.
  8. When token expires, ask visitor to start a new inquiry or log in.

19.2 Admin support inbox

  1. Load open inquiries with GET /api/admin/support-inquiries?status=open.
  2. Search by tracking code, email, phone, or subject.
  3. Assign inquiry to self.
  4. Join websocket inquiry room for live updates.
  5. Reply through REST.
  6. Resolve, close, mark spam, or link to support request.

19.3 Mobile support center

  1. Use /api/mobile/support-requests for logged-in customer ticket history.
  2. Use /api/mobile/support-requests/:id/messages for ticket replies.
  3. Join support:join_request_messages for open ticket detail screens.
  4. On reconnect, call support:sync_request_messages.
  5. If replay gap is detected, refetch ticket detail.

19.4 Admin feedback queue

  1. Show GET /api/admin/feedback?status=new.
  2. Filter by category.
  3. Let admin open detail.
  4. Review action calls PATCH /api/admin/feedback/:id/review.
  5. Remove reviewed item from new queue.

20. Operational Notes

  • Run DB migrations before deploying support inquiry code.
  • Configure role permissions for SupportInquiries.
  • Keep EVENT_HISTORY_ENABLED=true for reconnect replay.
  • Keep SUPPORT_INQUIRIES_INACTIVE_CLOSE_DAYS aligned with product support policy.
  • Guest si_... token is sensitive and should not be logged.
  • Tracking code is safe to show to customers and admins.
  • Full chat history remains available after close; close is not delete.

Time fields in this module are stored as timezone-aware values and should be handled as ISO-8601 instants by API consumers.


See Also

On this page

Support Module - API & Integration Guide1. How to Read / Quick Metadata2. High-Level Overview3. Auth Models4. Core Concepts and Terminology5. Route Summary5.1 Public / Customer Support Inquiries5.2 Admin Support Inquiries5.3 Mobile Support Requests5.4 Admin Support Requests5.5 Feedback6. Support Inquiry Endpoint Details6.1 Create inquiry6.2 List current customer's inquiries6.3 Get inquiry detail6.4 Get inquiry messages6.5 Add inquiry message6.6 Identify guest contact6.7 Request email verification6.8 Confirm email verification7. Admin Inquiry Endpoint Details7.1 Admin list inquiries7.2 Admin get inquiry detail7.3 Admin add inquiry reply7.4 Admin assign inquiry7.5 Admin update inquiry status7.6 Admin link/create support request from inquiry8. Support Request Endpoint Details8.1 Mobile create support request8.2 Mobile list support requests8.3 Mobile get support request detail8.4 Mobile add support request reply8.5 Admin support request list8.6 Admin support request detail8.7 Admin update support request status8.8 Admin assign support request8.9 Admin add support request reply9. Feedback Endpoint Details9.1 Mobile submit feedback9.2 Admin list feedback9.3 Admin feedback detail9.4 Admin review feedback10. DTO Field Reference10.1 CreateSupportInquiryDto10.2 IdentifySupportInquiryDto10.3 CreateSupportInquiryMessageDto10.4 ConfirmSupportInquiryEmailDto10.5 LinkSupportInquiryRequestDto10.6 Support request DTOs10.7 Feedback DTOs11. Response Shape Examples11.1 Support inquiry list item11.2 Support request detail11.3 Feedback response12. Enums12.1 Support inquiry categories12.2 Support inquiry statuses12.3 Support inquiry message author types12.4 Support request categories12.5 Support request statuses12.6 Support request message author types12.7 Feedback categories12.8 Feedback statuses13. Websocket Integration13.1 Connection auth13.2 Client events13.3 Join response examples13.4 Server event envelope13.5 Sync response14. Integration Diagrams14.1 Guest inquiry from homepage chat14.2 Inquiry verification and conversion14.3 Support request ticket flow15. Endpoint Reference + Payload Cheatsheet15.1 Every REST endpoint15.2 Websocket event cheatsheet16. Query Variation Examples16.1 Customer inquiries16.2 Admin inquiries16.3 Admin support requests16.4 Admin feedback17. Error Handling18. Testing Scenarios18.1 Guest starts support inquiry18.2 Guest sends and receives live messages18.3 Guest email verification18.4 Admin converts inquiry to support request18.5 Existing mobile support request18.6 Feedback review19. Integration Recipes19.1 Website homepage chat widget19.2 Admin support inbox19.3 Mobile support center19.4 Admin feedback queue20. Operational NotesSee Also