curl --request GET \
--url https://api.privy.com/v1/campaigns \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.privy.com/v1/campaigns"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.privy.com/v1/campaigns', 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.privy.com/v1/campaigns",
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.privy.com/v1/campaigns"
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.privy.com/v1/campaigns")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.privy.com/v1/campaigns")
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{
"data": [
{
"id": "Nw8K2rT5xY",
"type": "newsletter",
"title": "June Restock Announcement",
"channel": "email",
"status": "sent",
"subject": "The restock you asked for is here",
"send_date": "2026-06-18T15:00:00Z",
"audience": {
"included_segments": [
{
"id": "aBc1234",
"name": "Engaged 90d",
"prebuilt": false
},
{
"id": "potential_customers",
"name": "Potential Customers",
"prebuilt": true
}
],
"excluded_segments": [
{
"id": "dEf5678",
"name": "Recent purchasers",
"prebuilt": false
}
]
},
"coupon": null,
"ab_test": {
"winning_metric": "click_rate",
"test_duration_seconds": 86400,
"versions": [
{
"id": "cpv_dkyYZmk",
"name": "Version A",
"is_control": true,
"is_winner": false,
"audience_share": 0.125,
"subject": "The restock you asked for is here",
"preheader": "Back in stock and going fast",
"coupon": null
},
{
"id": "cpv_YJGOjpJ",
"name": "Version B",
"is_control": false,
"is_winner": true,
"audience_share": 0.125,
"subject": "Your size is back, but not for long",
"preheader": "We saved you a look",
"coupon": {
"id": "7k2dG6Y",
"title": "RESTOCK20",
"kind": "master",
"platform": "manual"
}
}
]
},
"created_at": "2026-06-10T09:00:00Z",
"updated_at": "2026-06-18T15:05:00Z"
}
],
"pagination": {
"page": 1,
"per_page": 40,
"total_count": 12,
"total_pages": 1
}
}{
"error": {
"code": "unauthorized",
"message": "Bearer token is missing or invalid"
}
}{
"error": {
"code": "insufficient_scope",
"message": "Token does not have the required scope"
}
}{
"error": {
"code": "validation_failed",
"message": "One or more fields are invalid",
"details": [
{
"field": "email",
"message": "is required"
}
]
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded"
}
}List campaigns
Retrieve a paginated list of your message campaigns, newest first.
By default the list contains your newsletters — email and SMS
broadcasts. Pass type=flows to instead list the flow campaigns:
the email and SMS messages your automation flows send, each naming its
owning flow in flow.
Configuration only — no send statistics. /v1/reports/campaigns lists
every campaign sent in a period with its full stat block (revenue-ranked,
top 100); one campaign’s funnel is
/v1/reports/campaigns/{campaign_id}.
Required scope: campaigns_read
curl --request GET \
--url https://api.privy.com/v1/campaigns \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.privy.com/v1/campaigns"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.privy.com/v1/campaigns', 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.privy.com/v1/campaigns",
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.privy.com/v1/campaigns"
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.privy.com/v1/campaigns")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.privy.com/v1/campaigns")
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{
"data": [
{
"id": "Nw8K2rT5xY",
"type": "newsletter",
"title": "June Restock Announcement",
"channel": "email",
"status": "sent",
"subject": "The restock you asked for is here",
"send_date": "2026-06-18T15:00:00Z",
"audience": {
"included_segments": [
{
"id": "aBc1234",
"name": "Engaged 90d",
"prebuilt": false
},
{
"id": "potential_customers",
"name": "Potential Customers",
"prebuilt": true
}
],
"excluded_segments": [
{
"id": "dEf5678",
"name": "Recent purchasers",
"prebuilt": false
}
]
},
"coupon": null,
"ab_test": {
"winning_metric": "click_rate",
"test_duration_seconds": 86400,
"versions": [
{
"id": "cpv_dkyYZmk",
"name": "Version A",
"is_control": true,
"is_winner": false,
"audience_share": 0.125,
"subject": "The restock you asked for is here",
"preheader": "Back in stock and going fast",
"coupon": null
},
{
"id": "cpv_YJGOjpJ",
"name": "Version B",
"is_control": false,
"is_winner": true,
"audience_share": 0.125,
"subject": "Your size is back, but not for long",
"preheader": "We saved you a look",
"coupon": {
"id": "7k2dG6Y",
"title": "RESTOCK20",
"kind": "master",
"platform": "manual"
}
}
]
},
"created_at": "2026-06-10T09:00:00Z",
"updated_at": "2026-06-18T15:05:00Z"
}
],
"pagination": {
"page": 1,
"per_page": 40,
"total_count": 12,
"total_pages": 1
}
}{
"error": {
"code": "unauthorized",
"message": "Bearer token is missing or invalid"
}
}{
"error": {
"code": "insufficient_scope",
"message": "Token does not have the required scope"
}
}{
"error": {
"code": "validation_failed",
"message": "One or more fields are invalid",
"details": [
{
"field": "email",
"message": "is required"
}
]
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded"
}
}Authorizations
Send either an API token or an OAuth access token as
Authorization: Bearer <token>. See the Authentication page for details.
Headers
Target a subaccount instead of the main connected account.
Pass a subaccount id from get_account's subaccounts list. Only direct subaccounts
of the connected account are reachable — omit this for the main account itself.
Query Parameters
Page number (starts at 1).
x >= 1Number of results per page. Values outside 10–100 are clamped to the nearest bound.
10 <= x <= 100Pass flows to list the messages your flows send instead of newsletters.
flows Filter by message channel. Works for both newsletters and flow campaigns.
email, sms Filter newsletters by send lifecycle. Not supported with type=flows
(flow campaigns have no send lifecycle of their own — their live/draft
state belongs to the parent flow, via GET /v1/flows → status) —
combining them returns a 422.
draft, scheduled, preparing, awaiting_winner, sending, sent, partially_sent, unsent, canceled Was this page helpful?