Skip to content

Messages API

This content is not available in your language yet.

Manage messages within tickets—both customer replies and internal notes.

Endpoints

MethodEndpointDescription
GET/tickets/:ticket_id/messagesList messages
POST/tickets/:ticket_id/messagesCreate message
GET/tickets/:ticket_id/messages/:idGet message
DELETE/tickets/:ticket_id/messages/:idDelete message

List Messages

Terminal window
GET /api/v1/tickets/:ticket_id/messages

Query Parameters

ParameterTypeDescription
include_internalbooleanInclude internal notes (default: true)

Response

{
"data": [
{
"id": "msg-uuid-1",
"body": "I cannot login to my dashboard since this morning.",
"body_html": "<p>I cannot login to my dashboard since this morning.</p>",
"is_internal": false,
"direction": "inbound",
"sender": {
"name": "John Doe",
"email": "john@example.com"
},
"attachments": [
{
"id": "att-uuid-1",
"filename": "screenshot.png",
"content_type": "image/png",
"size": 245678,
"url": "https://..."
}
],
"created_at": "2024-01-15T10:30:00Z"
},
{
"id": "msg-uuid-2",
"body": "Thanks for reaching out. Let me check your account...",
"is_internal": false,
"direction": "outbound",
"sender": {
"name": "Jane Agent",
"email": "jane@company.com"
},
"attachments": [],
"created_at": "2024-01-15T11:15:00Z"
}
]
}

Create Message

Terminal window
POST /api/v1/tickets/:ticket_id/messages

Request Body

{
"body": "Thanks for reaching out. I've reset your password...",
"is_internal": false,
"send_email": true
}
FieldTypeRequiredDescription
bodystringYesMessage content (plain text or HTML)
is_internalbooleanNoInternal note if true (default: false)
send_emailbooleanNoSend email notification (default: true for public)

Response

{
"data": {
"id": "msg-uuid-3",
"body": "Thanks for reaching out. I've reset your password...",
"is_internal": false,
"direction": "outbound",
"sender": {
"name": "Jane Agent",
"email": "jane@company.com"
},
"email_sent": true,
"created_at": "2024-01-15T11:30:00Z"
}
}

Internal Notes

Create an internal note (not visible to customers):

{
"body": "Checked the logs - looks like a password issue.",
"is_internal": true
}

Internal notes:

  • Are visible only to team members
  • Never send emails
  • Appear differently in the UI
  • Are included in the activity timeline

Get Message

Terminal window
GET /api/v1/tickets/:ticket_id/messages/:id

Response

Full message object:

{
"data": {
"id": "msg-uuid-1",
"body": "...",
"body_html": "...",
"is_internal": false,
"direction": "inbound",
"sender": { ... },
"attachments": [ ... ],
"email_message_id": "<msg-id@mail.example.com>",
"created_at": "2024-01-15T10:30:00Z"
}
}

Delete Message

Terminal window
DELETE /api/v1/tickets/:ticket_id/messages/:id

Response

204 No Content

Attachments

Upload Attachment

Attachments are uploaded separately and referenced in messages:

Terminal window
POST /api/v1/attachments
Content-Type: multipart/form-data
file: <binary>

Response

{
"data": {
"id": "att-uuid",
"filename": "document.pdf",
"content_type": "application/pdf",
"size": 123456,
"url": "https://..."
}
}

Include in Message

Reference attachments when creating a message:

{
"body": "Please see the attached document.",
"attachment_ids": ["att-uuid-1", "att-uuid-2"]
}

Email Integration

Inbound Emails

When emails arrive at connected mailboxes:

  1. New sender → new ticket with first message
  2. Reply to existing → new message on that ticket
  3. Attachments are extracted and stored
  4. HTML is preserved, plain text version generated

Outbound Emails

When send_email: true:

  1. Message is sent via connected mailbox
  2. Proper threading headers are added
  3. Email status is tracked (email_sent: true/false)

Message Direction

DirectionMeaning
inboundFrom customer (via email or portal)
outboundFrom team member to customer

Internal notes don’t have a direction—they’re internal only.

Error Codes

CodeDescription
TICKET_NOT_FOUNDTicket doesn’t exist
MESSAGE_NOT_FOUNDMessage doesn’t exist
EMPTY_BODYMessage body is required
EMAIL_SEND_FAILEDFailed to send email
ATTACHMENT_NOT_FOUNDReferenced attachment doesn’t exist