Conversations API
The Conversations API manages replies, comments, and notes within tickets. A conversation represents a single message in the ticket thread.
Conversation Object
{
id: string; // UUID
ticket_id: string; // UUID of parent ticket
author_id: string; // UUID of message author
content: object; // Rich text content (TipTap JSON)
content_text: string; // Plain text version
content_html?: string; // HTML version
type: string; // comment, note, email, sms
internal: boolean; // Whether this is an internal note
parent_id?: string; // UUID for threaded replies
translated_content?: object; // Translated TipTap JSON (for outgoing)
translated_content_text?: string;
translated_content_html?: string;
metadata?: object; // Additional metadata
attachments?: Attachment[]; // Array of file attachments
created_at: string; // ISO timestamp
updated_at: string; // ISO timestamp
deleted_at?: string; // ISO timestamp (soft delete)
// Joined relations
author?: {
name: string;
email: string;
avatar_url?: string;
};
}
Type Values
| Type | Description |
|---|---|
comment | Standard customer-visible reply |
note | Internal note (only visible to agents) |
email | Reply sent via email channel |
sms | Reply sent via SMS channel |
List Conversations
Retrieve all conversations for a ticket, ordered chronologically.
Procedure: conversations.list
Authentication: Required
Input:
{
ticketId: string; // UUID of the ticket
}
Example:
curl -X GET "https://your-domain.com/api/trpc/conversations.list?input=%7B%22ticketId%22:%22uuid-here%22%7D" \
-H "Cookie: your-session-cookie"
Response:
{
"result": {
"data": {
"json": [
{
"id": "uuid",
"ticket_id": "ticket-uuid",
"author_id": "user-uuid",
"content": {
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{"type": "text", "text": "Thank you for reaching out..."}
]
}
]
},
"content_text": "Thank you for reaching out...",
"type": "comment",
"internal": false,
"author": {
"name": "Support Agent",
"email": "agent@company.com",
"avatar_url": "https://..."
},
"attachments": [],
"created_at": "2024-01-15T10:35:00.000Z"
}
]
}
}
}
Notes:
- Results are ordered by
created_atascending (oldest first) - Soft-deleted conversations are excluded
- Includes author details and attachments
Create Conversation
Add a new reply or note to a ticket.
Procedure: conversations.create
Authentication: Required
Input:
{
ticketId: string; // Required, ticket UUID
content: object; // Required, rich text content (TipTap JSON)
contentText: string; // Required, plain text version
contentHtml?: string; // Optional HTML version
type?: 'comment' | 'note' | 'email' | 'sms'; // default: comment
internal?: boolean; // default: false
parentId?: string; // UUID for threaded replies
translateToLanguage?: string; // ISO 639-1 code for outgoing translation
}
Example - Public Reply:
curl -X POST "https://your-domain.com/api/trpc/conversations.create" \
-H "Content-Type: application/json" \
-H "Cookie: your-session-cookie" \
-d '{
"json": {
"ticketId": "ticket-uuid",
"content": {
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{"type": "text", "text": "Thank you for reaching out. I will look into this issue and get back to you shortly."}
]
}
]
},
"contentText": "Thank you for reaching out. I will look into this issue and get back to you shortly.",
"type": "comment",
"internal": false
}
}'
Example - Internal Note:
curl -X POST "https://your-domain.com/api/trpc/conversations.create" \
-H "Content-Type: application/json" \
-H "Cookie: your-session-cookie" \
-d '{
"json": {
"ticketId": "ticket-uuid",
"content": {
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{"type": "text", "text": "Escalating to tier 2 support due to complexity."}
]
}
]
},
"contentText": "Escalating to tier 2 support due to complexity.",
"type": "note",
"internal": true
}
}'
Example - Translated Reply:
curl -X POST "https://your-domain.com/api/trpc/conversations.create" \
-H "Content-Type: application/json" \
-H "Cookie: your-session-cookie" \
-d '{
"json": {
"ticketId": "ticket-uuid",
"content": {...},
"contentText": "Thank you for contacting us...",
"translateToLanguage": "es"
}
}'
Response:
{
"result": {
"data": {
"json": {
"id": "uuid",
"ticket_id": "ticket-uuid",
"author_id": "user-uuid",
"content": {...},
"content_text": "Thank you for reaching out...",
"content_html": "<p>Thank you for reaching out...</p>",
"type": "comment",
"internal": false,
"author": {
"name": "Support Agent",
"email": "agent@company.com",
"avatar_url": "https://..."
},
"created_at": "2024-01-15T10:35:00.000Z"
}
}
}
}
Side Effects:
- Updates
first_response_aton ticket if this is the first response - Sets ticket status to
pendingif public reply (waiting for customer) - Triggers
conversation.createdautomation event - Sends reply through appropriate channel (email, SMS, etc.) for public comments
- Content is sanitized to prevent XSS
- Rate limited to prevent abuse
Update Conversation
Update an existing conversation. Users can only update their own conversations.
Procedure: conversations.update
Authentication: Required
Input:
{
id: string; // Required, conversation UUID
content?: object; // Rich text content
contentText?: string; // Plain text version
contentHtml?: string; // HTML version
}
Example:
curl -X POST "https://your-domain.com/api/trpc/conversations.update" \
-H "Content-Type: application/json" \
-H "Cookie: your-session-cookie" \
-d '{
"json": {
"id": "conversation-uuid",
"content": {...},
"contentText": "Updated message content"
}
}'
Response:
{
"result": {
"data": {
"json": {
"id": "uuid",
"content": {...},
"content_text": "Updated message content",
"updated_at": "2024-01-15T11:00:00.000Z"
}
}
}
}
Notes:
- Users can only update conversations they authored
- Updates are reflected in the ticket thread
Delete Conversation
Soft delete a conversation. Users can only delete their own conversations.
Procedure: conversations.delete
Authentication: Required
Input:
{
id: string; // Conversation UUID
}
Example:
curl -X POST "https://your-domain.com/api/trpc/conversations.delete" \
-H "Content-Type: application/json" \
-H "Cookie: your-session-cookie" \
-d '{"json":{"id":"conversation-uuid"}}'
Response:
{
"result": {
"data": {
"json": {
"success": true
}
}
}
}
Notes:
- Users can only delete conversations they authored
- Soft delete - data is retained but excluded from queries
Bulk Reply
Send the same reply to multiple tickets at once. Useful for responding to similar issues.
Procedure: conversations.bulkReply
Authentication: Required (admin or agent)
Input:
{
ticketIds: string[]; // Array of ticket UUIDs (1-100)
content: object; // Rich text content (TipTap JSON)
contentText: string; // Plain text version
contentHtml?: string; // HTML version
internal?: boolean; // default: false
}
Example:
curl -X POST "https://your-domain.com/api/trpc/conversations.bulkReply" \
-H "Content-Type: application/json" \
-H "Cookie: your-session-cookie" \
-d '{
"json": {
"ticketIds": ["uuid1", "uuid2", "uuid3"],
"content": {
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{"type": "text", "text": "We have released a fix for this issue. Please update to the latest version."}
]
}
]
},
"contentText": "We have released a fix for this issue. Please update to the latest version.",
"internal": false
}
}'
Response:
{
"result": {
"data": {
"json": {
"success": true,
"repliedCount": 3
}
}
}
}
Side Effects:
- Creates a conversation on each ticket
- Updates
first_response_aton tickets without prior responses - Sets ticket status to
pendingfor public replies - Sends replies through appropriate channels
- Triggers
conversation.createdautomation events - Rate limited to prevent abuse
Notes:
- Maximum 100 tickets per bulk operation
- Only tickets in the user's organization are processed
- Soft-deleted tickets are skipped
- Agent cannot send to their own tickets
Translation Support
Relay supports automatic translation for both incoming and outgoing messages.
Outgoing Translation
When creating a conversation with translateToLanguage, the content is translated before being sent to the customer:
{
ticketId: "...",
content: {...},
contentText: "Thank you for your message",
translateToLanguage: "es" // Translate to Spanish
}
The original English content is stored in content, content_text, and content_html.
The translated content is stored in translated_content, translated_content_text, and translated_content_html.
When sending through channels (email, etc.), the translated content is used if available.
Supported Languages
Translation supports all major languages. Common language codes:
| Code | Language |
|---|---|
en | English |
es | Spanish |
fr | French |
de | German |
it | Italian |
pt | Portuguese |
ja | Japanese |
ko | Korean |
zh | Chinese |
ar | Arabic |
hi | Hindi |
ru | Russian |
Rate Limits
| Operation | Limit |
|---|---|
| Create conversation | 100 per minute per user |
| Bulk reply | 10 per minute per user |
Webhooks
The following webhook event is available for conversations:
| Event | Description |
|---|---|
conversation.created | Triggered when a conversation is created |
Event payload includes:
ticketId: Parent ticket UUIDticketNumber: Human-readable ticket numbercommentText: Plain text contentchannel: The conversation type/channelisPublic: Whether the conversation is visible to customers
See Webhooks for configuration details.