curl --request GET \
--url https://api.upliftai.org/v1/campaigns/{campaignId}/calls \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.upliftai.org/v1/campaigns/{campaignId}/calls"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.upliftai.org/v1/campaigns/{campaignId}/calls', 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.upliftai.org/v1/campaigns/{campaignId}/calls",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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.upliftai.org/v1/campaigns/{campaignId}/calls"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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.upliftai.org/v1/campaigns/{campaignId}/calls")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.upliftai.org/v1/campaigns/{campaignId}/calls")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"calls": [
{
"callId": "7c1f9ab4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a1",
"contactId": "+923001234567",
"name": "عائشہ صدیقی",
"phone": "+923001234567",
"state": "done",
"attempts": 1,
"nextAttemptAt": 1787030462711,
"connected": true,
"startedAt": "2026-08-18T05:16:02.711Z",
"durationSec": 74,
"score": 82,
"sentiment": "happy"
},
{
"callId": "7c1f9ab4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923214455661#a2",
"contactId": "+923214455661",
"name": "بلال احمد",
"phone": "+923214455661",
"state": "retry_wait",
"attempts": 2,
"nextAttemptAt": 1787034062711,
"outcome": "busy",
"connected": false,
"startedAt": "2026-08-18T05:31:44.902Z",
"endReason": "busy:486",
"failureReason": "busy",
"failureReasonWithCode": "busy:486"
},
{
"contactId": "+923339988774",
"name": "فرحان قریشی",
"phone": "+923339988774",
"state": "queued",
"attempts": 0,
"nextAttemptAt": 1787030400000
}
],
"nextCursor": "eyJjYW1wYWlnbklkIjoiN2MxZjlhYjQtxxxx"
}List a campaign's calls
One row per enrolled contact per campaign run, showing that contact’s latest attempt — never-dialed contacts included. Earlier attempts collapse into the latest one, and a relaunch or recurrence can put the same contactId on the page twice. Rows come in no particular order, so don’t read the top of the list as the most recent. Where callId is present it is the session id. Pass it to the session detail for that call’s transcript and recording.
Note: Scores, conversions, and sentiment are computed by LLMs — best effort, with room to be wrong. We are continuously closing the tracking gaps, but for sensitive workloads we recommend running your own analysis on the transcripts delivered over webhooks.
curl --request GET \
--url https://api.upliftai.org/v1/campaigns/{campaignId}/calls \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.upliftai.org/v1/campaigns/{campaignId}/calls"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.upliftai.org/v1/campaigns/{campaignId}/calls', 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.upliftai.org/v1/campaigns/{campaignId}/calls",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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.upliftai.org/v1/campaigns/{campaignId}/calls"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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.upliftai.org/v1/campaigns/{campaignId}/calls")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.upliftai.org/v1/campaigns/{campaignId}/calls")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"calls": [
{
"callId": "7c1f9ab4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a1",
"contactId": "+923001234567",
"name": "عائشہ صدیقی",
"phone": "+923001234567",
"state": "done",
"attempts": 1,
"nextAttemptAt": 1787030462711,
"connected": true,
"startedAt": "2026-08-18T05:16:02.711Z",
"durationSec": 74,
"score": 82,
"sentiment": "happy"
},
{
"callId": "7c1f9ab4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923214455661#a2",
"contactId": "+923214455661",
"name": "بلال احمد",
"phone": "+923214455661",
"state": "retry_wait",
"attempts": 2,
"nextAttemptAt": 1787034062711,
"outcome": "busy",
"connected": false,
"startedAt": "2026-08-18T05:31:44.902Z",
"endReason": "busy:486",
"failureReason": "busy",
"failureReasonWithCode": "busy:486"
},
{
"contactId": "+923339988774",
"name": "فرحان قریشی",
"phone": "+923339988774",
"state": "queued",
"attempts": 0,
"nextAttemptAt": 1787030400000
}
],
"nextCursor": "eyJjYW1wYWlnbklkIjoiN2MxZjlhYjQtxxxx"
}Authorizations
Project API key (sk_api_…).
Path Parameters
Query Parameters
Rows per page. No maximum, though response size caps every page whether you set this or not.
x >= 1The previous page's nextCursor, verbatim.
Adds each call's summary to its row, up to about 1 KB each. Must be exactly true or false, anything else is a 400. A row with no summary leaves the key out: a call that never connected, one not summarised yet, or one from before summaries.
