OpenPoly logo
Operator Api

Support tickets

Create, read, reply to, and reopen operator support tickets with a staff session.

Support tickets

Operator support connects human operator staff with Polynion Support. Every endpoint requires an active staff-session bearer token; no extra resource scope is required. An API key cannot call these routes, even with *. There is no support:read or support:write scope to grant.

Tickets are shared within the authenticated operator, not private to the creating staff member. The server derives operator and actor identity; operatorId or operator_id query parameters are rejected. Do not send credentials, launch tokens, raw wallet headers, or other secrets in subjects/messages.

Method and pathRequestResponse
GET /api/operator/support-ticketsOptional list query below.{ ok: true, tickets, total, page, pageSize, totalPages }
POST /api/operator/support-ticketsJSON { category, subject, body }.{ ok: true, ticketId }
GET /api/operator/support-tickets/{id}Positive canonical decimal safe-integer ticket ID; no body.{ ok: true, ticket }
POST /api/operator/support-tickets/{id}/messagesJSON { body }.{ ok: true }
POST /api/operator/support-tickets/{id}/reopenNo body or an empty JSON object {}.{ ok: true }

Operator routes do not provide close, delete, category/subject edit, or attachment-upload operations. Closing is a Polynion Support action. Reopening an already-open owned ticket succeeds without creating another status-change event.

List filters

ParameterValues/default
statusOptional open or closed; omission includes both.
searchOptional trimmed text, maximum 200 characters; case-insensitive literal substring of subject, ticket ID text, or the authenticated operator's name/slug. It does not search message bodies.
pagePositive canonical decimal safe integer, default 1.
pageSizePositive canonical decimal integer, default 20, maximum 100; camelCase, not page_size.

Unknown query keys and invalid values return 400 INVALID_INPUT; values over the page-size maximum are rejected, not capped. Pagination offset must also be a safe integer. Results are ordered by lastMessageAt descending, then ID descending; totalPages is at least 1.

Create and reply

{
  "category": "operations",
  "subject": "Unknown wallet credit for redemption item 123",
  "body": "Please review operation 456. Our ledger reference is redacted-reference; no second credit has been issued."
}
FieldRequired contract
categorytechnical, billing, operations, or other. Required only on create.
subjectTrimmed, nonempty text, maximum 255 characters. Required only on create.
bodyTrimmed, nonempty text, maximum 20000 characters. Required on create and reply.

Bodies are strict objects; unknown fields are rejected. Creation stores the ticket as open, the first operator message, and an open status event. The API does not return a notification-delivery receipt or a response-time guarantee.

A reply does not reopen a closed ticket: it returns 409 TICKET_CLOSED. Reopen first, then send the message. There is no creation/reply idempotency-key field; after an ambiguous response, inspect the list/detail before retrying to avoid duplicate tickets or messages.

Response objects

List ticket objects and detail use camelCase:

FieldsType/meaning
id, operatorId, createdByAdminUserIdNumeric identities.
operatorName, operatorSlugOperator display identity.
category, subject, statusCategory enum, subject text, and open/closed.
createdAt, updatedAt, lastMessageAtISO timestamps.
lastOperatorReplyAt, lastAdminReplyAt, closedAtNullable ISO timestamps.

Detail adds:

  • messages: { id, actorType, actorName, body, createdAt };
  • events: { id, actorType, actorName, adminUserId, status, createdAt }.

actorType is operator or admin; actorName is nullable. Messages and status events are ordered oldest first by timestamp, then ID, and are not separately paginated. Render message text as text, not executable HTML. A ticket is an operational conversation, not authorization to issue a new payment or override cash-flow reconciliation.

Errors

  • 400 INVALID_INPUT: invalid ID, schema, filters, unknown fields, or operator selectors.
  • 403 STAFF_SESSION_REQUIRED: API-key authentication is not supported.
  • 404 TICKET_NOT_FOUND: missing ticket, wrong operator, or actor no longer eligible for a mutation.
  • 409 TICKET_CLOSED: reply attempted on a closed ticket; reopen before replying.

Standard bearer authentication errors also apply. A ticket ID is not a public access link; read and mutation requests must remain authenticated.

Copyright © 2026