curl --request POST \
--url https://api.upliftai.org/v1/contact-lists/uploads/{uploadId}/preview \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"mapping": {
"nameColumn": "Name",
"phoneColumn": "B",
"attributeColumns": [
"City"
]
}
}
'import requests
url = "https://api.upliftai.org/v1/contact-lists/uploads/{uploadId}/preview"
payload = { "mapping": {
"nameColumn": "Name",
"phoneColumn": "B",
"attributeColumns": ["City"]
} }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({mapping: {nameColumn: 'Name', phoneColumn: 'B', attributeColumns: ['City']}})
};
fetch('https://api.upliftai.org/v1/contact-lists/uploads/{uploadId}/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-lists/uploads/{uploadId}/preview",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'mapping' => [
'nameColumn' => 'Name',
'phoneColumn' => 'B',
'attributeColumns' => [
'City'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.upliftai.org/v1/contact-lists/uploads/{uploadId}/preview"
payload := strings.NewReader("{\n \"mapping\": {\n \"nameColumn\": \"Name\",\n \"phoneColumn\": \"B\",\n \"attributeColumns\": [\n \"City\"\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
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-lists/uploads/{uploadId}/preview")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"mapping\": {\n \"nameColumn\": \"Name\",\n \"phoneColumn\": \"B\",\n \"attributeColumns\": [\n \"City\"\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.upliftai.org/v1/contact-lists/uploads/{uploadId}/preview")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"mapping\": {\n \"nameColumn\": \"Name\",\n \"phoneColumn\": \"B\",\n \"attributeColumns\": [\n \"City\"\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"summary": {
"willBeCalled": 2,
"excluded": {
"invalidPhone": 0,
"missingName": 0,
"duplicate": 0,
"dnc": 0,
"recentlyCalled": 0
},
"errors": []
},
"detectedMapping": {
"nameColumn": "Name",
"phoneColumn": "Phone",
"attributeColumns": [
"City"
]
},
"sample": [
{
"name": "عائشہ صدیقی",
"phone": "+923000000001",
"attributes": {
"City": "لاہور"
}
},
{
"name": "بلال احمد",
"phone": "+923000000002",
"attributes": {
"City": "کراچی"
}
}
],
"total": 2,
"columns": [
"Name",
"Phone",
"City",
"Appointment"
],
"mappingIssues": []
}{
"message": [
"mapping must be an object"
],
"error": "Bad Request",
"statusCode": 400
}{
"message": "invalid authorization",
"error": "Unauthorized",
"statusCode": 401
}{
"message": "Forbidden resource",
"error": "Forbidden",
"statusCode": 403
}{
"message": "Upload not found: 00000000-0000-4000-8000-000000000000",
"error": "Not Found",
"statusCode": 404
}Re-preview an upload with a mapping
Try a column mapping before you commit to it. Nothing is written, so re-run this as often as you need while adjusting — a body is still required, so send {} to just re-run auto-detection. When the sample looks right, create the list from the same uploadId and mapping. Column naming rules: Special column names.
curl --request POST \
--url https://api.upliftai.org/v1/contact-lists/uploads/{uploadId}/preview \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"mapping": {
"nameColumn": "Name",
"phoneColumn": "B",
"attributeColumns": [
"City"
]
}
}
'import requests
url = "https://api.upliftai.org/v1/contact-lists/uploads/{uploadId}/preview"
payload = { "mapping": {
"nameColumn": "Name",
"phoneColumn": "B",
"attributeColumns": ["City"]
} }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({mapping: {nameColumn: 'Name', phoneColumn: 'B', attributeColumns: ['City']}})
};
fetch('https://api.upliftai.org/v1/contact-lists/uploads/{uploadId}/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-lists/uploads/{uploadId}/preview",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'mapping' => [
'nameColumn' => 'Name',
'phoneColumn' => 'B',
'attributeColumns' => [
'City'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.upliftai.org/v1/contact-lists/uploads/{uploadId}/preview"
payload := strings.NewReader("{\n \"mapping\": {\n \"nameColumn\": \"Name\",\n \"phoneColumn\": \"B\",\n \"attributeColumns\": [\n \"City\"\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
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-lists/uploads/{uploadId}/preview")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"mapping\": {\n \"nameColumn\": \"Name\",\n \"phoneColumn\": \"B\",\n \"attributeColumns\": [\n \"City\"\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.upliftai.org/v1/contact-lists/uploads/{uploadId}/preview")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"mapping\": {\n \"nameColumn\": \"Name\",\n \"phoneColumn\": \"B\",\n \"attributeColumns\": [\n \"City\"\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"summary": {
"willBeCalled": 2,
"excluded": {
"invalidPhone": 0,
"missingName": 0,
"duplicate": 0,
"dnc": 0,
"recentlyCalled": 0
},
"errors": []
},
"detectedMapping": {
"nameColumn": "Name",
"phoneColumn": "Phone",
"attributeColumns": [
"City"
]
},
"sample": [
{
"name": "عائشہ صدیقی",
"phone": "+923000000001",
"attributes": {
"City": "لاہور"
}
},
{
"name": "بلال احمد",
"phone": "+923000000002",
"attributes": {
"City": "کراچی"
}
}
],
"total": 2,
"columns": [
"Name",
"Phone",
"City",
"Appointment"
],
"mappingIssues": []
}{
"message": [
"mapping must be an object"
],
"error": "Bad Request",
"statusCode": 400
}{
"message": "invalid authorization",
"error": "Unauthorized",
"statusCode": 401
}{
"message": "Forbidden resource",
"error": "Forbidden",
"statusCode": 403
}{
"message": "Upload not found: 00000000-0000-4000-8000-000000000000",
"error": "Not Found",
"statusCode": 404
}Authorizations
Project API key (sk_api_…).
Path Parameters
The uploadId returned by /contact-lists/uploads.
Body
Omit it to re-run auto-detection — the same preview the upload returned.
Show child attributes
Show child attributes
Response
The parse under the requested mapping.
Show child attributes
Show child attributes
The mapping applied. Overrides you sent are resolved to header names — an A1 letter comes back as its header — and the rest is auto-detected.
Show child attributes
Show child attributes
First 10 contacts that would be called, after normalization.
Show child attributes
Show child attributes
Data rows read, excluding the header. summary.willBeCalled and the summary.excluded counts add up to this.
Headers as parsed, in file order — the choices for a mapping override.
Columns that resolved to nothing. Check this first when everything is excluded — an unmapped phone column makes every number look invalid.
phoneColumnNotFound, nameColumnNotFound 