Skip to content

Depot tickets

Registers the ticket routes on mux.

This page is generated from the Depot route table. Every operation carries the permission it needs and the anchor an agent can link to.

GETticket:readtenant facehosteditmspremoteIdempotent

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

listTicketMacrosForConsole returns the canned responses a technician can apply from the composer, on “ticket:read” for the same reason the views list is.

NameInTypeRequiredDescription
pagequeryintegerNoOne-based page number. Defaults to 1.
pageSizequeryintegerNoRows per page, 1 to 200. Defaults to 50.
StatusBodyDescription
200application/json, PagedResultTicketMacroViewSuccess.
401application/problem+json, ProblemDetailsNo signed-in identity.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:read.
500application/problem+json, ProblemDetailsNo client store in request context.

200 response body

FieldTypeDescription
itemsrequiredarray of TicketMacroView
items[].addTagsarray of string
items[].bodyrequiredstring
items[].namerequiredstring
items[].publicIdrequiredstring
items[].setAssigneeIdstring
items[].setPrioritystring
items[].setStatusstring
pagerequiredinteger
pageSizerequiredinteger
totalrequiredinteger
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X GET 'https://depot.example.com/api/v1/ticket-macros?page=0&pageSize=0' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-b 'outpost_console=<console-session>'

GETticket:readtenant facehosteditmspremoteIdempotent

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

List ticket queues for console

NameInTypeRequiredDescription
pagequeryintegerNoOne-based page number. Defaults to 1.
pageSizequeryintegerNoRows per page, 1 to 200. Defaults to 50.
StatusBodyDescription
200application/json, PagedResultTicketQueueViewSuccess.
401application/problem+json, ProblemDetailsNo signed-in identity.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:read.
500application/problem+json, ProblemDetailsNo client store in request context.

200 response body

FieldTypeDescription
itemsrequiredarray of TicketQueueView
items[].namerequiredstring
items[].openCountrequiredinteger
items[].publicIdrequiredstring
pagerequiredinteger
pageSizerequiredinteger
totalrequiredinteger
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X GET 'https://depot.example.com/api/v1/ticket-queues?page=0&pageSize=0' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-b 'outpost_console=<console-session>'

GETticket:readtenant facehosteditmspremoteIdempotent

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

listTicketViewsForConsole returns the saved views this technician can use: their own plus the shared ones.

This is a “ticket:read” route and the CRUD that maintains views is not. A technician has no admin permission and still has to see their sidebar, so serving the list from the admin route would leave the sidebar empty for exactly the people who work the queue.

NameInTypeRequiredDescription
pagequeryintegerNoOne-based page number. Defaults to 1.
pageSizequeryintegerNoRows per page, 1 to 200. Defaults to 50.
StatusBodyDescription
200application/json, PagedResultTicketSavedViewViewSuccess.
401application/problem+json, ProblemDetailsNo signed-in identity.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:read.
500application/problem+json, ProblemDetailsNo client store in request context.

200 response body

FieldTypeDescription
itemsrequiredarray of TicketSavedViewView
items[].countrequiredinteger
items[].namerequiredstring
items[].publicIdrequiredstring
items[].queryrequiredobject
items[].sharedrequiredboolean
pagerequiredinteger
pageSizerequiredinteger
totalrequiredinteger
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X GET 'https://depot.example.com/api/v1/ticket-views?page=0&pageSize=0' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-b 'outpost_console=<console-session>'

GETticket:readtenant facehosteditmspremoteIdempotent

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

List tickets

NameInTypeRequiredDescription
agentIdquerystringNo
assigneeIdquerystringNo
breachedquerystringNo
categoryquerystringNo
createdAfterquerystringNo
createdBeforequerystringNo
hostnamequerystringNo
pagequeryintegerNoOne-based page number. Defaults to 1.
pageSizequeryintegerNoRows per page, 1 to 200. Defaults to 50.
priorityquerystring, one of critical, high, normal, urgentNoComma-separated set. An unrecognised value is refused.
qquerystringNo
queueIdquerystringNo
requesterIdquerystringNo
sortquerystringNo
statusquerystringNo
statusCategoryquerystringNo
statusCategoryNotquerystringNo
subcategoryquerystringNo
tagquerystringNo
viewIdquerystringNo
StatusBodyDescription
200application/json, PagedResultTicketSummaryViewSuccess.
400application/problem+json, ProblemDetailsOne or more validation errors occurred.
401application/problem+json, ProblemDetailsNo signed-in identity.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:read.
404application/problem+json, ProblemDetailsSaved view not found.
500application/problem+json, ProblemDetailsNo client store in request context.

200 response body

FieldTypeDescription
itemsrequiredarray of TicketSummaryView
items[].agentIdstring
items[].assigneeIdstring
items[].assigneeNamestring
items[].channelrequiredstring
items[].createdAtrequiredstring (date-time)
items[].hostnamestring
items[].lastPublicReplyAtstring (date-time) or null
items[].messageCountrequiredinteger
items[].numberrequiredinteger

int64.

items[].parentIdstring
items[].priorityrequiredstring
items[].publicIdrequiredstring
items[].queueIdstring
items[].queueNamestring
items[].referencerequiredstring
items[].requesterConfidencerequiredstring
items[].requesterEmailstring
items[].requesterIdstring
items[].requesterNamerequiredstring
items[].siteNamestring
items[].slaBreachedrequiredboolean
items[].slaNextEventAtstring (date-time) or null
items[].statusrequiredstring
items[].statusCategoryrequiredstring
items[].statusNamerequiredstring
items[].subcategorystring
items[].subjectrequiredstring
items[].tagsrequiredarray of string
items[].typerequiredstring
items[].unreadrequiredboolean
items[].updatedAtrequiredstring (date-time)
pagerequiredinteger
pageSizerequiredinteger
totalrequiredinteger
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X GET 'https://depot.example.com/api/v1/tickets?agentId=<agentId>&assigneeId=<assigneeId>&breached=<breached>&category=<category>&createdAfter=<createdAfter>&createdBefore=<createdBefore>' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-b 'outpost_console=<console-session>'

POSTticket:writetenant facehosteditmspremote

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

Create ticket

Required, sent as application/json.

FieldTypeDescription
agentIdrequiredstring
descriptionrequiredstring
priorityrequiredstring
queueIdrequiredstring
requesterIdrequiredstring
subcategoryrequiredstring
subjectrequiredstring
tagsrequiredarray of string
typerequiredstring
StatusBodyDescription
201application/json, TicketDetailViewCreated.
400application/problem+json, ProblemDetailsThe request body is not valid JSON.
401application/problem+json, ProblemDetailsNo signed-in identity.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:write.
404application/problem+json, ProblemDetailsNo resource matches.
409application/problem+json, ProblemDetailsThe request conflicts with the current state.
500application/problem+json, ProblemDetailsNo client store in request context.
507application/problem+json, ProblemDetailsThe storage profile for this client is over its configured quota. Raise the quota or remove attachments.

201 response body

FieldTypeDescription
agentIdstring
assigneeIdstring
assigneeNamestring
channelrequiredstring
childCountrequiredinteger
contactAlertsrequiredarray of ContactAlertView
contactAlerts[].colorrequiredstring
contactAlerts[].descriptionrequiredstring
contactAlerts[].displayNamerequiredstring
contactAlerts[].labelrequiredstring
contactAlerts[].namedUserIdrequiredstring
contactAlerts[].tagCoderequiredstring
createdAtrequiredstring (date-time)
customFieldsrequiredobject
descriptionrequiredstring
hostnamestring
lastPublicReplyAtstring (date-time) or null
linksrequiredarray of TicketLinkView
links[].kindrequiredstring
links[].otherPublicIdrequiredstring
links[].otherReferencerequiredstring
links[].otherStatusrequiredstring
links[].otherStatusCategoryrequiredstring
links[].otherSubjectrequiredstring
links[].publicIdrequiredstring
mergedIntoPublicIdstring
messageCountrequiredinteger
numberrequiredinteger

int64.

parentTicketParentView

ticketParentView is the parent breadcrumb on a child's detail.

parent.publicIdrequiredstring
parent.referencerequiredstring
parent.statusCategoryrequiredstring
parent.subjectrequiredstring
parentIdstring
participantsrequiredarray of TicketParticipantView
participants[].emailstring
participants[].namerequiredstring
participants[].rolerequiredstring
participants[].userPublicIdstring
priorityrequiredstring
projectLinksrequiredarray of TicketProjectLinkView
projectLinks[].kindrequiredstring
projectLinks[].projectNamerequiredstring
projectLinks[].projectPublicIdrequiredstring
projectLinks[].projectReferencerequiredstring
projectLinks[].publicIdrequiredstring
projectLinks[].taskPublicIdstring
publicIdrequiredstring
queueIdstring
queueNamestring
referencerequiredstring
requesterConfidencerequiredstring
requesterEmailstring
requesterIdstring
requesterNamerequiredstring
siteNamestring
slaBreachedrequiredboolean
slaNextEventAtstring (date-time) or null
slaReasonstring
statusrequiredstring
statusCategoryrequiredstring
statusNamerequiredstring
subcategorystring
subjectrequiredstring
tagsrequiredarray of string
typerequiredstring
unreadrequiredboolean
updatedAtrequiredstring (date-time)
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/v1/tickets' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-b 'outpost_console=<console-session>' \
--data '{
"agentId": "string",
"description": "string",
"priority": "string",
"queueId": "string",
"requesterId": "string",
"subcategory": "string",
"subject": "string",
"tags": [
"string"
],
"type": "string"
}'

GETticket:readtenant facehosteditmspremoteIdempotent

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

Get ticket

NameInTypeRequiredDescription
ticketIDpathstringYesA uuid.
StatusBodyDescription
200application/json, TicketDetailViewSuccess.
401application/problem+json, ProblemDetailsNo signed-in identity.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:read.
404application/problem+json, ProblemDetailsNo resource matches that id.
409application/problem+json, ProblemDetailsThe request conflicts with the current state.
500application/problem+json, ProblemDetailsNo client store in request context.
507application/problem+json, ProblemDetailsThe storage profile for this client is over its configured quota. Raise the quota or remove attachments.

200 response body

FieldTypeDescription
agentIdstring
assigneeIdstring
assigneeNamestring
channelrequiredstring
childCountrequiredinteger
contactAlertsrequiredarray of ContactAlertView
contactAlerts[].colorrequiredstring
contactAlerts[].descriptionrequiredstring
contactAlerts[].displayNamerequiredstring
contactAlerts[].labelrequiredstring
contactAlerts[].namedUserIdrequiredstring
contactAlerts[].tagCoderequiredstring
createdAtrequiredstring (date-time)
customFieldsrequiredobject
descriptionrequiredstring
hostnamestring
lastPublicReplyAtstring (date-time) or null
linksrequiredarray of TicketLinkView
links[].kindrequiredstring
links[].otherPublicIdrequiredstring
links[].otherReferencerequiredstring
links[].otherStatusrequiredstring
links[].otherStatusCategoryrequiredstring
links[].otherSubjectrequiredstring
links[].publicIdrequiredstring
mergedIntoPublicIdstring
messageCountrequiredinteger
numberrequiredinteger

int64.

parentTicketParentView

ticketParentView is the parent breadcrumb on a child's detail.

parent.publicIdrequiredstring
parent.referencerequiredstring
parent.statusCategoryrequiredstring
parent.subjectrequiredstring
parentIdstring
participantsrequiredarray of TicketParticipantView
participants[].emailstring
participants[].namerequiredstring
participants[].rolerequiredstring
participants[].userPublicIdstring
priorityrequiredstring
projectLinksrequiredarray of TicketProjectLinkView
projectLinks[].kindrequiredstring
projectLinks[].projectNamerequiredstring
projectLinks[].projectPublicIdrequiredstring
projectLinks[].projectReferencerequiredstring
projectLinks[].publicIdrequiredstring
projectLinks[].taskPublicIdstring
publicIdrequiredstring
queueIdstring
queueNamestring
referencerequiredstring
requesterConfidencerequiredstring
requesterEmailstring
requesterIdstring
requesterNamerequiredstring
siteNamestring
slaBreachedrequiredboolean
slaNextEventAtstring (date-time) or null
slaReasonstring
statusrequiredstring
statusCategoryrequiredstring
statusNamerequiredstring
subcategorystring
subjectrequiredstring
tagsrequiredarray of string
typerequiredstring
unreadrequiredboolean
updatedAtrequiredstring (date-time)
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X GET 'https://depot.example.com/api/v1/tickets/<ticketID>' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-b 'outpost_console=<console-session>'

PATCHticket:writetenant facehosteditmspremoteIdempotent

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

Patch ticket

NameInTypeRequiredDescription
ticketIDpathstringYesA uuid.

Required, sent as application/json.

FieldTypeDescription
assigneeIdstring or null
prioritystring or null
queueIdstring or null
statusstring or null
statusCategorystring or null
subcategorystring or null
subjectstring or null
tagsrequiredarray of string
typestring or null
StatusBodyDescription
200application/json, TicketDetailViewSuccess.
400application/problem+json, ProblemDetailsThe request body is not valid JSON.
401application/problem+json, ProblemDetailsAuthentication is required.
403application/problem+json, ProblemDetailsChanging who a ticket is assigned to requires the ticket:assign permission.
404application/problem+json, ProblemDetailsNo resource matches that id.
409application/problem+json, ProblemDetailsThe request conflicts with the current state.
500application/problem+json, ProblemDetailsNo client store in request context.
507application/problem+json, ProblemDetailsThe storage profile for this client is over its configured quota. Raise the quota or remove attachments.

200 response body

FieldTypeDescription
agentIdstring
assigneeIdstring
assigneeNamestring
channelrequiredstring
childCountrequiredinteger
contactAlertsrequiredarray of ContactAlertView
contactAlerts[].colorrequiredstring
contactAlerts[].descriptionrequiredstring
contactAlerts[].displayNamerequiredstring
contactAlerts[].labelrequiredstring
contactAlerts[].namedUserIdrequiredstring
contactAlerts[].tagCoderequiredstring
createdAtrequiredstring (date-time)
customFieldsrequiredobject
descriptionrequiredstring
hostnamestring
lastPublicReplyAtstring (date-time) or null
linksrequiredarray of TicketLinkView
links[].kindrequiredstring
links[].otherPublicIdrequiredstring
links[].otherReferencerequiredstring
links[].otherStatusrequiredstring
links[].otherStatusCategoryrequiredstring
links[].otherSubjectrequiredstring
links[].publicIdrequiredstring
mergedIntoPublicIdstring
messageCountrequiredinteger
numberrequiredinteger

int64.

parentTicketParentView

ticketParentView is the parent breadcrumb on a child's detail.

parent.publicIdrequiredstring
parent.referencerequiredstring
parent.statusCategoryrequiredstring
parent.subjectrequiredstring
parentIdstring
participantsrequiredarray of TicketParticipantView
participants[].emailstring
participants[].namerequiredstring
participants[].rolerequiredstring
participants[].userPublicIdstring
priorityrequiredstring
projectLinksrequiredarray of TicketProjectLinkView
projectLinks[].kindrequiredstring
projectLinks[].projectNamerequiredstring
projectLinks[].projectPublicIdrequiredstring
projectLinks[].projectReferencerequiredstring
projectLinks[].publicIdrequiredstring
projectLinks[].taskPublicIdstring
publicIdrequiredstring
queueIdstring
queueNamestring
referencerequiredstring
requesterConfidencerequiredstring
requesterEmailstring
requesterIdstring
requesterNamerequiredstring
siteNamestring
slaBreachedrequiredboolean
slaNextEventAtstring (date-time) or null
slaReasonstring
statusrequiredstring
statusCategoryrequiredstring
statusNamerequiredstring
subcategorystring
subjectrequiredstring
tagsrequiredarray of string
typerequiredstring
unreadrequiredboolean
updatedAtrequiredstring (date-time)
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X PATCH 'https://depot.example.com/api/v1/tickets/<ticketID>' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-b 'outpost_console=<console-session>' \
--data '{
"assigneeId": "string",
"priority": "string",
"queueId": "string",
"status": "string",
"statusCategory": "string",
"subcategory": "string",
"subject": "string",
"tags": [
"string"
],
"type": "string"
}'

GETticket:readtenant facehosteditmspremoteIdempotent

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

listTicketActivity returns the ticket’s audit trail.

IT IS BACKED BY THE TICKET’S SYSTEM MESSAGES, which is what the schema has: a system message is a row in the conversation that describes something that happened TO the ticket (“assigned to Dana Reyes”, “merged into OUT-1042”), and the merge rules already treat them as the ticket’s own history by leaving them behind rather than moving them.

ponytail: the console’s TicketEvent carries field/from/to for a structured diff, and a system message has only prose, so those three are left absent and the console falls back to rendering the kind. The upgrade path is a “TicketActivity” table with Field/OldValue/NewValue columns written by the same code that writes the system message; do it when a writer actually has a field diff to record, not before, because a table nobody fills is worse than no table.

NameInTypeRequiredDescription
ticketIDpathstringYesA uuid.
pagequeryintegerNoOne-based page number. Defaults to 1.
pageSizequeryintegerNoRows per page, 1 to 200. Defaults to 50.
StatusBodyDescription
200application/json, PagedResultTicketEventViewSuccess.
401application/problem+json, ProblemDetailsNo signed-in identity.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:read.
404application/problem+json, ProblemDetailsNo resource matches that id.
500application/problem+json, ProblemDetailsNo client store in request context.

200 response body

FieldTypeDescription
itemsrequiredarray of TicketEventView
items[].actorNamerequiredstring
items[].createdAtrequiredstring (date-time)
items[].fieldstring
items[].fromstring
items[].kindrequiredstring
items[].publicIdrequiredstring
items[].ruleNamestring
items[].tostring
pagerequiredinteger
pageSizerequiredinteger
totalrequiredinteger
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X GET 'https://depot.example.com/api/v1/tickets/<ticketID>/activity?page=0&pageSize=0' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-b 'outpost_console=<console-session>'

GETticket:readtenant facehosteditmspremoteIdempotent

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

List ticket messages

NameInTypeRequiredDescription
ticketIDpathstringYesA uuid.
pagequeryintegerNoOne-based page number. Defaults to 1.
pageSizequeryintegerNoRows per page, 1 to 200. Defaults to 50.
StatusBodyDescription
200application/json, PagedResultTicketMessageViewSuccess.
401application/problem+json, ProblemDetailsNo signed-in identity.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:read.
404application/problem+json, ProblemDetailsNo resource matches that id.
500application/problem+json, ProblemDetailsNo client store in request context.

200 response body

FieldTypeDescription
itemsrequiredarray of TicketMessageView
items[].attachmentsrequiredarray of TicketAttachmentView
items[].attachments[].contentTyperequiredstring
items[].attachments[].downloadUrlrequiredstring
items[].attachments[].fileNamerequiredstring
items[].attachments[].idrequiredstring
items[].attachments[].sizeBytesrequiredinteger

int64.

items[].authorKindrequiredstring
items[].authorNamerequiredstring
items[].bodyrequiredstring
items[].createdAtrequiredstring (date-time)
items[].idrequiredstring
pagerequiredinteger
pageSizerequiredinteger
totalrequiredinteger
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X GET 'https://depot.example.com/api/v1/tickets/<ticketID>/messages?page=0&pageSize=0' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-b 'outpost_console=<console-session>'

POSTticket:writetenant facehosteditmspremote

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

Create ticket message

NameInTypeRequiredDescription
ticketIDpathstringYesA uuid.

Required, sent as application/json.

FieldTypeDescription
bodyrequiredstring
internalrequiredboolean
StatusBodyDescription
201application/json, TicketMessageViewCreated.
400application/problem+json, ProblemDetailsThe request body is not valid JSON.
401application/problem+json, ProblemDetailsNo signed-in identity.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:write.
404application/problem+json, ProblemDetailsNo resource matches that id.
409application/problem+json, ProblemDetailsThat message cannot be saved as written: an internal note can never be queued for delivery.
500application/problem+json, ProblemDetailsNo client store in request context.

201 response body

FieldTypeDescription
attachmentsrequiredarray of TicketAttachmentView
attachments[].contentTyperequiredstring
attachments[].downloadUrlrequiredstring
attachments[].fileNamerequiredstring
attachments[].idrequiredstring
attachments[].sizeBytesrequiredinteger

int64.

authorKindrequiredstring
authorNamerequiredstring
bodyrequiredstring
createdAtrequiredstring (date-time)
idrequiredstring
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/v1/tickets/<ticketID>/messages' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-b 'outpost_console=<console-session>' \
--data '{
"body": "string",
"internal": false
}'

POSTticket:readtenant facehosteditmspremote

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

markTicketRead records how far the signed-in technician has read.

It notifies the tray, which the four automation hooks’ sites do not, because unread is what drives the tray’s badge and the count on its Tickets tab - the one number a user reads without opening anything.

ponytail: KNOWN, and stated here rather than discovered later: today this push is always suppressed by the hash, because trayTickets in grpcserver/ticket.go does not fill UserTicket.unread or unread_count yet, so the recomputed panel is byte-identical and nothing goes out. The read position this route writes is also the TECHNICIAN’s (TicketRead is per console user), not the requester’s, so filling the tray’s badge needs a requester-side read marker that does not exist yet. The call is here so that when either lands the badge moves on its own; it costs one recomputation of a panel that was going to be recomputed on the next reply anyway.

NameInTypeRequiredDescription
ticketIDpathstringYesA uuid.

Required, sent as application/json.

FieldTypeDescription
lastMessageIdrequiredstring
StatusBodyDescription
204NoneSuccess, with no body.
400application/problem+json, ProblemDetailsThe request body is not valid JSON.
401application/problem+json, ProblemDetailsAuthentication is required.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:read.
404application/problem+json, ProblemDetailsNo resource matches that id.
500application/problem+json, ProblemDetailsNo client store in request context.
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/v1/tickets/<ticketID>/read' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-b 'outpost_console=<console-session>' \
--data '{
"lastMessageId": "string"
}'

GETticket:readtenant facehosteditmspremoteIdempotent

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

List ticket time entries

NameInTypeRequiredDescription
ticketIDpathstringYesA uuid.
pagequeryintegerNoOne-based page number. Defaults to 1.
pageSizequeryintegerNoRows per page, 1 to 200. Defaults to 50.
StatusBodyDescription
200application/json, PagedResultTicketTimeEntryViewSuccess.
401application/problem+json, ProblemDetailsNo signed-in identity.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:read.
404application/problem+json, ProblemDetailsNo resource matches that id.
500application/problem+json, ProblemDetailsNo client store in request context.

200 response body

FieldTypeDescription
itemsrequiredarray of TicketTimeEntryView
items[].amountCentsinteger

int64.

items[].billablerequiredboolean
items[].chargeTypeCodestring
items[].classifiedAtstring (date-time) or null
items[].invoicePublicIdstring or null
items[].invoicedrequiredboolean
items[].lockedboolean
items[].messagePublicIdstring
items[].minutesrequiredinteger
items[].noterequiredstring
items[].occurredAtrequiredstring (date-time)
items[].outcomestring
items[].publicIdrequiredstring
items[].rateCentsSnapshotinteger or null

int64.

items[].technicianNamerequiredstring
pagerequiredinteger
pageSizerequiredinteger
totalrequiredinteger
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X GET 'https://depot.example.com/api/v1/tickets/<ticketID>/time?page=0&pageSize=0' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-b 'outpost_console=<console-session>'

POSTticket:writetenant facehosteditmspremote

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

createTicketTimeEntry logs a technician’s worked minutes against a ticket.

NO TRAY NOTIFICATION FOR THE TIME ITSELF, DELIBERATELY; only a public note logged with it repaints the tray. Logged time is desk-internal billing material: it is not on UserTicket, it is not on any panel the tray renders, and it does not move the ticket’s status, priority or activity. A push would recompute a panel that is byte-identical, be suppressed by the hash, and have cost a read per timesheet entry. Add one here only if a time entry ever becomes something the user sees.

IT TAKES THE HOOKS FOR ONE FIELD. The cost-rate snapshot lives in the control database and this route mounts on every face, so the read goes through TicketHooks.CostRateFor, which main.go supplies in msp mode only. Everywhere else the entry is stored with a null snapshot, which is the honest answer for a deployment that has no cost rates.

NameInTypeRequiredDescription
ticketIDpathstringYesA uuid.

Required, sent as application/json.

FieldTypeDescription
billablerequiredboolean
chargeTypeCoderequiredstring
messageTimeEntryMessageRequest
message.bodyrequiredstring
message.internalboolean or null
minutesrequiredinteger
noterequiredstring
occurredAtrequiredstring
StatusBodyDescription
201application/json, TicketTimeEntryViewCreated.
400application/problem+json, ProblemDetailsThe request body is not valid JSON.
401application/problem+json, ProblemDetailsLogging time requires a signed-in technician.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:write.
404application/problem+json, ProblemDetailsNo resource matches that id.
500application/problem+json, ProblemDetailsNo client store in request context.
503application/problem+json, ProblemDetailsCould not check whether this week’s timesheet is approved. Nothing was changed; try again in a moment.

201 response body

FieldTypeDescription
amountCentsinteger

int64.

billablerequiredboolean
chargeTypeCodestring
classifiedAtstring (date-time) or null
invoicePublicIdstring or null
invoicedrequiredboolean
lockedboolean
messagePublicIdstring
minutesrequiredinteger
noterequiredstring
occurredAtrequiredstring (date-time)
outcomestring
publicIdrequiredstring
rateCentsSnapshotinteger or null

int64.

technicianNamerequiredstring
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/v1/tickets/<ticketID>/time' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-b 'outpost_console=<console-session>' \
--data '{
"billable": false,
"chargeTypeCode": "string",
"message": {
"body": "string",
"internal": false
},
"minutes": 0,
"note": "string",
"occurredAt": "string"
}'

PATCH /api/v1/tickets/{ticketID}/time/{entryID}

Section titled “PATCH /api/v1/tickets/{ticketID}/time/{entryID}”

PATCHticket:writetenant facehosteditmspremoteIdempotent

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

patchTicketTimeEntry corrects what a technician logged.

409 ONCE THE ENTRY IS INVOICED, and the check is the store’s under a row lock rather than a status read here: a check in the handler would race a concurrent finalize and let an edit land on work that had already been billed, which makes a sent invoice disagree with the database.

THE WIRE FIELDS ARE THE ONES THE POST AND THE GET ON THIS RESOURCE ALREADY USE: minutes and occurredAt, converted to seconds and StartedAt here exactly as createTicketTimeEntry converts them. One resource with three verbs that name the same value two different ways is a resource whose forms have to know which verb they are about to use, and the first person to get that wrong logs ninety seconds where they meant ninety minutes.

NameInTypeRequiredDescription
entryIDpathstringYesA uuid.
ticketIDpathstringYesA uuid.

Required, sent as application/json.

FieldTypeDescription
billableboolean or null
chargeTypeCodestring or null
minutesinteger or null
notestring or null
occurredAtstring or null
StatusBodyDescription
200application/json, TicketTimeEntryViewSuccess.
400application/problem+json, ProblemDetailsThe request body is not valid JSON.
401application/problem+json, ProblemDetailsNo signed-in identity.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:write.
404application/problem+json, ProblemDetailsNo resource matches that id.
409application/problem+json, ProblemDetailsThis time entry is on an invoice and can no longer be edited.
500application/problem+json, ProblemDetailsNo client store in request context.
503application/problem+json, ProblemDetailsCould not check whether this week’s timesheet is approved. Nothing was changed; try again in a moment.

200 response body

FieldTypeDescription
amountCentsinteger

int64.

billablerequiredboolean
chargeTypeCodestring
classifiedAtstring (date-time) or null
invoicePublicIdstring or null
invoicedrequiredboolean
lockedboolean
messagePublicIdstring
minutesrequiredinteger
noterequiredstring
occurredAtrequiredstring (date-time)
outcomestring
publicIdrequiredstring
rateCentsSnapshotinteger or null

int64.

technicianNamerequiredstring
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X PATCH 'https://depot.example.com/api/v1/tickets/<ticketID>/time/<entryID>' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-b 'outpost_console=<console-session>' \
--data '{
"billable": false,
"chargeTypeCode": "string",
"minutes": 0,
"note": "string",
"occurredAt": "string"
}'

DELETE /api/v1/tickets/{ticketID}/time/{entryID}

Section titled “DELETE /api/v1/tickets/{ticketID}/time/{entryID}”

DELETEticket:writetenant facehosteditmspremoteIdempotent

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

deleteTicketTimeEntry removes one logged entry, under the same invoiced guard.

That guard is not new: DeleteTicketTimeEntry has refused an invoiced row since 0018_client.sql, at a time when nothing could set InvoicedAt. This route is what finally reaches it.

NameInTypeRequiredDescription
entryIDpathstringYesA uuid.
ticketIDpathstringYesA uuid.
StatusBodyDescription
204NoneSuccess, with no body.
400application/problem+json, ProblemDetailsOne or more validation errors occurred.
401application/problem+json, ProblemDetailsNo signed-in identity.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:write.
404application/problem+json, ProblemDetailsNo resource matches that id.
409application/problem+json, ProblemDetailsThis time entry is on an invoice and can no longer be deleted.
500application/problem+json, ProblemDetailsNo client store in request context.
503application/problem+json, ProblemDetailsCould not check whether this week’s timesheet is approved. Nothing was changed; try again in a moment.
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X DELETE 'https://depot.example.com/api/v1/tickets/<ticketID>/time/<entryID>' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-b 'outpost_console=<console-session>'

POST /api/v1/tickets/{ticketID}/verify-sender

Section titled “POST /api/v1/tickets/{ticketID}/verify-sender”

POSTticket:writetenant facehosteditmspremoteIdempotent

From an MSP console, prefix the path with /api/v1/clients/{clientID} to reach one client.

Source: [object Object]

verifyTicketSender confirms who sent an email ticket, so its replies are emailed.

Mail from a sender nothing vouches for (no allow rule, known contact, DMARC pass or trust-all) opens a ticket with an unverified requester and sends no email from it, to the requester or to anyone they copied, because its From may be forged (EMAIL_CONTRACTS.md R22). A technician who knows the person verifies them here. Only an email ticket qualifies: an endpoint’s unclaimed requester is resolved through the people merge queue instead. 409 when the ticket’s sender needs no verifying.

NameInTypeRequiredDescription
ticketIDpathstringYesA uuid.
StatusBodyDescription
200application/json, TicketDetailViewSuccess.
401application/problem+json, ProblemDetailsNo signed-in identity.
403application/problem+json, ProblemDetailsThe identity does not hold ticket:write.
404application/problem+json, ProblemDetailsNo resource matches that id.
409application/problem+json, ProblemDetailsThis ticket was merged into another; verify the sender there.
500application/problem+json, ProblemDetailsNo client store in request context.
507application/problem+json, ProblemDetailsThe storage profile for this client is over its configured quota. Raise the quota or remove attachments.

200 response body

FieldTypeDescription
agentIdstring
assigneeIdstring
assigneeNamestring
channelrequiredstring
childCountrequiredinteger
contactAlertsrequiredarray of ContactAlertView
contactAlerts[].colorrequiredstring
contactAlerts[].descriptionrequiredstring
contactAlerts[].displayNamerequiredstring
contactAlerts[].labelrequiredstring
contactAlerts[].namedUserIdrequiredstring
contactAlerts[].tagCoderequiredstring
createdAtrequiredstring (date-time)
customFieldsrequiredobject
descriptionrequiredstring
hostnamestring
lastPublicReplyAtstring (date-time) or null
linksrequiredarray of TicketLinkView
links[].kindrequiredstring
links[].otherPublicIdrequiredstring
links[].otherReferencerequiredstring
links[].otherStatusrequiredstring
links[].otherStatusCategoryrequiredstring
links[].otherSubjectrequiredstring
links[].publicIdrequiredstring
mergedIntoPublicIdstring
messageCountrequiredinteger
numberrequiredinteger

int64.

parentTicketParentView

ticketParentView is the parent breadcrumb on a child's detail.

parent.publicIdrequiredstring
parent.referencerequiredstring
parent.statusCategoryrequiredstring
parent.subjectrequiredstring
parentIdstring
participantsrequiredarray of TicketParticipantView
participants[].emailstring
participants[].namerequiredstring
participants[].rolerequiredstring
participants[].userPublicIdstring
priorityrequiredstring
projectLinksrequiredarray of TicketProjectLinkView
projectLinks[].kindrequiredstring
projectLinks[].projectNamerequiredstring
projectLinks[].projectPublicIdrequiredstring
projectLinks[].projectReferencerequiredstring
projectLinks[].publicIdrequiredstring
projectLinks[].taskPublicIdstring
publicIdrequiredstring
queueIdstring
queueNamestring
referencerequiredstring
requesterConfidencerequiredstring
requesterEmailstring
requesterIdstring
requesterNamerequiredstring
siteNamestring
slaBreachedrequiredboolean
slaNextEventAtstring (date-time) or null
slaReasonstring
statusrequiredstring
statusCategoryrequiredstring
statusNamerequiredstring
subcategorystring
subjectrequiredstring
tagsrequiredarray of string
typerequiredstring
unreadrequiredboolean
updatedAtrequiredstring (date-time)
Terminal window
# Sign in first. outpost_console is a session cookie, so send it with every request.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X POST 'https://depot.example.com/api/v1/tickets/<ticketID>/verify-sender' \
-H 'X-CSRF-Token: <csrf-token>' \
-H 'Accept: application/json' \
-b 'outpost_console=<console-session>'

Content is licensed CC BY 4.0. Code samples are MIT. Outpost and the Outpost mark are trademarks of Outpost Business Solutions, PBC and are not covered by either license.