Marketing
Create a drip email campaign
Section titled “Create a drip email campaign”/v1/drip_campaignSign a traveler up for a series of emails that go out on your behalf
before their trip. The emails introduce you as the traveler’s travel
advisor and invite them to book tours, transfers and other experiences
on the Project Expedition page you choose (pe_url).
How It Works
Section titled “How It Works”- You send the traveler’s email address, their travel date and the Project Expedition page to feature.
- PE sends the first email right away (unless you turn it off) and schedules the rest, counting back from the travel date.
- Every email links to that page through your partner referral link.
The simplest request sends email, date, pe_url and title, and
signs the traveler up for every email (see the first code example below).
Required vs Optional Parameters
Section titled “Required vs Optional Parameters”| Parameter | Required | Notes |
|---|---|---|
email |
Yes | Traveler’s email address. The campaign emails are sent here. |
date |
Yes | Travel date, YYYY-MM-DD. Scheduled emails count back from this date. |
pe_url |
Yes | The Project Expedition page the emails link to: a destination, tour or trip page. https:// is added if missing. PE turns it into your partner referral link, a short pe.tours link that carries your referral code. |
title |
Recommended | The destination name the emails mention, e.g. Ireland. Also lets PE recognize a repeated request (see Duplicates and Updates). |
first_name |
No | Traveler’s first name, used in the greeting. |
last_name |
No | Traveler’s last name. |
reference_id |
No | Only when changing a campaign you created earlier: send the reference_id PE returned for it. This is not a booking reference. |
freq_* |
No | Which emails to send. See Choosing Which Emails to Send below. |
Email Schedule
Section titled “Email Schedule”| Field | When the email is sent |
|---|---|
freq_today |
Immediately, when the campaign is created |
freq_540 |
540 days (about 18 months) before date |
freq_360 |
360 days (about 12 months) before date |
freq_180 |
180 days (about 6 months) before date |
freq_90 |
90 days before date |
freq_60 |
60 days before date |
freq_30 |
30 days before date |
freq_14 |
14 days before date |
freq_7 |
7 days before date |
freq_3 |
Retired: accepted, never sent |
PE sends scheduled emails once a day. Each one goes out on the day that
is exactly that many days before date. If that day has already passed
when the campaign is created (for example freq_540 for a trip three
months away), that email is skipped.
Choosing Which Emails to Send
Section titled “Choosing Which Emails to Send”- Send no
freq_*fields to get every email:todayplus all eight scheduled emails. - Send one or more
freq_*fields to choose. Only the fields set to1are sent. A field you leave out is off; it does not fall back to the default. - Set every
freq_*field to0to save the campaign without sending any email. freq_3does not count as a choice: a request whose only frequency field isfreq_3behaves as if it sent none.
The Request Body example below sends the immediate email and the 30-day
and 7-day reminders, and nothing else. Its response lists
"intervals": ["today", "7", "30"].
Reading the Response
Section titled “Reading the Response”| Field | Meaning |
|---|---|
status |
Success for new, duplicate and updated campaigns alike |
reference_id |
The campaign’s reference (a string). Keep it if you may need to update the campaign. |
intervals |
The emails this campaign includes: today for the immediate email, and the number of days before travel for each scheduled one, in the order today, 7, 14, 30, 60, 90, 180, 360, 540. An email whose send day has already passed is still listed but is never sent. null for a duplicate. |
email_sent |
true if the immediate (today) email was sent, false if sending it failed, null if it was not requested or the request was a duplicate. |
Duplicates and Updates
Section titled “Duplicates and Updates”- A traveler can have several campaigns, for example one per trip, each with its own
reference_id. - Sending the same
email,date,pe_urlandtitleagain does not create a second campaign. The response returns the existingreference_idwithintervalsandemail_sentset tonull, and no email is sent. Without atitle, every request creates a new campaign. - To change a campaign (a new date, page or set of emails), send the full request again for the same
email, withreference_idset to the value you received. The campaign is replaced with the new values. Thefreq_*rules apply again, so send"freq_today": 0unless you want the immediate email sent a second time.
When Emails Are Not Sent
Section titled “When Emails Are Not Sent”- Scheduled emails are skipped while the traveler has an upcoming Project Expedition booking (a booking under the same email address with a future travel date).
- Travelers who unsubscribe from drip campaign emails get no further scheduled emails.
- The campaign is removed once
datehas passed.
Testing in Staging
Section titled “Testing in Staging”On apistage.projectexpedition.com, creating a campaign also sends a
test copy of every enabled scheduled email straight away, with the
subject prefixed [TEST - 30 days] and so on, so you can preview the
whole series. Use an email address you control.
Errors
Section titled “Errors”If a field is missing or invalid, the request is rejected with HTTP
status 400 and one of these messages: Missing email, Invalid Email,
Missing date, Invalid Date (the date must be YYYY-MM-DD),
Missing pe_url or Invalid URL.
Request Body
Section titled “Request Body”Required
{ "email": "traveler@example.com", "first_name": "John", "date": "2028-06-15", "pe_url": "https://www.projectexpedition.com/ireland/", "title": "Ireland", "freq_today": 1, "freq_30": 1, "freq_7": 1}Code Examples
Section titled “Code Examples”curl -X POST "https://apistage.projectexpedition.com/v1/drip_campaign" \ -H "access-token: {{token}}" \ -H "Content-Type: application/json" \ -d '{ "email": "traveler@example.com", "first_name": "John", "last_name": "Smith", "date": "2028-06-15", "pe_url": "https://www.projectexpedition.com/ireland/", "title": "Ireland" }'const response = await fetch('https://apistage.projectexpedition.com/v1/drip_campaign', { method: 'POST', headers: { 'access-token': 'YOUR_TOKEN', 'Content-Type': 'application/json' }, body: JSON.stringify({ "email": "traveler@example.com", "first_name": "John", "last_name": "Smith", "date": "2028-06-15", "pe_url": "https://www.projectexpedition.com/ireland/", "title": "Ireland" })});
const data = await response.json();<?php$data = json_encode({ 'email': 'traveler@example.com', 'first_name': 'John', 'last_name': 'Smith', 'date': '2028-06-15', 'pe_url': 'https://www.projectexpedition.com/ireland/', 'title': 'Ireland' });
$context = stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: application/json\r\naccess-token: YOUR_TOKEN\r\nContent-Type: application/json", 'content' => $data ]]);
$response = file_get_contents('https://apistage.projectexpedition.com/v1/drip_campaign', false, $context);$result = json_decode($response, true);curl -X POST "https://apistage.projectexpedition.com/v1/drip_campaign" \ -H "access-token: {{token}}" \ -H "Content-Type: application/json" \ -d '{ "email": "traveler@example.com", "first_name": "John", "date": "2028-06-15", "pe_url": "https://www.projectexpedition.com/ireland/", "title": "Ireland", "freq_today": 1, "freq_30": 1, "freq_7": 1 }'const response = await fetch('https://apistage.projectexpedition.com/v1/drip_campaign', { method: 'POST', headers: { 'access-token': 'YOUR_TOKEN', 'Content-Type': 'application/json' }, body: JSON.stringify({ "email": "traveler@example.com", "first_name": "John", "date": "2028-06-15", "pe_url": "https://www.projectexpedition.com/ireland/", "title": "Ireland", "freq_today": 1, "freq_30": 1, "freq_7": 1 })});
const data = await response.json();<?php$data = json_encode({ 'email': 'traveler@example.com', 'first_name': 'John', 'date': '2028-06-15', 'pe_url': 'https://www.projectexpedition.com/ireland/', 'title': 'Ireland', 'freq_today': 1, 'freq_30': 1, 'freq_7': 1 });
$context = stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: application/json\r\naccess-token: YOUR_TOKEN\r\nContent-Type: application/json", 'content' => $data ]]);
$response = file_get_contents('https://apistage.projectexpedition.com/v1/drip_campaign', false, $context);$result = json_decode($response, true);curl -X POST "https://apistage.projectexpedition.com/v1/drip_campaign" \ -H "access-token: {{token}}" \ -H "Content-Type: application/json" \ -d '{ "email": "traveler@example.com", "first_name": "John", "date": "2028-07-01", "pe_url": "https://www.projectexpedition.com/ireland/", "title": "Ireland", "reference_id": "2181511", "freq_today": 0, "freq_30": 1, "freq_7": 1 }'const response = await fetch('https://apistage.projectexpedition.com/v1/drip_campaign', { method: 'POST', headers: { 'access-token': 'YOUR_TOKEN', 'Content-Type': 'application/json' }, body: JSON.stringify({ "email": "traveler@example.com", "first_name": "John", "date": "2028-07-01", "pe_url": "https://www.projectexpedition.com/ireland/", "title": "Ireland", "reference_id": "2181511", "freq_today": 0, "freq_30": 1, "freq_7": 1 })});
const data = await response.json();<?php$data = json_encode({ 'email': 'traveler@example.com', 'first_name': 'John', 'date': '2028-07-01', 'pe_url': 'https://www.projectexpedition.com/ireland/', 'title': 'Ireland', 'reference_id': '2181511', 'freq_today': 0, 'freq_30': 1, 'freq_7': 1 });
$context = stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: application/json\r\naccess-token: YOUR_TOKEN\r\nContent-Type: application/json", 'content' => $data ]]);
$response = file_get_contents('https://apistage.projectexpedition.com/v1/drip_campaign', false, $context);$result = json_decode($response, true);Responses
Section titled “Responses”200 Campaign created, updated, or matched to an existing one
Section titled “200 Campaign created, updated, or matched to an existing one”{ "status": "Success", "message": "Drip Campaign added for traveler@example.com", "reference_id": "2181511", "intervals": [ "today", "7", "30" ], "email_sent": true}400 Invalid request
Section titled “400 Invalid request”{ "error": "Missing pe_url"}