curl --request POST \
--url https://api.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"contacts": [
{
"name": "Ada Lovelace",
"phoneNumber": "+15550100",
"additionalNumbers": [
"+15550199"
]
},
{
"name": "Grace Hopper",
"phoneNumber": "+15550101",
"metadata": {
"company": "Acme"
}
},
{
"phoneNumber": "+15550102"
}
]
}
'import requests
url = "https://api.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts"
payload = { "contacts": [{
"name": "Ada Lovelace",
"phoneNumber": "+15550100",
"additionalNumbers": ["+15550199"]
}, {
"name": "Grace Hopper",
"phoneNumber": "+15550101",
"metadata": { "company": "Acme" }
}, { "phoneNumber": "+15550102" }] }
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({
contacts: [
{
name: 'Ada Lovelace',
phoneNumber: '+15550100',
additionalNumbers: ['+15550199']
},
{name: 'Grace Hopper', phoneNumber: '+15550101', metadata: {company: 'Acme'}},
{phoneNumber: '+15550102'}
]
})
};
fetch('https://api.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts', 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.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts",
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([
'contacts' => [
[
'name' => 'Ada Lovelace',
'phoneNumber' => '+15550100',
'additionalNumbers' => [
'+15550199'
]
],
[
'name' => 'Grace Hopper',
'phoneNumber' => '+15550101',
'metadata' => [
'company' => 'Acme'
]
],
[
'phoneNumber' => '+15550102'
]
]
]),
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.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts"
payload := strings.NewReader("{\n \"contacts\": [\n {\n \"name\": \"Ada Lovelace\",\n \"phoneNumber\": \"+15550100\",\n \"additionalNumbers\": [\n \"+15550199\"\n ]\n },\n {\n \"name\": \"Grace Hopper\",\n \"phoneNumber\": \"+15550101\",\n \"metadata\": {\n \"company\": \"Acme\"\n }\n },\n {\n \"phoneNumber\": \"+15550102\"\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.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"contacts\": [\n {\n \"name\": \"Ada Lovelace\",\n \"phoneNumber\": \"+15550100\",\n \"additionalNumbers\": [\n \"+15550199\"\n ]\n },\n {\n \"name\": \"Grace Hopper\",\n \"phoneNumber\": \"+15550101\",\n \"metadata\": {\n \"company\": \"Acme\"\n }\n },\n {\n \"phoneNumber\": \"+15550102\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts")
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 \"contacts\": [\n {\n \"name\": \"Ada Lovelace\",\n \"phoneNumber\": \"+15550100\",\n \"additionalNumbers\": [\n \"+15550199\"\n ]\n },\n {\n \"name\": \"Grace Hopper\",\n \"phoneNumber\": \"+15550101\",\n \"metadata\": {\n \"company\": \"Acme\"\n }\n },\n {\n \"phoneNumber\": \"+15550102\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"contactListId": 4821,
"received": 3,
"added": 2,
"skippedExisting": 1,
"duplicatesInPayload": 0
}{
"error": "Invalid request",
"details": [
{
"path": "contacts.0.phoneNumber",
"message": "phoneNumber is required"
}
]
}{
"error": "Invalid API key"
}{
"error": "Contact list not found"
}{
"error": "Rate limit exceeded"
}Add contacts (batch)
Appends up to 10,000 contacts in one transaction. A phone number already in the list is skipped and counted in skippedExisting (its name and metadata are not updated). Repeated numbers inside one payload collapse to the first one and are counted in duplicatesInPayload. A failure leaves nothing half-applied, so the request can simply be retried.
curl --request POST \
--url https://api.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"contacts": [
{
"name": "Ada Lovelace",
"phoneNumber": "+15550100",
"additionalNumbers": [
"+15550199"
]
},
{
"name": "Grace Hopper",
"phoneNumber": "+15550101",
"metadata": {
"company": "Acme"
}
},
{
"phoneNumber": "+15550102"
}
]
}
'import requests
url = "https://api.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts"
payload = { "contacts": [{
"name": "Ada Lovelace",
"phoneNumber": "+15550100",
"additionalNumbers": ["+15550199"]
}, {
"name": "Grace Hopper",
"phoneNumber": "+15550101",
"metadata": { "company": "Acme" }
}, { "phoneNumber": "+15550102" }] }
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({
contacts: [
{
name: 'Ada Lovelace',
phoneNumber: '+15550100',
additionalNumbers: ['+15550199']
},
{name: 'Grace Hopper', phoneNumber: '+15550101', metadata: {company: 'Acme'}},
{phoneNumber: '+15550102'}
]
})
};
fetch('https://api.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts', 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.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts",
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([
'contacts' => [
[
'name' => 'Ada Lovelace',
'phoneNumber' => '+15550100',
'additionalNumbers' => [
'+15550199'
]
],
[
'name' => 'Grace Hopper',
'phoneNumber' => '+15550101',
'metadata' => [
'company' => 'Acme'
]
],
[
'phoneNumber' => '+15550102'
]
]
]),
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.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts"
payload := strings.NewReader("{\n \"contacts\": [\n {\n \"name\": \"Ada Lovelace\",\n \"phoneNumber\": \"+15550100\",\n \"additionalNumbers\": [\n \"+15550199\"\n ]\n },\n {\n \"name\": \"Grace Hopper\",\n \"phoneNumber\": \"+15550101\",\n \"metadata\": {\n \"company\": \"Acme\"\n }\n },\n {\n \"phoneNumber\": \"+15550102\"\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.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"contacts\": [\n {\n \"name\": \"Ada Lovelace\",\n \"phoneNumber\": \"+15550100\",\n \"additionalNumbers\": [\n \"+15550199\"\n ]\n },\n {\n \"name\": \"Grace Hopper\",\n \"phoneNumber\": \"+15550101\",\n \"metadata\": {\n \"company\": \"Acme\"\n }\n },\n {\n \"phoneNumber\": \"+15550102\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.migration.powerdialer.ai/api/public/v1/contact-lists/{id}/contacts")
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 \"contacts\": [\n {\n \"name\": \"Ada Lovelace\",\n \"phoneNumber\": \"+15550100\",\n \"additionalNumbers\": [\n \"+15550199\"\n ]\n },\n {\n \"name\": \"Grace Hopper\",\n \"phoneNumber\": \"+15550101\",\n \"metadata\": {\n \"company\": \"Acme\"\n }\n },\n {\n \"phoneNumber\": \"+15550102\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"contactListId": 4821,
"received": 3,
"added": 2,
"skippedExisting": 1,
"duplicatesInPayload": 0
}{
"error": "Invalid request",
"details": [
{
"path": "contacts.0.phoneNumber",
"message": "phoneNumber is required"
}
]
}{
"error": "Invalid API key"
}{
"error": "Contact list not found"
}{
"error": "Rate limit exceeded"
}Authorizations
Authorization: Bearer <api key>. The key is issued by PowerDialer and must stay on your server.
Headers
Login email of the PowerDialer user the request acts for. Send this or x-user-id; if both are sent, x-user-id wins.
Clerk user id of the PowerDialer user the request acts for. Send this or x-user-email.
"user_2abc..."
Path Parameters
Id of the contact list, from the create response.
4821
Body
1 - 10000 elementsShow child attributes
Show child attributes
Response
Batch result
4821
Contacts in the request.
3
2
Numbers already in the list; not updated.
1
Repeated numbers inside the request, collapsed to the first.
0