# The id is percent-encoded: # becomes %23, + becomes %2B
curl 'https://api.upliftai.org/v1/realtime-assistants/sessions/7b2e91c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx%23%2B923001234567%23a2' \
-H 'Authorization: Bearer <token>'import requests
from urllib.parse import quote
# Campaign call ids carry # and +, so always encode the id in the path
session_id = "7b2e91c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a2"
url = f"https://api.upliftai.org/v1/realtime-assistants/sessions/{quote(session_id, safe='')}"
response = requests.get(url, headers={"Authorization": "Bearer <token>"})
print(response.json())
const options = { method: 'GET', headers: { Authorization: 'Bearer <token>' } }
// Campaign call ids carry # and +, so always encode the id in the path
const sessionId = '7b2e91c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a2'
fetch(`https://api.upliftai.org/v1/realtime-assistants/sessions/${encodeURIComponent(sessionId)}`, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err))
<?php
// Campaign call ids carry # and +, so always encode the id in the path
$sessionId = '7b2e91c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a2';
$url = 'https://api.upliftai.org/v1/realtime-assistants/sessions/' . rawurlencode($sessionId);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer <token>']);
echo curl_exec($ch);
package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
// Campaign call ids carry # and +, so always encode the id in the path
sessionID := "7b2e91c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a2"
endpoint := "https://api.upliftai.org/v1/realtime-assistants/sessions/" + url.PathEscape(sessionID)
req, _ := http.NewRequest("GET", endpoint, 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))
}
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
// Campaign call ids carry # and +, so always encode the id in the path
String sessionId = "7b2e91c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a2";
String url = "https://api.upliftai.org/v1/realtime-assistants/sessions/"
+ URLEncoder.encode(sessionId, StandardCharsets.UTF_8);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer <token>")
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
require 'uri'
require 'net/http'
url = URI("https://api.upliftai.org/v1/realtime-assistants/sessions/{sessionId}")
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{
"sessionId": "25661352-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"realtimeAssistantId": "452dda41-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"organizationId": "a12b7e74-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"projectId": "c782a4ec-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"channel": "telephony",
"direction": "outbound",
"state": "completed",
"connected": true,
"toNumber": "+923001234567",
"fromNumber": "+924232591000",
"roomName": "call-25661352-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"participantIdentity": "callee-25661352",
"transportProvider": "twilio",
"variables": {
"patientName": "عائشہ صدیقی",
"appointmentTime": "کل صبح 11 بجے"
},
"createdAt": "2026-08-16T18:55:22.677Z",
"ringingAt": "2026-08-16T18:55:30.758Z",
"connectedAt": "2026-08-16T18:55:36.927Z",
"answeredAt": "2026-08-16T18:55:37.641Z",
"endedAt": "2026-08-16T18:56:17.411Z",
"durationSec": 40
}Get a session's status
Session metadata — where one browser session or phone call stands right now. Poll this while a call is in flight; once it ends, read the session detail for the transcript, tool calls, and grade.
# The id is percent-encoded: # becomes %23, + becomes %2B
curl 'https://api.upliftai.org/v1/realtime-assistants/sessions/7b2e91c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx%23%2B923001234567%23a2' \
-H 'Authorization: Bearer <token>'import requests
from urllib.parse import quote
# Campaign call ids carry # and +, so always encode the id in the path
session_id = "7b2e91c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a2"
url = f"https://api.upliftai.org/v1/realtime-assistants/sessions/{quote(session_id, safe='')}"
response = requests.get(url, headers={"Authorization": "Bearer <token>"})
print(response.json())
const options = { method: 'GET', headers: { Authorization: 'Bearer <token>' } }
// Campaign call ids carry # and +, so always encode the id in the path
const sessionId = '7b2e91c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a2'
fetch(`https://api.upliftai.org/v1/realtime-assistants/sessions/${encodeURIComponent(sessionId)}`, options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err))
<?php
// Campaign call ids carry # and +, so always encode the id in the path
$sessionId = '7b2e91c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a2';
$url = 'https://api.upliftai.org/v1/realtime-assistants/sessions/' . rawurlencode($sessionId);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer <token>']);
echo curl_exec($ch);
package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
// Campaign call ids carry # and +, so always encode the id in the path
sessionID := "7b2e91c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a2"
endpoint := "https://api.upliftai.org/v1/realtime-assistants/sessions/" + url.PathEscape(sessionID)
req, _ := http.NewRequest("GET", endpoint, 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))
}
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
// Campaign call ids carry # and +, so always encode the id in the path
String sessionId = "7b2e91c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a2";
String url = "https://api.upliftai.org/v1/realtime-assistants/sessions/"
+ URLEncoder.encode(sessionId, StandardCharsets.UTF_8);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer <token>")
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
require 'uri'
require 'net/http'
url = URI("https://api.upliftai.org/v1/realtime-assistants/sessions/{sessionId}")
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{
"sessionId": "25661352-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"realtimeAssistantId": "452dda41-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"organizationId": "a12b7e74-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"projectId": "c782a4ec-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"channel": "telephony",
"direction": "outbound",
"state": "completed",
"connected": true,
"toNumber": "+923001234567",
"fromNumber": "+924232591000",
"roomName": "call-25661352-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"participantIdentity": "callee-25661352",
"transportProvider": "twilio",
"variables": {
"patientName": "عائشہ صدیقی",
"appointmentTime": "کل صبح 11 بجے"
},
"createdAt": "2026-08-16T18:55:22.677Z",
"ringingAt": "2026-08-16T18:55:30.758Z",
"connectedAt": "2026-08-16T18:55:36.927Z",
"answeredAt": "2026-08-16T18:55:37.641Z",
"endedAt": "2026-08-16T18:56:17.411Z",
"durationSec": 40
}Authorizations
Project API key (sk_api_…).
Path Parameters
Returned as sessionId by the call dispatch, or as callId on a campaign's calls list, like 7b2e91c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a2. Always percent-encode it in the path, encodeURIComponent(sessionId) in JavaScript. Campaign call ids embed # and +, and an unencoded # truncates the id.
Query Parameters
Adds audioUrl, a recording link valid for one hour. Any value switches it on, including false, so omit the parameter instead. The link is signed without checking a recording exists, so it 404s on calls that were never recorded.
Response
The session as it stands right now.
One conversation — a browser session or a phone call.
The assistant that ran the session. Still returned after that assistant is deleted.
web, telephony, whatsapp Browser sessions are inbound by convention — the user opens them.
inbound, outbound Each channel walks its own path:
- Web session:
created→active→completed - Phone call:
dispatched→dialing→ringing→answered→completed, orfailed
The dial hops come from the carrier, which may skip any of them.
created, dispatched, dialing, ringing, answered, active, completed, failed Whether audio was ever bridged — false for everything up to and including ringing.
Why no conversation happened; present exactly when connected is false. An in-flight call reads no_answer simply because it has not connected yet, so treat it as a verdict only once state is failed.
busy, no_answer, unreachable, voicemail, silent_pickup, failed Who hung up.
callee, agent, supervisor, system E.164. Telephony only.
"+923001234567"
E.164 caller id the callee saw. Telephony only.
"+924232591000"
Display name of the person called, stamped at dial time from the campaign contact.
Server-generated, {prefix}-{sessionId}.
Identifies the human on the call: the token identity for a browser session, the SIP participant for a phone call.
Carrier that placed the call, e.g. twilio.
"twilio"
The values you supplied when the session was created, returned verbatim.
Set on calls a campaign dialed.
The campaign run that dialed this call.
The campaign contact that was dialed.
When the record was created — for an outbound call, when it was dispatched, not when it rang.
Carrier accepted the dial request. Reported by the carrier, so it can be absent even on a call that connected.
Callee's phone started ringing. Same carrier caveat as dialingAt.
Audio bridged (SIP answer).
When the callee first spoke. connectedAt set while this stays absent is a phantom answer — the line opened and nobody spoke.
Talk time, answeredAt to endedAt. Absent until the call ends, and on calls that never got an answeredAt.
Why the call failed, on state: failed. The confusable ones: no_answer rang out, unreachable never rang (phone off), silent_pickup was answered but carried no callee audio, and network_error is a carrier or trunk fault rather than anything the callee did.
wrong_number, busy, declined, no_answer, unreachable, voicemail, silent_pickup, network_error, call_failed failureReason with the carrier's SIP code appended when there is one, as in busy:486.
"busy:486"
The session ran on an inline config rather than a stored assistant.
The session was opened without an API key.
Recording link, valid one hour. Only when requested with include_audio_url.
The assistant version this session ran. Absent on sessions from before versions.
The alias the session was launched on. Absent when it was launched by an exact version number, and on sessions from before versions.
prod, draft On list rows only, with include_summary=true. Absent, not null, when there is none.
Show child attributes
Show child attributes
