Conversations

Managing customer conversations

Conversations

A conversation is a thread of messages between a visitor and your support team.

Conversation Lifecycle

OPEN → PENDING → RESOLVED → CLOSED
         ↓
      SNOOZED

Statuses

StatusDescription
openActive conversation requiring attention
pendingAwaiting customer response
snoozedTemporarily hidden, will reopen at set time
resolvedIssue addressed, can be reopened
closedPermanently closed

Viewing Conversations

Dashboard

Navigate to Support > Inbox to see all conversations.

Filtering

Filter conversations by:

  • Status (Open, Pending, Resolved, Closed)
  • Assignee
  • Inbox
  • Tags
  • Date range

Search across conversations:

  • Visitor name/email
  • Message content
  • Tags
  • Custom attributes

API Operations

List Conversations

const response = await fetch('/api/support/conversations', {
  headers: {
    'X-API-Key': 'your-api-key',
  },
});
 
const { data, meta } = await response.json();

Query parameters:

ParameterTypeDescription
statusstringFilter by status
inboxIdstringFilter by inbox
assigneeIdstringFilter by assignee
visitorIdstringFilter by visitor
pagenumberPage number
limitnumberItems per page

Get Conversation

const response = await fetch('/api/support/conversations/{conversationId}', {
  headers: {
    'X-API-Key': 'your-api-key',
  },
});
 
const { data } = await response.json();

Response:

{
  data: {
    id: 'conv-123',
    status: 'open',
    inboxId: 'inbox-123',
    visitor: {
      id: 'visitor-123',
      name: 'John Doe',
      email: 'john@example.com'
    },
    assignee: {
      id: 'user-123',
      name: 'Support Agent'
    },
    messages: [
      {
        id: 'msg-1',
        type: 'visitor',
        content: 'Hi, I need help',
        createdAt: '2024-01-15T10:00:00Z'
      },
      {
        id: 'msg-2',
        type: 'agent',
        content: 'How can I help?',
        createdAt: '2024-01-15T10:05:00Z',
        author: { id: 'user-123', name: 'Support Agent' }
      }
    ],
    tags: ['billing', 'urgent'],
    createdAt: '2024-01-15T10:00:00Z',
    updatedAt: '2024-01-15T10:05:00Z'
  }
}

Reply to Conversation

const response = await fetch('/api/support/conversations/{conversationId}/reply', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'your-api-key',
  },
  body: JSON.stringify({
    message: 'Thanks for reaching out! Let me help you with that.',
    type: 'reply' // 'reply' | 'note'
  }),
});

Add Internal Note

const response = await fetch('/api/support/conversations/{conversationId}/reply', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'your-api-key',
  },
  body: JSON.stringify({
    message: 'Customer seems confused about pricing. Escalate to sales?',
    type: 'note'
  }),
});

Internal notes are only visible to your team.

Assign Conversation

const response = await fetch('/api/support/conversations/{conversationId}/assign', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'your-api-key',
  },
  body: JSON.stringify({
    assigneeId: 'user-456'
  }),
});

Update Status

const response = await fetch('/api/support/conversations/{conversationId}', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'your-api-key',
  },
  body: JSON.stringify({
    status: 'resolved'
  }),
});

Snooze Conversation

const response = await fetch('/api/support/conversations/{conversationId}/snooze', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'your-api-key',
  },
  body: JSON.stringify({
    until: '2024-01-16T09:00:00Z'
  }),
});

Add Tags

const response = await fetch('/api/support/conversations/{conversationId}/tags', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'your-api-key',
  },
  body: JSON.stringify({
    tags: ['billing', 'urgent']
  }),
});

Remove Tag

const response = await fetch('/api/support/conversations/{conversationId}/tags/{tagId}', {
  method: 'DELETE',
  headers: {
    'X-API-Key': 'your-api-key',
  },
});

Message Types

Text Message

{
  type: 'text',
  content: 'Hello, how can I help?'
}

Attachment

{
  type: 'attachment',
  content: 'Here is the document you requested.',
  attachments: [
    {
      name: 'invoice.pdf',
      url: 'https://...',
      type: 'application/pdf',
      size: 102400
    }
  ]
}

Card/Rich Message

{
  type: 'card',
  content: {
    title: 'Order #12345',
    description: 'Your order has been shipped',
    actions: [
      { label: 'Track Package', url: 'https://...' },
      { label: 'View Order', action: 'view_order' }
    ]
  }
}

Conversation Events

Subscribe to real-time events:

// WebSocket connection
const ws = new WebSocket('wss://api.usetransactional.com/support/conversations/live');
 
ws.onmessage = (event) => {
  const { type, data } = JSON.parse(event.data);
 
  switch (type) {
    case 'conversation.created':
      console.log('New conversation:', data);
      break;
    case 'message.received':
      console.log('New message:', data);
      break;
    case 'conversation.updated':
      console.log('Conversation updated:', data);
      break;
  }
};

Webhooks

Configure webhooks for conversation events:

const response = await fetch('/api/support/webhooks', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'your-api-key',
  },
  body: JSON.stringify({
    url: 'https://your-server.com/webhook',
    events: [
      'conversation.created',
      'conversation.assigned',
      'conversation.resolved',
      'message.received'
    ]
  }),
});

Webhook Payload

{
  "event": "message.received",
  "timestamp": "2024-01-15T10:00:00Z",
  "conversation": {
    "id": "conv-123",
    "status": "open"
  },
  "message": {
    "id": "msg-123",
    "type": "visitor",
    "content": "I need help with billing"
  },
  "visitor": {
    "id": "visitor-123",
    "email": "john@example.com"
  }
}

Canned Responses

Save time with pre-written responses:

Create Canned Response

const response = await fetch('/api/support/canned-responses', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'your-api-key',
  },
  body: JSON.stringify({
    title: 'Greeting',
    shortcut: '/hello',
    content: 'Hi {{visitor.name}}! Thanks for reaching out. How can I help you today?'
  }),
});

Using Variables

Available variables in canned responses:

VariableDescription
{{visitor.name}}Visitor's name
{{visitor.email}}Visitor's email
{{agent.name}}Current agent's name
{{company.name}}Company name

Automation Rules

Automate common tasks:

Auto-Assignment

{
  trigger: 'conversation.created',
  conditions: [
    { field: 'visitor.plan', operator: 'equals', value: 'enterprise' }
  ],
  actions: [
    { type: 'assign', assigneeId: 'priority-team-id' },
    { type: 'addTag', tag: 'enterprise' }
  ]
}

Auto-Reply

{
  trigger: 'message.received',
  conditions: [
    { field: 'message.content', operator: 'contains', value: 'refund' }
  ],
  actions: [
    { type: 'reply', message: 'I see you have a question about refunds. Let me connect you with our billing team.' },
    { type: 'addTag', tag: 'refund-request' }
  ]
}

Analytics

Conversation Metrics

const response = await fetch('/api/support/analytics/conversations', {
  headers: {
    'X-API-Key': 'your-api-key',
  },
});
 
const { data } = await response.json();

Response:

{
  data: {
    totalConversations: 500,
    openConversations: 25,
    resolvedToday: 45,
    avgFirstResponseTime: 120, // seconds
    avgResolutionTime: 3600, // seconds
    csat: 4.5
  }
}

Next Steps