Ask Sortd to analyse an email thread (smart status, urgency, sentiment). It's cached-or-enqueue: a cached result returns instantly; otherwise you get a job to poll.
Needs a key with ai.classify. thread_id is the provider (Gmail/Outlook) thread id.
# curl
curl -X POST "https://api.sortd.com/v2/ai/classify-thread" \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{ "thread_id": "<thread_id>" }'
If the analysis is cached you get 200 with the result directly. If not, you get 202 Accepted with a job to poll (typically ready in 10–30s):
{
"data": { "status": "queued", "job_id": "job_…", "poll_url": "https://api.sortd.com/v2/ai/jobs/job_…" },
"meta": { "request_id": "req_…" }
}
Follow poll_url (i.e. GET /ai/jobs/{job_id}) until status is no longer queued/processing.
curl "https://api.sortd.com/v2/ai/jobs/job_…" \
-H "Authorization: Bearer sk_live_…"
// JavaScript — request, then poll if needed
async function classify(threadId) {
const start = await fetch("https://api.sortd.com/v2/ai/classify-thread", {
method: "POST",
headers: { Authorization: "Bearer sk_live_…", "Content-Type": "application/json" },
body: JSON.stringify({ thread_id: threadId }),
});
let body = await start.json();
if (start.status !== 202) return body.data; // cached — done
const jobUrl = "https://api.sortd.com" + body.data.poll_url;
for (let i = 0; i < 10; i++) {
await new Promise((r) => setTimeout(r, 3000)); // wait 3s between polls
const res = await fetch(jobUrl, { headers: { Authorization: "Bearer sk_live_…" } });
body = await res.json();
if (body.data.status !== "queued" && body.data.status !== "processing") return body.data;
}
throw new Error("classification timed out");
}
# Python — request, then poll if needed
import requests, time
H = {"Authorization": "Bearer sk_live_…"}
start = requests.post("https://api.sortd.com/v2/ai/classify-thread",
headers=H, json={"thread_id": "<thread_id>"})
body = start.json()
if start.status_code == 202:
job_url = "https://api.sortd.com" + body["data"]["poll_url"]
for _ in range(10):
time.sleep(3)
body = requests.get(job_url, headers=H).json()
if body["data"]["status"] not in ("queued", "processing"):
break
result = body["data"]
The finished job (or the cached 200) carries the analysis. You can also re-read cached analyses any time with GET /ai/analyses?thread_id=<thread_id>.
Tip: classification is per-thread and cached, so it's cheap to ask again — don't re-poll a thread you've already classified; read /ai/analyses instead.
Next: receive webhooks.