Tickets
A ticket is one conversation with one customer through one of your integrations: an email thread, a marketplace
message thread, a custom integration’s conversation. The API calls tickets threads, so paths and parameters say
thread and threadId. Most integrations list tickets to find work, read a ticket’s messages to answer it (see
Messages), and then resolve, assign or snooze it.
Fields that matter
Section titled “Fields that matter”A ticket in a list has these fields, among others:
| Field | Meaning |
|---|---|
id |
The ticket’s id. Pass it as threadId to read its messages, set a draft, or change it. |
numberId |
The ticket number your agents see in Replyco. |
subject |
The subject line. |
status |
Where the ticket stands; see States. |
accountId, accountName, marketplace |
The integration the ticket came through. |
customerId, customerName, customerEmail |
The customer. |
userId, username |
The agent the ticket is assigned to; empty when nobody is. |
unread, isStarred |
Whether it has unread messages, and whether it is starred. |
snoozeTill |
Until when the ticket is snoozed; empty when it is not. |
createdDate, lastMessageDate |
When the ticket started, and when its last message arrived or was sent. |
orderId, marketOrderId |
The ticket’s order, when it has one. |
priority, respondWithin, resolveWithin |
The ticket’s priority and its due times; see Priorities and SLAs. |
States
Section titled “States”| Value | State | How it gets there |
|---|---|---|
0 |
Not set | A new ticket; or POST /openapi/thread/markunresolved reopens it. |
1 |
Action required | Set by an agent in Replyco. |
2 |
In progress | Set by an agent in Replyco. |
3 |
Resolved | POST /openapi/thread/markresolved. |
4 |
Waiting for customer | Set by an agent in Replyco. |
Resolving also follows the signed-in user’s settings: it removes the agent when unassignThreadUponResolve is on and
marks the ticket read when markAsReadThreadUponResolve is on (see Users). Automatic replies still
scheduled for the ticket are cancelled.
Next to its state, a ticket can be:
- snoozed:
POST /openapi/thread/snoozeorPOST /openapi/thread/snoozethreadhide it from the ticket list until the time you give; anulltime ends the snooze; - starred:
POST /openapi/thread/changestarred/{value}withtrueorfalse; - archived:
inActiveistrue. Archived tickets are left out of the ticket list unless you ask for the archive tab.
Listing and filtering
Section titled “Listing and filtering”POST /openapi/thread/ticketsforreading/paged takes its filters in the request body and returns one page of tickets.
It lists only tickets of the integrations and folders the signed-in user has access to; accounts and folders
narrow the list further within that.
| Field | What it does | Default | Limits |
|---|---|---|---|
page |
The page to return. | 1 | Stop at the response’s pagesCount. |
count |
Tickets per page. | 10 | At most 100; a larger value is rejected with 400 “Max page size is 100.” |
term |
Searches customer name and email, subject and message text, and matches a ticket number, order number, tracking number or postcode exactly. | none | — |
tab |
One ticket-list tab: 1 my tickets, 2 not resolved, 4 unassigned, 8 resolved, 64 archive, 256 snoozed, 512 delayed, 1024 starred, 32 blocked customers. The signed-in user must have the tab (ticketListPermission). |
none: tickets that are not archived, snoozed or from a blocked customer | — |
folderId |
Only the tickets in this folder. | none | — |
accounts, folders |
Only tickets of these integrations or in these folders. | all the user can see | — |
users, searchUnassigned, searchAssignedToMe |
Only tickets assigned to these agents, unassigned, or assigned to the signed-in user. | any agent | — |
customerId |
Only this customer’s tickets. | any customer | — |
startDate, endDate |
Only tickets created in this range (inclusive). | no range | — |
filterTypes, slaTypes |
Only new, unread, starred… tickets, or tickets due or overdue for a response or resolution. | none | — |
sort |
lastMessageDate, createdDate, numberId, respondWithin or resolveWithin. |
lastMessageDate |
— |
asc |
true for oldest or lowest first. |
false |
— |
curl -X POST "https://open-api.replyco.com/openapi/thread/ticketsforreading/paged" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d @filter.json{ "page": 1, "count": 100, "searchUnassigned": true, "startDate": "2026-10-01T00:00:00Z", "sort": "createdDate", "asc": true}The response holds totalRecords, pageSize, pagesCount, currentPage and the tickets in data. See
Answer tickets for a full example.
Other operations list tickets by what they belong to:
| Operation | Returns |
|---|---|
GET /openapi/thread/bycontact/{customerId} |
A customer’s tickets, newest first, paged with page (default 1) and count (default 10). |
GET /openapi/thread/byorder/{orderId} |
The tickets of an order, archived ones left out. |
GET /openapi/thread/byproduct/{productVariationId} |
Tickets about a product variation or whose order contains it, archived ones left out. |
GET /openapi/thread/byfeedback/{feedbackId} |
The tickets of a review’s order; an empty list when the review has no order. |
GET /openapi/thread/simplifiedthread/{id} |
One ticket, with the fields above. |
GET /openapi/thread/parentthread/{id} |
The ticket another ticket was merged into, when there is one. |
GET /openapi/thread/threadscount |
How many tickets the signed-in user’s list holds, how many are unread, and per-folder counts keyed by folder id. |
GET /openapi/thread/unresolvedticketsassignedusers |
The agents (id, fullName) who have at least one unresolved ticket. |
Changing tickets
Section titled “Changing tickets”The bulk operations take a JSON array of ticket ids as the body; send at least one id. Resolving, reopening, starring and snoozing set a value, so repeating a request gives the same result.
| Operation | What it does |
|---|---|
POST /openapi/thread/assignuser |
Assigns the agent in userId to every ticket in threadsIds, replacing the current agent; an empty userId unassigns them. The agent gets a notification unless they are the signed-in user. An unknown user or ticket returns 404; tickets before the unknown one in the list are already assigned. |
POST /openapi/thread/markresolved, POST /openapi/thread/markunresolved |
Resolve or reopen the tickets; see States. |
POST /openapi/thread/changestarred/{value} |
Stars (true) or unstars (false) the tickets. |
POST /openapi/thread/snooze, POST /openapi/thread/snoozethread |
Snooze several tickets (ids, date) or one (threadId, snoozeUntil) until a time in the future; null ends the snooze. |
POST /openapi/thread/merge |
Merges tickets of the same integration and customer. The ticket created first is kept, and the others’ messages, notes and files move into it; the other tickets are deleted. The kept ticket’s subject starts with “MERGED:”. |
GET /openapi/thread/assignpriority/{threadId}/{id} |
Gives the ticket a priority; see Priorities and SLAs. |
POST /openapi/thread/removeorder/{threadId} |
Unlinks the ticket’s order; the order itself stays. |
PUT /openapi/thread/draft/{threadId} |
Saves a draft reply that agents see in the reply editor, as htmlBody or plain text (htmlBody wins when you send both). It replaces the ticket’s draft, is never sent to the customer by itself, and is kept for 24 hours. Send both fields empty to clear it. An unknown ticket returns 404. |
POST /openapi/thread/note/{threadId} |
Adds an internal note that only your team sees, and that never goes to the customer. Send it in note; basic HTML is allowed and cleaned before saving. The user your token stands for becomes the author, and agents who have the ticket open see the note straight away. An empty note returns 400, and an unknown ticket returns 404. |
POST /openapi/thread/create |
Opens a ticket with its first message, on a custom integration only; see Connect your own system. |
{ "userId": "0b2d4f6b-8c0e-4a2c-9e4a-6c8e0a2c4e6a", "threadsIds": [ "7d2e4f6a-8b1c-4d3e-9f5a-6b7c8d9e0f1a", "8e3f5a7b-9c2d-4e4f-8a6b-7c8d9e0f1a2b" ]}{ "note": "Customer called about this order. Refund approved." }Operations
Section titled “Operations”| Method | Path | Summary | Scopes |
|---|---|---|---|
| GET | /openapi/thread/assignpriority/{threadId}/{id} |
Assign or remove priority from a thread | — |
| POST | /openapi/thread/assignuser |
Assign or unassign a user to/from multiple threads | — |
| GET | /openapi/thread/bycontact/{customerId} |
Get paginated threads by customer ID | — |
| GET | /openapi/thread/byfeedback/{feedbackId} |
Get all threads associated with a feedback/review | — |
| GET | /openapi/thread/byorder/{orderId} |
Get all threads associated with an order | — |
| GET | /openapi/thread/byproduct/{productVariationId} |
Get all threads associated with a product variation | — |
| POST | /openapi/thread/changestarred/{value} |
Change starred status for multiple threads | — |
| POST | /openapi/thread/create |
Create a new thread (ticket) | — |
| PUT | /openapi/thread/draft/{threadId} |
Set the draft reply for a thread | — |
| POST | /openapi/thread/markresolved |
Mark threads as resolved | — |
| POST | /openapi/thread/markunresolved |
Mark threads as unresolved (reopen) | — |
| POST | /openapi/thread/merge |
Merge multiple threads into one | — |
| POST | /openapi/thread/note/{threadId} |
Add an internal note to a thread (ticket) | — |
| GET | /openapi/thread/parentthread/{id} |
Get parent thread by child thread ID | — |
| POST | /openapi/thread/removeorder/{threadId} |
Remove order association from a thread | — |
| GET | /openapi/thread/simplifiedthread/{id} |
Get simplified thread information by ID | — |
| POST | /openapi/thread/snooze |
Snooze tickets until a specified date | — |
| POST | /openapi/thread/snoozethread |
Snooze a single thread until a specified date | — |
| GET | /openapi/thread/threadscount |
Get total and unread threads count for the current company | — |
| POST | /openapi/thread/ticketsforreading/paged |
Get paginated list of tickets with advanced filtering | — |
| GET | /openapi/thread/unresolvedticketsassignedusers |
Get all users who are assigned to unresolved tickets | — |
Errors
Section titled “Errors”| Status | Meaning | Returned by |
|---|---|---|
| 400 | Invalid request (e.g., empty thread list, too many IDs); Invalid pagination parameters; Invalid request (e.g., empty list, too many IDs); Invalid request - missing required fields, an account that is not a Custom Integration, or an attachment that is too large, of a blocked file type, or missing its file name. The response body carries the reason in its ‘error’ field; Invalid request body; Invalid request (e.g., less than 2 IDs, more than 10 IDs); The note is missing or empty. The response body carries the reason in its ‘error’ field; Invalid request (e.g., past date, too many IDs, invalid date range); Invalid request (e.g., past date, invalid date range); Invalid filter parameters (e.g., page size exceeds 100) | POST /openapi/thread/assignuser, GET /openapi/thread/bycontact/{customerId}, POST /openapi/thread/changestarred/{value}, POST /openapi/thread/create, PUT /openapi/thread/draft/{threadId}, POST /openapi/thread/markresolved, POST /openapi/thread/markunresolved, POST /openapi/thread/merge, POST /openapi/thread/note/{threadId}, POST /openapi/thread/snooze, POST /openapi/thread/snoozethread, POST /openapi/thread/ticketsforreading/paged |
| 401 | User is not authenticated or authorized | GET /openapi/thread/assignpriority/{threadId}/{id}, POST /openapi/thread/assignuser, GET /openapi/thread/bycontact/{customerId}, GET /openapi/thread/byfeedback/{feedbackId}, GET /openapi/thread/byorder/{orderId}, GET /openapi/thread/byproduct/{productVariationId}, POST /openapi/thread/changestarred/{value}, POST /openapi/thread/create, PUT /openapi/thread/draft/{threadId}, POST /openapi/thread/markresolved, POST /openapi/thread/markunresolved, POST /openapi/thread/merge, POST /openapi/thread/note/{threadId}, GET /openapi/thread/parentthread/{id}, POST /openapi/thread/removeorder/{threadId}, GET /openapi/thread/simplifiedthread/{id}, POST /openapi/thread/snooze, POST /openapi/thread/snoozethread, GET /openapi/thread/threadscount, POST /openapi/thread/ticketsforreading/paged, GET /openapi/thread/unresolvedticketsassignedusers |
| 403 | User does not have permission to create threads; User does not have access to this thread | POST /openapi/thread/create, GET /openapi/thread/simplifiedthread/{id} |
| 404 | Thread or priority ID was not found; User ID or one or more thread IDs were not found; Customer with the specified ID was not found; Feedback with the specified ID was not found; Order with the specified ID was not found; Product variation with the specified ID was not found; One or more thread IDs were not found; Thread with the specified ID was not found; Child thread with the specified ID was not found | GET /openapi/thread/assignpriority/{threadId}/{id}, POST /openapi/thread/assignuser, GET /openapi/thread/bycontact/{customerId}, GET /openapi/thread/byfeedback/{feedbackId}, GET /openapi/thread/byorder/{orderId}, GET /openapi/thread/byproduct/{productVariationId}, POST /openapi/thread/changestarred/{value}, PUT /openapi/thread/draft/{threadId}, POST /openapi/thread/markresolved, POST /openapi/thread/markunresolved, POST /openapi/thread/merge, POST /openapi/thread/note/{threadId}, GET /openapi/thread/parentthread/{id}, POST /openapi/thread/removeorder/{threadId}, GET /openapi/thread/simplifiedthread/{id}, POST /openapi/thread/snooze, POST /openapi/thread/snoozethread |
- Ask for at most 100 tickets per page; a larger count is rejected with 400 “Max page size is 100.”
- Setting a ticket’s draft replaces the draft it already has; nothing reaches the customer until an agent sends it.
- Each paged list operation allows one user 15 calls a minute; ask for larger pages and narrow the list with filters instead of paging through everything.
- Check the ticket count at most twice a minute for one user.
Related
Section titled “Related”- Answer tickets: find tickets, read them, draft or send the answer.
- Route and organise tickets: assign, label and snooze.
- Look up a customer’s history and Open a ticket for a customer.
- Messages, Folders, Tasks, Users.
- API reference.