curl --request POST \
--url https://galinum.com/api/v1/campaigns \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Launch: CSV export",
"message": {
"presentation": "toast",
"title": "CSV export is here 📊",
"body": "Export any table to CSV from the toolbar.",
"media": {
"url": "https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png",
"alt": "Screenshot of the new analytics dashboard",
"decorative": false
}
},
"channel": "web_inapp",
"variants": [
{
"message": {
"presentation": "toast",
"title": "CSV export is here 📊",
"body": "Export any table to CSV from the toolbar.",
"media": {
"url": "https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png",
"alt": "Screenshot of the new analytics dashboard",
"decorative": false
}
},
"name": "A",
"weight": 1,
"isControl": true
}
],
"audience": {
"kind": "all",
"reason": "<string>"
},
"targeting": {
"traits": {
"plan": "free"
},
"events": {
"seen": [
"activated_workspace"
],
"not_seen": [
"used_csv_export"
]
}
},
"pages": [
"/settings/*"
],
"goalId": "<string>",
"launch": false,
"deliverFrom": 123,
"deliverUntil": 123
}
'import requests
url = "https://galinum.com/api/v1/campaigns"
payload = {
"name": "Launch: CSV export",
"message": {
"presentation": "toast",
"title": "CSV export is here 📊",
"body": "Export any table to CSV from the toolbar.",
"media": {
"url": "https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png",
"alt": "Screenshot of the new analytics dashboard",
"decorative": False
}
},
"channel": "web_inapp",
"variants": [
{
"message": {
"presentation": "toast",
"title": "CSV export is here 📊",
"body": "Export any table to CSV from the toolbar.",
"media": {
"url": "https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png",
"alt": "Screenshot of the new analytics dashboard",
"decorative": False
}
},
"name": "A",
"weight": 1,
"isControl": True
}
],
"audience": {
"kind": "all",
"reason": "<string>"
},
"targeting": {
"traits": { "plan": "free" },
"events": {
"seen": ["activated_workspace"],
"not_seen": ["used_csv_export"]
}
},
"pages": ["/settings/*"],
"goalId": "<string>",
"launch": False,
"deliverFrom": 123,
"deliverUntil": 123
}
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({
name: 'Launch: CSV export',
message: {
presentation: 'toast',
title: 'CSV export is here 📊',
body: JSON.stringify('Export any table to CSV from the toolbar.'),
media: {
url: 'https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png',
alt: 'Screenshot of the new analytics dashboard',
decorative: false
}
},
channel: 'web_inapp',
variants: [
{
message: {
presentation: 'toast',
title: 'CSV export is here 📊',
body: JSON.stringify('Export any table to CSV from the toolbar.'),
media: {
url: 'https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png',
alt: 'Screenshot of the new analytics dashboard',
decorative: false
}
},
name: 'A',
weight: 1,
isControl: true
}
],
audience: {kind: 'all', reason: '<string>'},
targeting: {
traits: {plan: 'free'},
events: {seen: ['activated_workspace'], not_seen: ['used_csv_export']}
},
pages: ['/settings/*'],
goalId: '<string>',
launch: false,
deliverFrom: 123,
deliverUntil: 123
})
};
fetch('https://galinum.com/api/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://galinum.com/api/v1/campaigns",
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([
'name' => 'Launch: CSV export',
'message' => [
'presentation' => 'toast',
'title' => 'CSV export is here 📊',
'body' => 'Export any table to CSV from the toolbar.',
'media' => [
'url' => 'https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png',
'alt' => 'Screenshot of the new analytics dashboard',
'decorative' => false
]
],
'channel' => 'web_inapp',
'variants' => [
[
'message' => [
'presentation' => 'toast',
'title' => 'CSV export is here 📊',
'body' => 'Export any table to CSV from the toolbar.',
'media' => [
'url' => 'https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png',
'alt' => 'Screenshot of the new analytics dashboard',
'decorative' => false
]
],
'name' => 'A',
'weight' => 1,
'isControl' => true
]
],
'audience' => [
'kind' => 'all',
'reason' => '<string>'
],
'targeting' => [
'traits' => [
'plan' => 'free'
],
'events' => [
'seen' => [
'activated_workspace'
],
'not_seen' => [
'used_csv_export'
]
]
],
'pages' => [
'/settings/*'
],
'goalId' => '<string>',
'launch' => false,
'deliverFrom' => 123,
'deliverUntil' => 123
]),
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://galinum.com/api/v1/campaigns"
payload := strings.NewReader("{\n \"name\": \"Launch: CSV export\",\n \"message\": {\n \"presentation\": \"toast\",\n \"title\": \"CSV export is here 📊\",\n \"body\": \"Export any table to CSV from the toolbar.\",\n \"media\": {\n \"url\": \"https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png\",\n \"alt\": \"Screenshot of the new analytics dashboard\",\n \"decorative\": false\n }\n },\n \"channel\": \"web_inapp\",\n \"variants\": [\n {\n \"message\": {\n \"presentation\": \"toast\",\n \"title\": \"CSV export is here 📊\",\n \"body\": \"Export any table to CSV from the toolbar.\",\n \"media\": {\n \"url\": \"https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png\",\n \"alt\": \"Screenshot of the new analytics dashboard\",\n \"decorative\": false\n }\n },\n \"name\": \"A\",\n \"weight\": 1,\n \"isControl\": true\n }\n ],\n \"audience\": {\n \"kind\": \"all\",\n \"reason\": \"<string>\"\n },\n \"targeting\": {\n \"traits\": {\n \"plan\": \"free\"\n },\n \"events\": {\n \"seen\": [\n \"activated_workspace\"\n ],\n \"not_seen\": [\n \"used_csv_export\"\n ]\n }\n },\n \"pages\": [\n \"/settings/*\"\n ],\n \"goalId\": \"<string>\",\n \"launch\": false,\n \"deliverFrom\": 123,\n \"deliverUntil\": 123\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://galinum.com/api/v1/campaigns")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Launch: CSV export\",\n \"message\": {\n \"presentation\": \"toast\",\n \"title\": \"CSV export is here 📊\",\n \"body\": \"Export any table to CSV from the toolbar.\",\n \"media\": {\n \"url\": \"https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png\",\n \"alt\": \"Screenshot of the new analytics dashboard\",\n \"decorative\": false\n }\n },\n \"channel\": \"web_inapp\",\n \"variants\": [\n {\n \"message\": {\n \"presentation\": \"toast\",\n \"title\": \"CSV export is here 📊\",\n \"body\": \"Export any table to CSV from the toolbar.\",\n \"media\": {\n \"url\": \"https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png\",\n \"alt\": \"Screenshot of the new analytics dashboard\",\n \"decorative\": false\n }\n },\n \"name\": \"A\",\n \"weight\": 1,\n \"isControl\": true\n }\n ],\n \"audience\": {\n \"kind\": \"all\",\n \"reason\": \"<string>\"\n },\n \"targeting\": {\n \"traits\": {\n \"plan\": \"free\"\n },\n \"events\": {\n \"seen\": [\n \"activated_workspace\"\n ],\n \"not_seen\": [\n \"used_csv_export\"\n ]\n }\n },\n \"pages\": [\n \"/settings/*\"\n ],\n \"goalId\": \"<string>\",\n \"launch\": false,\n \"deliverFrom\": 123,\n \"deliverUntil\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://galinum.com/api/v1/campaigns")
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 \"name\": \"Launch: CSV export\",\n \"message\": {\n \"presentation\": \"toast\",\n \"title\": \"CSV export is here 📊\",\n \"body\": \"Export any table to CSV from the toolbar.\",\n \"media\": {\n \"url\": \"https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png\",\n \"alt\": \"Screenshot of the new analytics dashboard\",\n \"decorative\": false\n }\n },\n \"channel\": \"web_inapp\",\n \"variants\": [\n {\n \"message\": {\n \"presentation\": \"toast\",\n \"title\": \"CSV export is here 📊\",\n \"body\": \"Export any table to CSV from the toolbar.\",\n \"media\": {\n \"url\": \"https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png\",\n \"alt\": \"Screenshot of the new analytics dashboard\",\n \"decorative\": false\n }\n },\n \"name\": \"A\",\n \"weight\": 1,\n \"isControl\": true\n }\n ],\n \"audience\": {\n \"kind\": \"all\",\n \"reason\": \"<string>\"\n },\n \"targeting\": {\n \"traits\": {\n \"plan\": \"free\"\n },\n \"events\": {\n \"seen\": [\n \"activated_workspace\"\n ],\n \"not_seen\": [\n \"used_csv_export\"\n ]\n }\n },\n \"pages\": [\n \"/settings/*\"\n ],\n \"goalId\": \"<string>\",\n \"launch\": false,\n \"deliverFrom\": 123,\n \"deliverUntil\": 123\n}"
response = http.request(request)
puts response.read_body{
"campaign": {
"id": "cmp_3ce6dba5-7f36-41f5-9327-d5cc3099ab77",
"name": "Launch: CSV export",
"status": "draft",
"effectiveStatus": "draft",
"channel": "web_inapp",
"goalId": "<string>",
"createdBy": "api",
"createdAt": 1784067764978,
"startedAt": 123,
"endedAt": 123,
"deliverFrom": 123,
"deliverUntil": 123,
"audience": {
"kind": "all"
},
"targeting": {
"traits": {
"plan": "free"
},
"events": {
"seen": [
"activated_workspace"
],
"not_seen": [
"used_csv_export"
]
}
},
"pages": [
"/dashboard",
"/settings/*"
],
"stats": {
"sent": 123,
"frequencyCapped": 123,
"delivered": 123,
"shown": 123,
"opened": 123,
"clicked": 123,
"dismissed": 123,
"bounced": 123,
"complained": 123,
"unsubscribed": 123,
"converted": 123
},
"variants": [
{
"id": "var_37705a49-52c6-4577-aeed-665099a1e13d",
"name": "A",
"weight": 1,
"isControl": true,
"content": {
"presentation": "toast",
"title": "CSV export is here 📊",
"body": "Export any table to CSV from the toolbar.",
"cta": {
"label": "Try it",
"destination": {
"kind": "website",
"url": "https://app.example.com/exports"
}
},
"media": {
"url": "https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png",
"alt": "Screenshot of the new analytics dashboard",
"decorative": false
}
},
"stats": {
"sent": 123,
"frequencyCapped": 123,
"delivered": 123,
"shown": 123,
"opened": 123,
"clicked": 123,
"dismissed": 123,
"bounced": 123,
"complained": 123,
"unsubscribed": 123,
"converted": 123
}
}
],
"sourceChanges": {
"revision": "<string>",
"changes": [
{
"sourceId": "<string>",
"kind": "commit",
"sha": "<string>"
}
]
},
"push": {
"appId": "<string>",
"selection": {
"kind": "last_active"
},
"ttlSeconds": 1209600,
"replacementKey": "<string>"
}
}
}{
"error": "userId is required"
}{
"error": "Unauthorized"
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "Invalid request"
}{
"error": "Too many requests"
}{
"error": "Could not identify user"
}{
"error": "<string>"
}Create a campaign
Creates a web in-app or email campaign behind the same campaign model. Use either one message (a direct communication, one variant named “A”) or an explicit weighted variants array. Pass launch: true to start delivery, or leave a draft. Email launch requires a verified project domain and a matching from address. Optional deliverFrom/deliverUntil schedule a future start and automatic expiry. Optional sourceChanges declares the changes for deployment-based activation. Content and declaration commit atomically. Declaring changes does not approve the campaign. Approval survives later edits, but launch requires coverage for the current declaration and current channel readiness.
curl --request POST \
--url https://galinum.com/api/v1/campaigns \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Launch: CSV export",
"message": {
"presentation": "toast",
"title": "CSV export is here 📊",
"body": "Export any table to CSV from the toolbar.",
"media": {
"url": "https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png",
"alt": "Screenshot of the new analytics dashboard",
"decorative": false
}
},
"channel": "web_inapp",
"variants": [
{
"message": {
"presentation": "toast",
"title": "CSV export is here 📊",
"body": "Export any table to CSV from the toolbar.",
"media": {
"url": "https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png",
"alt": "Screenshot of the new analytics dashboard",
"decorative": false
}
},
"name": "A",
"weight": 1,
"isControl": true
}
],
"audience": {
"kind": "all",
"reason": "<string>"
},
"targeting": {
"traits": {
"plan": "free"
},
"events": {
"seen": [
"activated_workspace"
],
"not_seen": [
"used_csv_export"
]
}
},
"pages": [
"/settings/*"
],
"goalId": "<string>",
"launch": false,
"deliverFrom": 123,
"deliverUntil": 123
}
'import requests
url = "https://galinum.com/api/v1/campaigns"
payload = {
"name": "Launch: CSV export",
"message": {
"presentation": "toast",
"title": "CSV export is here 📊",
"body": "Export any table to CSV from the toolbar.",
"media": {
"url": "https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png",
"alt": "Screenshot of the new analytics dashboard",
"decorative": False
}
},
"channel": "web_inapp",
"variants": [
{
"message": {
"presentation": "toast",
"title": "CSV export is here 📊",
"body": "Export any table to CSV from the toolbar.",
"media": {
"url": "https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png",
"alt": "Screenshot of the new analytics dashboard",
"decorative": False
}
},
"name": "A",
"weight": 1,
"isControl": True
}
],
"audience": {
"kind": "all",
"reason": "<string>"
},
"targeting": {
"traits": { "plan": "free" },
"events": {
"seen": ["activated_workspace"],
"not_seen": ["used_csv_export"]
}
},
"pages": ["/settings/*"],
"goalId": "<string>",
"launch": False,
"deliverFrom": 123,
"deliverUntil": 123
}
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({
name: 'Launch: CSV export',
message: {
presentation: 'toast',
title: 'CSV export is here 📊',
body: JSON.stringify('Export any table to CSV from the toolbar.'),
media: {
url: 'https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png',
alt: 'Screenshot of the new analytics dashboard',
decorative: false
}
},
channel: 'web_inapp',
variants: [
{
message: {
presentation: 'toast',
title: 'CSV export is here 📊',
body: JSON.stringify('Export any table to CSV from the toolbar.'),
media: {
url: 'https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png',
alt: 'Screenshot of the new analytics dashboard',
decorative: false
}
},
name: 'A',
weight: 1,
isControl: true
}
],
audience: {kind: 'all', reason: '<string>'},
targeting: {
traits: {plan: 'free'},
events: {seen: ['activated_workspace'], not_seen: ['used_csv_export']}
},
pages: ['/settings/*'],
goalId: '<string>',
launch: false,
deliverFrom: 123,
deliverUntil: 123
})
};
fetch('https://galinum.com/api/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://galinum.com/api/v1/campaigns",
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([
'name' => 'Launch: CSV export',
'message' => [
'presentation' => 'toast',
'title' => 'CSV export is here 📊',
'body' => 'Export any table to CSV from the toolbar.',
'media' => [
'url' => 'https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png',
'alt' => 'Screenshot of the new analytics dashboard',
'decorative' => false
]
],
'channel' => 'web_inapp',
'variants' => [
[
'message' => [
'presentation' => 'toast',
'title' => 'CSV export is here 📊',
'body' => 'Export any table to CSV from the toolbar.',
'media' => [
'url' => 'https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png',
'alt' => 'Screenshot of the new analytics dashboard',
'decorative' => false
]
],
'name' => 'A',
'weight' => 1,
'isControl' => true
]
],
'audience' => [
'kind' => 'all',
'reason' => '<string>'
],
'targeting' => [
'traits' => [
'plan' => 'free'
],
'events' => [
'seen' => [
'activated_workspace'
],
'not_seen' => [
'used_csv_export'
]
]
],
'pages' => [
'/settings/*'
],
'goalId' => '<string>',
'launch' => false,
'deliverFrom' => 123,
'deliverUntil' => 123
]),
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://galinum.com/api/v1/campaigns"
payload := strings.NewReader("{\n \"name\": \"Launch: CSV export\",\n \"message\": {\n \"presentation\": \"toast\",\n \"title\": \"CSV export is here 📊\",\n \"body\": \"Export any table to CSV from the toolbar.\",\n \"media\": {\n \"url\": \"https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png\",\n \"alt\": \"Screenshot of the new analytics dashboard\",\n \"decorative\": false\n }\n },\n \"channel\": \"web_inapp\",\n \"variants\": [\n {\n \"message\": {\n \"presentation\": \"toast\",\n \"title\": \"CSV export is here 📊\",\n \"body\": \"Export any table to CSV from the toolbar.\",\n \"media\": {\n \"url\": \"https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png\",\n \"alt\": \"Screenshot of the new analytics dashboard\",\n \"decorative\": false\n }\n },\n \"name\": \"A\",\n \"weight\": 1,\n \"isControl\": true\n }\n ],\n \"audience\": {\n \"kind\": \"all\",\n \"reason\": \"<string>\"\n },\n \"targeting\": {\n \"traits\": {\n \"plan\": \"free\"\n },\n \"events\": {\n \"seen\": [\n \"activated_workspace\"\n ],\n \"not_seen\": [\n \"used_csv_export\"\n ]\n }\n },\n \"pages\": [\n \"/settings/*\"\n ],\n \"goalId\": \"<string>\",\n \"launch\": false,\n \"deliverFrom\": 123,\n \"deliverUntil\": 123\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://galinum.com/api/v1/campaigns")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Launch: CSV export\",\n \"message\": {\n \"presentation\": \"toast\",\n \"title\": \"CSV export is here 📊\",\n \"body\": \"Export any table to CSV from the toolbar.\",\n \"media\": {\n \"url\": \"https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png\",\n \"alt\": \"Screenshot of the new analytics dashboard\",\n \"decorative\": false\n }\n },\n \"channel\": \"web_inapp\",\n \"variants\": [\n {\n \"message\": {\n \"presentation\": \"toast\",\n \"title\": \"CSV export is here 📊\",\n \"body\": \"Export any table to CSV from the toolbar.\",\n \"media\": {\n \"url\": \"https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png\",\n \"alt\": \"Screenshot of the new analytics dashboard\",\n \"decorative\": false\n }\n },\n \"name\": \"A\",\n \"weight\": 1,\n \"isControl\": true\n }\n ],\n \"audience\": {\n \"kind\": \"all\",\n \"reason\": \"<string>\"\n },\n \"targeting\": {\n \"traits\": {\n \"plan\": \"free\"\n },\n \"events\": {\n \"seen\": [\n \"activated_workspace\"\n ],\n \"not_seen\": [\n \"used_csv_export\"\n ]\n }\n },\n \"pages\": [\n \"/settings/*\"\n ],\n \"goalId\": \"<string>\",\n \"launch\": false,\n \"deliverFrom\": 123,\n \"deliverUntil\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://galinum.com/api/v1/campaigns")
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 \"name\": \"Launch: CSV export\",\n \"message\": {\n \"presentation\": \"toast\",\n \"title\": \"CSV export is here 📊\",\n \"body\": \"Export any table to CSV from the toolbar.\",\n \"media\": {\n \"url\": \"https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png\",\n \"alt\": \"Screenshot of the new analytics dashboard\",\n \"decorative\": false\n }\n },\n \"channel\": \"web_inapp\",\n \"variants\": [\n {\n \"message\": {\n \"presentation\": \"toast\",\n \"title\": \"CSV export is here 📊\",\n \"body\": \"Export any table to CSV from the toolbar.\",\n \"media\": {\n \"url\": \"https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png\",\n \"alt\": \"Screenshot of the new analytics dashboard\",\n \"decorative\": false\n }\n },\n \"name\": \"A\",\n \"weight\": 1,\n \"isControl\": true\n }\n ],\n \"audience\": {\n \"kind\": \"all\",\n \"reason\": \"<string>\"\n },\n \"targeting\": {\n \"traits\": {\n \"plan\": \"free\"\n },\n \"events\": {\n \"seen\": [\n \"activated_workspace\"\n ],\n \"not_seen\": [\n \"used_csv_export\"\n ]\n }\n },\n \"pages\": [\n \"/settings/*\"\n ],\n \"goalId\": \"<string>\",\n \"launch\": false,\n \"deliverFrom\": 123,\n \"deliverUntil\": 123\n}"
response = http.request(request)
puts response.read_body{
"campaign": {
"id": "cmp_3ce6dba5-7f36-41f5-9327-d5cc3099ab77",
"name": "Launch: CSV export",
"status": "draft",
"effectiveStatus": "draft",
"channel": "web_inapp",
"goalId": "<string>",
"createdBy": "api",
"createdAt": 1784067764978,
"startedAt": 123,
"endedAt": 123,
"deliverFrom": 123,
"deliverUntil": 123,
"audience": {
"kind": "all"
},
"targeting": {
"traits": {
"plan": "free"
},
"events": {
"seen": [
"activated_workspace"
],
"not_seen": [
"used_csv_export"
]
}
},
"pages": [
"/dashboard",
"/settings/*"
],
"stats": {
"sent": 123,
"frequencyCapped": 123,
"delivered": 123,
"shown": 123,
"opened": 123,
"clicked": 123,
"dismissed": 123,
"bounced": 123,
"complained": 123,
"unsubscribed": 123,
"converted": 123
},
"variants": [
{
"id": "var_37705a49-52c6-4577-aeed-665099a1e13d",
"name": "A",
"weight": 1,
"isControl": true,
"content": {
"presentation": "toast",
"title": "CSV export is here 📊",
"body": "Export any table to CSV from the toolbar.",
"cta": {
"label": "Try it",
"destination": {
"kind": "website",
"url": "https://app.example.com/exports"
}
},
"media": {
"url": "https://galinum.example/media/projects/prj_123/media/9c2f0b7e-4d11-4c2a-a3d1-1c9a1a2b3c4d.png",
"alt": "Screenshot of the new analytics dashboard",
"decorative": false
}
},
"stats": {
"sent": 123,
"frequencyCapped": 123,
"delivered": 123,
"shown": 123,
"opened": 123,
"clicked": 123,
"dismissed": 123,
"bounced": 123,
"complained": 123,
"unsubscribed": 123,
"converted": 123
}
}
],
"sourceChanges": {
"revision": "<string>",
"changes": [
{
"sourceId": "<string>",
"kind": "commit",
"sha": "<string>"
}
]
},
"push": {
"appId": "<string>",
"selection": {
"kind": "last_active"
},
"ttlSeconds": 1209600,
"replacementKey": "<string>"
}
}
}{
"error": "userId is required"
}{
"error": "Unauthorized"
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "Invalid request"
}{
"error": "Too many requests"
}{
"error": "Could not identify user"
}{
"error": "<string>"
}Authorizations
Your project's secret key (pk_…, without the pub segment). Server-side only — never ship it to a browser. Get it from Settings → Projects in the dashboard.
Body
- Option 1
- Option 2
Exactly one of message or variants is required.
Internal campaign name shown in the dashboard.
80"Launch: CSV export"
Single-variant shorthand: creates one variant named "A". Mutually exclusive with variants.
- Option 1
- Option 2
- Option 3
Show child attributes
Show child attributes
Delivery channel. Email content uses subject, previewText, Markdown body, and an optional CTA.
web_inapp, email, push Weighted variants for an A/B test (at most one control, at least one positive weight). Mutually exclusive with message.
1 - 10 elementsShow child attributes
Show child attributes
Canonical audience union. null or { "kind": "all" } targets everyone. { "kind": "expression", "expression": { … }, "reason": "…" } authors an inline audience stored as an immutable audience version. { "kind": "segment", "segment": "id-or-key", "version": n? } pins a saved segment version (omitted version = current, resolved atomically; archived segments are refused). Check expressions first with POST /api/v1/audiences/check. Mutually exclusive with the deprecated targeting field.
- Option 1
- Option 2
- Option 3
Show child attributes
Show child attributes
Deprecated shorthand for the same audience semantics (strict trait equality + events seen/not_seen, ANDed). Still accepted; normalized into an immutable audience version. Prefer audience.
Show child attributes
Show child attributes
Web in-app only. Path patterns limiting where the message may render. Email campaigns reject this field.
20256Link the campaign to a goal in this project (400 if the goal doesn't exist here). Tracked events matching the linked goal's targetEvent automatically resolve the campaign's deliveries to converted once shown. Omit or pass null for no goal — direct communications never need one.
1Start the campaign instead of creating a draft. Email returns 409 until the project's sending domain is verified and its from address matches.
Requested delivery-window start: epoch milliseconds or ISO-8601 with an explicit timezone offset (e.g. 2026-08-01T09:00:00Z). Nothing is delivered before this instant; combine with launch: true to schedule a future start. Must be earlier than deliverUntil.
Requested delivery-window end: epoch milliseconds or ISO-8601 with an explicit timezone offset. Must be in the future; delivery stops automatically at exactly this instant.
Show child attributes
Show child attributes
Optional prepared source declaration, committed atomically with campaign content. No expectedRevision on create. Empty changes cannot qualify for automatic activation.
Show child attributes
Show child attributes
Response
The created campaign, including its variant.
Show child attributes
Show child attributes