curl --request GET \
--url https://api.getoneprofile.ai/inbox/threads/ \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.getoneprofile.ai/inbox/threads/"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.getoneprofile.ai/inbox/threads/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.getoneprofile.ai/inbox/threads/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.getoneprofile.ai/inbox/threads/"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.getoneprofile.ai/inbox/threads/")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.getoneprofile.ai/inbox/threads/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"threads": [
{
"came_back": true,
"channel": "email",
"contact_email": "<string>",
"contact_key": "<string>",
"contact_name": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"follow_up_expected": true,
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"is_bounce": true,
"is_done": true,
"is_out_of_office": true,
"is_unread": true,
"label_ids": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"last_message_at": "2023-11-07T05:31:56Z",
"last_snippet": "<string>",
"listed_at": "2023-11-07T05:31:56Z",
"mailbox_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"message_count": 123,
"sequence_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"step_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"subject": "<string>",
"updated_at": "2023-11-07T05:31:56Z",
"can_reply_on_linkedin": false,
"contact_linkedin_url": "<string>",
"contact_replied": true,
"done_at": "2023-11-07T05:31:56Z",
"enrolment_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"has_pending_draft": false,
"linkedin_account_status": "pending",
"linkedin_checkpoint_status": "ok",
"linkedin_last_seen_at": "2023-11-07T05:31:56Z",
"linkedin_presence": "active",
"linkedin_queue_expiry_days": 123,
"linkedin_sender_profile_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"match_excerpt": "<string>",
"returns_at": "2023-11-07T05:31:56Z",
"snoozed_until": "2023-11-07T05:31:56Z",
"stop_reason": "reply"
}
],
"total": 123
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"detail": "<string>",
"issues": [
{
"input": "<string>",
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"detail": "<string>"
}List inbox threads
Newest-first by default, unless search is set. Then it is ranked by relevance, most useful match first, and sort is ignored. sort=longest_waiting reads the same list from the other end, oldest activity first, which is how a reply that has been sitting unanswered for three days gets to the top. Auto-replies and bounces live in their own views; unlabelled is the work queue: real threads nobody and no classifier has described yet. search runs full-text over every message plus the contact’s name and address. channel and the last_message_at__after / last_message_at__before bounds narrow the list; both bounds are inclusive. The working views (all, unlabelled, needs_approval) list only conversations the contact wrote into: a send nobody answered is not in the inbox. all and unlabelled list only those still waiting on us: a reply with no answer yet, an unread conversation, a reminder that went off, or an answer of ours that went three business days unanswered (came_back, returns_at) when the verdict on their latest reply does not say the conversation is over. Once we answer, a conversation moves out and stays in sent; one marked done (is_done) stays out until a new message reaches us. A search or a label_id reads every conversation the contact wrote into, waiting or not. Each row’s listed_at is the moment it sorts by. out_of_office, bounces and reminders list what a machine wrote or the person snoozed. sent lists every conversation something of ours went out in, a sequence step or a reply, on email or LinkedIn, answered or not and whatever became of it since; a LinkedIn reply still queued for the browser, or one that failed, has not gone out. A send nobody answered never lights the unread badge. Each row’s contact_replied says whether the contact has written back. reply_state=replied keeps the conversations we answered after the contact’s latest reply, by a person or the agent; reply_state=not_replied keeps the ones whose latest reply is still the last word. all_mail lists every conversation, whatever became of it: the place a conversation marked done is found.
curl --request GET \
--url https://api.getoneprofile.ai/inbox/threads/ \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.getoneprofile.ai/inbox/threads/"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.getoneprofile.ai/inbox/threads/', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.getoneprofile.ai/inbox/threads/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.getoneprofile.ai/inbox/threads/"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.getoneprofile.ai/inbox/threads/")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.getoneprofile.ai/inbox/threads/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"threads": [
{
"came_back": true,
"channel": "email",
"contact_email": "<string>",
"contact_key": "<string>",
"contact_name": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"follow_up_expected": true,
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"is_bounce": true,
"is_done": true,
"is_out_of_office": true,
"is_unread": true,
"label_ids": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"last_message_at": "2023-11-07T05:31:56Z",
"last_snippet": "<string>",
"listed_at": "2023-11-07T05:31:56Z",
"mailbox_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"message_count": 123,
"sequence_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"step_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"subject": "<string>",
"updated_at": "2023-11-07T05:31:56Z",
"can_reply_on_linkedin": false,
"contact_linkedin_url": "<string>",
"contact_replied": true,
"done_at": "2023-11-07T05:31:56Z",
"enrolment_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"has_pending_draft": false,
"linkedin_account_status": "pending",
"linkedin_checkpoint_status": "ok",
"linkedin_last_seen_at": "2023-11-07T05:31:56Z",
"linkedin_presence": "active",
"linkedin_queue_expiry_days": 123,
"linkedin_sender_profile_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"match_excerpt": "<string>",
"returns_at": "2023-11-07T05:31:56Z",
"snoozed_until": "2023-11-07T05:31:56Z",
"stop_reason": "reply"
}
],
"total": 123
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"detail": "<string>",
"issues": [
{
"input": "<string>",
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"detail": "<string>"
}Authorizations
Query Parameters
^(all|unlabelled|needs_approval|out_of_office|bounces|reminders|sent|all_mail)$Whether the contact's latest reply has had an answer from us.
A filter over the working inbox, where every conversation is one the contact answered. REPLIED: an answer of ours went out after their latest reply, written by a person or by the agent. A LinkedIn reply queued for the browser counts once nothing waits on a person's approval for it (a person sent it, or its task was approved); one still waiting on Tasks, a failed one and a forward to somebody else do not. NOT_REPLIED: their latest reply is still the last word. Only a genuine reply asks for an answer, so an auto-reply or a bounce arriving after our answer leaves a conversation REPLIED, and a thread whose only inbound mail is automatic is no conversation at all: the inbox does not list it, so neither state does.
replied, not_replied 100100100Which surface a conversation happens on.
Threads are contact-scoped, not channel-scoped, so this says how a thread is REACHED rather than partitioning the inbox: a reply arrives, is classified and stops the cadence identically either way, and only the send path differs.
email, linkedin The order a working inbox is read in.
NEWEST is the default and what every mail client does. LONGEST_WAITING is the one a sales team actually triages by: a reply that came in on Monday and still has no answer on Thursday is the most expensive thing in the list, and newest-first buries it under everything that has arrived since. Smartlead builds its whole SLA view on this ordering, and we had no way to reach it: the list was newest-first with no alternative.
Deliberately two named READINGS rather than a generic field+direction pair.
"Longest waiting" is not last_message_at asc: an expired snooze lifts a
thread to its wake-up time, so both orderings sort the same
computed instant, and exposing the raw column would let a caller ask for an
order that disagrees with the one the list actually uses.
newest, longest_waiting, positives_first, sequence 2551 <= x <= 100x >= 0Was this page helpful?