Ndoto Docs

Conversations

Create, list, update, and manage conversations via the API

Conversations

Conversations are the core resource in Ndoto. Every customer interaction is a conversation.

Base path: /api/v1/accounts/:account_id/conversations


List conversations

Returns a paginated list of conversations in your account.

GET /api/v1/accounts/:account_id/conversations

Query parameters

ParameterTypeRequiredDescription
pagenumberNoPage number. Default: 1
sortstringNoSort field. Options: created_at, updated_at, last_activity_at
statusstringNoFilter by status: open, resolved, pending, snoozed
assignee_typestringNoFilter: me, unassigned, all, assigned
labelsstringNoFilter by label title

Response

{
  "data": {
    "meta": {
      "all_count": 120,
      "mine_count": 30,
      "unassigned_count": 15,
      "assigned_count": 75
    },
    "payload": [
      {
        "id": 1,
        "inbox_id": 2,
        "status": "open",
        "priority": "high",
        "unread_count": 3,
        "created_at": 1712000000,
        "contact": {
          "id": 10,
          "name": "Jane Doe",
          "email": "[email protected]"
        },
        "meta": {
          "assignee": { "id": 5, "name": "Agent Name" },
          "team": { "id": 1, "name": "Support" }
        }
      }
    ]
  }
}
const response = await fetch(
  'https://app.usendoto.com/api/v1/accounts/1/conversations?status=open&page=1',
  {
    headers: {
      'api_access_token': 'YOUR_TOKEN',
      'Content-Type': 'application/json',
    },
  }
);
const data = await response.json();
console.log(data);
import requests

response = requests.get(
    'https://app.usendoto.com/api/v1/accounts/1/conversations',
    headers={'api_access_token': 'YOUR_TOKEN'},
    params={'status': 'open', 'page': 1},
)
print(response.json())
<?php
$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => 'https://app.usendoto.com/api/v1/accounts/1/conversations?status=open&page=1',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'api_access_token: YOUR_TOKEN',
        'Content-Type: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response);
import 'package:http/http.dart' as http;
import 'dart:convert';

final response = await http.get(
  Uri.parse('https://app.usendoto.com/api/v1/accounts/1/conversations?status=open&page=1'),
  headers: {'api_access_token': 'YOUR_TOKEN'},
);
final data = jsonDecode(response.body);
print(data);
require 'net/http'
require 'json'

uri = URI('https://app.usendoto.com/api/v1/accounts/1/conversations')
uri.query = URI.encode_www_form(status: 'open', page: 1)

req = Net::HTTP::Get.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts JSON.parse(res.body)

Get a conversation

Returns a single conversation by its ID.

GET /api/v1/accounts/:account_id/conversations/:id

Path parameters

ParameterTypeRequiredDescription
account_idnumberYesYour account ID
idnumberYesConversation ID
const response = await fetch(
  'https://app.usendoto.com/api/v1/accounts/1/conversations/42',
  {
    headers: { 'api_access_token': 'YOUR_TOKEN' },
  }
);
const conversation = await response.json();
console.log(conversation);
import requests

response = requests.get(
    'https://app.usendoto.com/api/v1/accounts/1/conversations/42',
    headers={'api_access_token': 'YOUR_TOKEN'},
)
print(response.json())
<?php
$ch = curl_init('https://app.usendoto.com/api/v1/accounts/1/conversations/42');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['api_access_token: YOUR_TOKEN'],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response);
final response = await http.get(
  Uri.parse('https://app.usendoto.com/api/v1/accounts/1/conversations/42'),
  headers: {'api_access_token': 'YOUR_TOKEN'},
);
print(jsonDecode(response.body));
uri = URI('https://app.usendoto.com/api/v1/accounts/1/conversations/42')
req = Net::HTTP::Get.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts JSON.parse(res.body)

Create a conversation

Creates a new conversation.

POST /api/v1/accounts/:account_id/conversations

Body parameters

ParameterTypeRequiredDescription
inbox_idnumberYesThe inbox to create the conversation in
contact_idnumberYesThe contact this conversation belongs to
source_idstringNoExternal identifier for the conversation
assignee_idnumberNoAgent ID to assign the conversation to
team_idnumberNoTeam ID to assign the conversation to
messageobjectNoInitial message — { content: string }
additional_attributesobjectNoExtra metadata to attach
const response = await fetch(
  'https://app.usendoto.com/api/v1/accounts/1/conversations',
  {
    method: 'POST',
    headers: {
      'api_access_token': 'YOUR_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      inbox_id: 2,
      contact_id: 10,
      message: { content: 'Hello, how can I help you?' },
      assignee_id: 5,
    }),
  }
);
const conversation = await response.json();
console.log(conversation);
import requests

response = requests.post(
    'https://app.usendoto.com/api/v1/accounts/1/conversations',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={
        'inbox_id': 2,
        'contact_id': 10,
        'message': {'content': 'Hello, how can I help you?'},
        'assignee_id': 5,
    },
)
print(response.json())
<?php
$payload = json_encode([
    'inbox_id'   => 2,
    'contact_id' => 10,
    'message'    => ['content' => 'Hello, how can I help you?'],
    'assignee_id' => 5,
]);

$ch = curl_init('https://app.usendoto.com/api/v1/accounts/1/conversations');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $payload,
    CURLOPT_HTTPHEADER => [
        'api_access_token: YOUR_TOKEN',
        'Content-Type: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response);
final response = await http.post(
  Uri.parse('https://app.usendoto.com/api/v1/accounts/1/conversations'),
  headers: {
    'api_access_token': 'YOUR_TOKEN',
    'Content-Type': 'application/json',
  },
  body: jsonEncode({
    'inbox_id': 2,
    'contact_id': 10,
    'message': {'content': 'Hello, how can I help you?'},
    'assignee_id': 5,
  }),
);
print(jsonDecode(response.body));
require 'net/http'
require 'json'

uri = URI('https://app.usendoto.com/api/v1/accounts/1/conversations')
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
req['api_access_token'] = 'YOUR_TOKEN'
req.body = JSON.dump(
  inbox_id: 2,
  contact_id: 10,
  message: { content: 'Hello, how can I help you?' },
  assignee_id: 5
)

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts JSON.parse(res.body)

Update a conversation

Updates the priority or SLA policy of a conversation.

PATCH /api/v1/accounts/:account_id/conversations/:id

Body parameters

ParameterTypeRequiredDescription
prioritystringNourgent, high, medium, low
sla_policy_idnumberNoID of the SLA policy to apply
const response = await fetch(
  'https://app.usendoto.com/api/v1/accounts/1/conversations/42',
  {
    method: 'PATCH',
    headers: {
      'api_access_token': 'YOUR_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ priority: 'urgent' }),
  }
);
const updated = await response.json();
console.log(updated);
response = requests.patch(
    'https://app.usendoto.com/api/v1/accounts/1/conversations/42',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'priority': 'urgent'},
)
print(response.json())
<?php
$ch = curl_init('https://app.usendoto.com/api/v1/accounts/1/conversations/42');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_POSTFIELDS => json_encode(['priority' => 'urgent']),
    CURLOPT_HTTPHEADER => [
        'api_access_token: YOUR_TOKEN',
        'Content-Type: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response);
final response = await http.patch(
  Uri.parse('https://app.usendoto.com/api/v1/accounts/1/conversations/42'),
  headers: {
    'api_access_token': 'YOUR_TOKEN',
    'Content-Type': 'application/json',
  },
  body: jsonEncode({'priority': 'urgent'}),
);
print(jsonDecode(response.body));
uri = URI('https://app.usendoto.com/api/v1/accounts/1/conversations/42')
req = Net::HTTP::Patch.new(uri, 'Content-Type' => 'application/json')
req['api_access_token'] = 'YOUR_TOKEN'
req.body = JSON.dump(priority: 'urgent')

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts JSON.parse(res.body)

Toggle conversation status

Changes the status of a conversation between open, resolved, pending, and snoozed.

POST /api/v1/accounts/:account_id/conversations/:id/toggle_status

Body parameters

ParameterTypeRequiredDescription
statusstringYesopen, resolved, pending, or snoozed
snoozed_untiltimestampNoUnix timestamp — required when status is snoozed
const response = await fetch(
  'https://app.usendoto.com/api/v1/accounts/1/conversations/42/toggle_status',
  {
    method: 'POST',
    headers: {
      'api_access_token': 'YOUR_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ status: 'resolved' }),
  }
);
const result = await response.json();
console.log(result);
response = requests.post(
    'https://app.usendoto.com/api/v1/accounts/1/conversations/42/toggle_status',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'status': 'resolved'},
)
print(response.json())
<?php
$ch = curl_init('https://app.usendoto.com/api/v1/accounts/1/conversations/42/toggle_status');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode(['status' => 'resolved']),
    CURLOPT_HTTPHEADER => [
        'api_access_token: YOUR_TOKEN',
        'Content-Type: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response);
final response = await http.post(
  Uri.parse('https://app.usendoto.com/api/v1/accounts/1/conversations/42/toggle_status'),
  headers: {
    'api_access_token': 'YOUR_TOKEN',
    'Content-Type': 'application/json',
  },
  body: jsonEncode({'status': 'resolved'}),
);
print(jsonDecode(response.body));
uri = URI('https://app.usendoto.com/api/v1/accounts/1/conversations/42/toggle_status')
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
req['api_access_token'] = 'YOUR_TOKEN'
req.body = JSON.dump(status: 'resolved')

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts JSON.parse(res.body)

Assign a conversation

Assigns an agent and/or team to a conversation.

POST /api/v1/accounts/:account_id/conversations/:id/assignments

Body parameters

ParameterTypeRequiredDescription
assignee_idnumberNoAgent ID to assign
team_idnumberNoTeam ID to assign
const response = await fetch(
  'https://app.usendoto.com/api/v1/accounts/1/conversations/42/assignments',
  {
    method: 'POST',
    headers: {
      'api_access_token': 'YOUR_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ assignee_id: 5, team_id: 2 }),
  }
);
const result = await response.json();
console.log(result);
response = requests.post(
    'https://app.usendoto.com/api/v1/accounts/1/conversations/42/assignments',
    headers={'api_access_token': 'YOUR_TOKEN'},
    json={'assignee_id': 5, 'team_id': 2},
)
print(response.json())
<?php
$ch = curl_init('https://app.usendoto.com/api/v1/accounts/1/conversations/42/assignments');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode(['assignee_id' => 5, 'team_id' => 2]),
    CURLOPT_HTTPHEADER => [
        'api_access_token: YOUR_TOKEN',
        'Content-Type: application/json',
    ],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response);
final response = await http.post(
  Uri.parse('https://app.usendoto.com/api/v1/accounts/1/conversations/42/assignments'),
  headers: {
    'api_access_token': 'YOUR_TOKEN',
    'Content-Type': 'application/json',
  },
  body: jsonEncode({'assignee_id': 5, 'team_id': 2}),
);
print(jsonDecode(response.body));
uri = URI('https://app.usendoto.com/api/v1/accounts/1/conversations/42/assignments')
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
req['api_access_token'] = 'YOUR_TOKEN'
req.body = JSON.dump(assignee_id: 5, team_id: 2)

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts JSON.parse(res.body)

Search conversations

Search across conversations by content.

GET /api/v1/accounts/:account_id/conversations/search

Query parameters

ParameterTypeRequiredDescription
qstringYesSearch query
pagenumberNoPage number
const response = await fetch(
  'https://app.usendoto.com/api/v1/accounts/1/conversations/search?q=billing+issue',
  {
    headers: { 'api_access_token': 'YOUR_TOKEN' },
  }
);
const results = await response.json();
console.log(results);
response = requests.get(
    'https://app.usendoto.com/api/v1/accounts/1/conversations/search',
    headers={'api_access_token': 'YOUR_TOKEN'},
    params={'q': 'billing issue'},
)
print(response.json())
<?php
$ch = curl_init('https://app.usendoto.com/api/v1/accounts/1/conversations/search?q=billing+issue');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['api_access_token: YOUR_TOKEN'],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response);
final uri = Uri.parse('https://app.usendoto.com/api/v1/accounts/1/conversations/search')
    .replace(queryParameters: {'q': 'billing issue'});

final response = await http.get(
  uri,
  headers: {'api_access_token': 'YOUR_TOKEN'},
);
print(jsonDecode(response.body));
uri = URI('https://app.usendoto.com/api/v1/accounts/1/conversations/search')
uri.query = URI.encode_www_form(q: 'billing issue')

req = Net::HTTP::Get.new(uri)
req['api_access_token'] = 'YOUR_TOKEN'

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts JSON.parse(res.body)

On this page