curl --request POST \
--url https://api.upliftai.org/v1/contact-sources/{sourceId}/preview \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.upliftai.org/v1/contact-sources/{sourceId}/preview"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.upliftai.org/v1/contact-sources/{sourceId}/preview', 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/contact-sources/{sourceId}/preview",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
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/contact-sources/{sourceId}/preview"
req, _ := http.NewRequest("POST", 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.post("https://api.upliftai.org/v1/contact-sources/{sourceId}/preview")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.upliftai.org/v1/contact-sources/{sourceId}/preview")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"summary": {
"willBeCalled": 2,
"excluded": {
"invalidPhone": 1,
"missingName": 0,
"duplicate": 1,
"dnc": 0,
"recentlyCalled": 0
},
"errors": [
{
"row": 4,
"issue": "invalidPhone",
"value": "0300-999"
},
{
"row": 5,
"issue": "duplicate",
"value": "03001234567"
}
]
},
"detectedMapping": {
"nameColumn": "Full Name",
"phoneColumn": "Mobile",
"attributeColumns": [
"City",
"Property Type"
]
},
"sample": [
{
"name": "عائشہ صدیقی",
"phone": "03001234567",
"attributes": {
"City": "لاہور",
"Property Type": "5 مرلہ گھر"
}
},
{
"name": "بلال احمد",
"phone": "+923215557788",
"attributes": {
"City": "کراچی",
"Property Type": "اپارٹمنٹ"
}
}
],
"total": 4,
"columns": [
"Full Name",
"Mobile",
"City",
"Property Type"
],
"mappingIssues": []
}{
"message": "Connection 6b1f90c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx is not a Google Sheets connection",
"error": "Bad Request",
"statusCode": 400
}{
"message": "invalid authorization",
"error": "Unauthorized",
"statusCode": 401
}{
"message": "Forbidden resource",
"error": "Forbidden",
"statusCode": 403
}{
"message": "Contact source not found: 00000000-0000-4000-8000-000000000000",
"error": "Not Found",
"statusCode": 404
}{
"statusCode": 500,
"message": "Internal server error"
}Re-check a registered sheet
See what a registered source’s sheet would produce for a campaign right now. It re-reads the sheet live with the stored ref and mapping, and persists nothing — worth a run before you launch against a source you registered days ago. To try a different mapping, use /contact-sources/preview.
curl --request POST \
--url https://api.upliftai.org/v1/contact-sources/{sourceId}/preview \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.upliftai.org/v1/contact-sources/{sourceId}/preview"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.upliftai.org/v1/contact-sources/{sourceId}/preview', 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/contact-sources/{sourceId}/preview",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
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/contact-sources/{sourceId}/preview"
req, _ := http.NewRequest("POST", 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.post("https://api.upliftai.org/v1/contact-sources/{sourceId}/preview")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.upliftai.org/v1/contact-sources/{sourceId}/preview")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"summary": {
"willBeCalled": 2,
"excluded": {
"invalidPhone": 1,
"missingName": 0,
"duplicate": 1,
"dnc": 0,
"recentlyCalled": 0
},
"errors": [
{
"row": 4,
"issue": "invalidPhone",
"value": "0300-999"
},
{
"row": 5,
"issue": "duplicate",
"value": "03001234567"
}
]
},
"detectedMapping": {
"nameColumn": "Full Name",
"phoneColumn": "Mobile",
"attributeColumns": [
"City",
"Property Type"
]
},
"sample": [
{
"name": "عائشہ صدیقی",
"phone": "03001234567",
"attributes": {
"City": "لاہور",
"Property Type": "5 مرلہ گھر"
}
},
{
"name": "بلال احمد",
"phone": "+923215557788",
"attributes": {
"City": "کراچی",
"Property Type": "اپارٹمنٹ"
}
}
],
"total": 4,
"columns": [
"Full Name",
"Mobile",
"City",
"Property Type"
],
"mappingIssues": []
}{
"message": "Connection 6b1f90c4-xxxx-xxxx-xxxx-xxxxxxxxxxxx is not a Google Sheets connection",
"error": "Bad Request",
"statusCode": 400
}{
"message": "invalid authorization",
"error": "Unauthorized",
"statusCode": 401
}{
"message": "Forbidden resource",
"error": "Forbidden",
"statusCode": 403
}{
"message": "Contact source not found: 00000000-0000-4000-8000-000000000000",
"error": "Not Found",
"statusCode": 404
}{
"statusCode": 500,
"message": "Internal server error"
}Authorizations
Project API key (sk_api_…).
Path Parameters
The sourceId returned when the source was registered.
Response
The sheet as it reads right now.
What the import kept and dropped.
Show child attributes
Show child attributes
The columns actually used, after applying mapping. When a name was joined from two columns, nameColumn reads First Name + Last Name.
Show child attributes
Show child attributes
The first ten contacts that would be dialed.
10Show child attributes
Show child attributes
Rows read, before validation.
The header row as parsed — what a mapping override chooses from. Absent for free-form paste, which has no headers.
Non-empty means column detection failed. An unmapped phone column then shows up as every row invalidPhone with an empty value.
phoneColumnNotFound, nameColumnNotFound 