Adding subscribers to a list using Mailchimp's API v3
Based on the List Members Instance docs, the easiest way is to use a PUT
request which according to the docs either "adds a new list member or updates the member if the email already exists on the list".
Furthermore apikey
is definitely not part of the json schema and there's no point in including it in your json request.
Also, as noted in @TooMuchPete's comment, you can use CURLOPT_USERPWD
for basic http auth as illustrated in below.
I'm using the following function to add and update list members. You may need to include a slightly different set of merge_fields
depending on your list parameters.
$data = [
'email' => '[email protected]',
'status' => 'subscribed',
'firstname' => 'john',
'lastname' => 'doe'
];
syncMailchimp($data);
function syncMailchimp($data) {
$apiKey = 'your api key';
$listId = 'your list id';
$memberId = md5(strtolower($data['email']));
$dataCenter = substr($apiKey,strpos($apiKey,'-')+1);
$url = 'https://' . $dataCenter . '.api.mailchimp.com/3.0/lists/' . $listId . '/members/' . $memberId;
$json = json_encode([
'email_address' => $data['email'],
'status' => $data['status'], // "subscribed","unsubscribed","cleaned","pending"
'merge_fields' => [
'FNAME' => $data['firstname'],
'LNAME' => $data['lastname']
]
]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_USERPWD, 'user:' . $apiKey);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
$result = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpCode;
}
I got it working. I was adding the authentication to the header incorrectly:
$apikey = '<api_key>';
$auth = base64_encode( 'user:'.$apikey );
$data = array(
'apikey' => $apikey,
'email_address' => $email,
'status' => 'subscribed',
'merge_fields' => array(
'FNAME' => $name
)
);
$json_data = json_encode($data);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://us2.api.mailchimp.com/3.0/lists/<list_id>/members/');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json',
'Authorization: Basic '.$auth));
curl_setopt($ch, CURLOPT_USERAGENT, 'PHP-MCAPI/2.0');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
$result = curl_exec($ch);
var_dump($result);
die('Mailchimp executed');
These are good answers but detached from a full answer as to how you would get a form to send data and handle that response. This will demonstrate how to add a member to a list with v3.0 of the API from an HTML page via jquery .ajax()
.
In Mailchimp:
- Acquire your API Key and List ID
- Make sure you setup your list and what custom fields you want to use with it. In this case, I've set up
zipcode
as a custom field in the list BEFORE I did the API call. - Check out the API docs on adding members to lists. We are using the
create
method which requires the use of HTTPPOST
requests. There are other options in here that requirePUT
if you want to be able to modify/delete subs.
HTML:
<form id="pfb-signup-submission" method="post">
<div class="sign-up-group">
<input type="text" name="pfb-signup" id="pfb-signup-box-fname" class="pfb-signup-box" placeholder="First Name">
<input type="text" name="pfb-signup" id="pfb-signup-box-lname" class="pfb-signup-box" placeholder="Last Name">
<input type="email" name="pfb-signup" id="pfb-signup-box-email" class="pfb-signup-box" placeholder="[email protected]">
<input type="text" name="pfb-signup" id="pfb-signup-box-zip" class="pfb-signup-box" placeholder="Zip Code">
</div>
<input type="submit" class="submit-button" value="Sign-up" id="pfb-signup-button"></a>
<div id="pfb-signup-result"></div>
</form>
Key things:
- Give your
<form>
a unique ID and don't forget themethod="post"
attribute so the form works. - Note the last line
#signup-result
is where you will deposit the feedback from the PHP script.
PHP:
<?php
/*
* Add a 'member' to a 'list' via mailchimp API v3.x
* @ http://developer.mailchimp.com/documentation/mailchimp/reference/lists/members/#create-post_lists_list_id_members
*
* ================
* BACKGROUND
* Typical use case is that this code would get run by an .ajax() jQuery call or possibly a form action
* The live data you need will get transferred via the global $_POST variable
* That data must be put into an array with keys that match the mailchimp endpoints, check the above link for those
* You also need to include your API key and list ID for this to work.
* You'll just have to go get those and type them in here, see README.md
* ================
*/
// Set API Key and list ID to add a subscriber
$api_key = 'your-api-key-here';
$list_id = 'your-list-id-here';
/* ================
* DESTINATION URL
* Note: your API URL has a location subdomain at the front of the URL string
* It can vary depending on where you are in the world
* To determine yours, check the last 3 digits of your API key
* ================
*/
$url = 'https://us5.api.mailchimp.com/3.0/lists/' . $list_id . '/members/';
/* ================
* DATA SETUP
* Encode data into a format that the add subscriber mailchimp end point is looking for
* Must include 'email_address' and 'status'
* Statuses: pending = they get an email; subscribed = they don't get an email
* Custom fields go into the 'merge_fields' as another array
* More here: http://developer.mailchimp.com/documentation/mailchimp/reference/lists/members/#create-post_lists_list_id_members
* ================
*/
$pfb_data = array(
'email_address' => $_POST['emailname'],
'status' => 'pending',
'merge_fields' => array(
'FNAME' => $_POST['firstname'],
'LNAME' => $_POST['lastname'],
'ZIPCODE' => $_POST['zipcode']
),
);
// Encode the data
$encoded_pfb_data = json_encode($pfb_data);
// Setup cURL sequence
$ch = curl_init();
/* ================
* cURL OPTIONS
* The tricky one here is the _USERPWD - this is how you transfer the API key over
* _RETURNTRANSFER allows us to get the response into a variable which is nice
* This example just POSTs, we don't edit/modify - just a simple add to a list
* _POSTFIELDS does the heavy lifting
* _SSL_VERIFYPEER should probably be set but I didn't do it here
* ================
*/
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERPWD, 'user:' . $api_key);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded_pfb_data);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$results = curl_exec($ch); // store response
$response = curl_getinfo($ch, CURLINFO_HTTP_CODE); // get HTTP CODE
$errors = curl_error($ch); // store errors
curl_close($ch);
// Returns info back to jQuery .ajax or just outputs onto the page
$results = array(
'results' => $result_info,
'response' => $response,
'errors' => $errors
);
// Sends data back to the page OR the ajax() in your JS
echo json_encode($results);
?>
Key things:
-
CURLOPT_USERPWD
handles the API key and Mailchimp doesn't really show you how to do this. -
CURLOPT_RETURNTRANSFER
gives us the response in such a way that we can send it back into the HTML page with the.ajax()
success
handler. - Use
json_encode
on the data you received.
JS:
// Signup form submission
$('#pfb-signup-submission').submit(function(event) {
event.preventDefault();
// Get data from form and store it
var pfbSignupFNAME = $('#pfb-signup-box-fname').val();
var pfbSignupLNAME = $('#pfb-signup-box-lname').val();
var pfbSignupEMAIL = $('#pfb-signup-box-email').val();
var pfbSignupZIP = $('#pfb-signup-box-zip').val();
// Create JSON variable of retreived data
var pfbSignupData = {
'firstname': pfbSignupFNAME,
'lastname': pfbSignupLNAME,
'email': pfbSignupEMAIL,
'zipcode': pfbSignupZIP
};
// Send data to PHP script via .ajax() of jQuery
$.ajax({
type: 'POST',
dataType: 'json',
url: 'mailchimp-signup.php',
data: pfbSignupData,
success: function (results) {
$('#pfb-signup-box-fname').hide();
$('#pfb-signup-box-lname').hide();
$('#pfb-signup-box-email').hide();
$('#pfb-signup-box-zip').hide();
$('#pfb-signup-result').text('Thanks for adding yourself to the email list. We will be in touch.');
console.log(results);
},
error: function (results) {
$('#pfb-signup-result').html('<p>Sorry but we were unable to add you into the email list.</p>');
console.log(results);
}
});
});
Key things:
-
JSON
data is VERY touchy on transfer. Here, I am putting it into an array and it looks easy. If you are having problems, it is likely because of how your JSON data is structured. Check this out! - The keys for your JSON data will become what you reference in the PHP
_POST
global variable. In this case it will be_POST['email']
,_POST['firstname']
, etc. But you could name them whatever you want - just remember what you name the keys of thedata
part of your JSON transfer is how you access them in PHP. - This obviously requires jQuery ;)
BATCH LOAD - OK, so after having my previous reply deleted for just using links I have updated with the code I managed to get working. Appreciate anyone to simplify / correct / refine / put in function etc as I'm still learning this stuff, but I got batch member list add working :)
$apikey = "whatever-us99";
$list_id = "12ab34dc56";
$email1 = "[email protected]";
$fname1 = "Jack";
$lname1 = "Black";
$email2 = "[email protected]";
$fname2 = "Jill";
$lname2 = "Hill";
$auth = base64_encode( 'user:'.$apikey );
$data1 = array(
"apikey" => $apikey,
"email_address" => $email1,
"status" => "subscribed",
"merge_fields" => array(
'FNAME' => $fname1,
'LNAME' => $lname1,
)
);
$data2 = array(
"apikey" => $apikey,
"email_address" => $email2,
"status" => "subscribed",
"merge_fields" => array(
'FNAME' => $fname2,
'LNAME' => $lname2,
)
);
$json_data1 = json_encode($data1);
$json_data2 = json_encode($data2);
$array = array(
"operations" => array(
array(
"method" => "POST",
"path" => "/lists/$list_id/members/",
"body" => $json_data1
),
array(
"method" => "POST",
"path" => "/lists/$list_id/members/",
"body" => $json_data2
)
)
);
$json_post = json_encode($array);
$ch = curl_init();
$curlopt_url = "https://us99.api.mailchimp.com/3.0/batches";
curl_setopt($ch, CURLOPT_URL, $curlopt_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json',
'Authorization: Basic '.$auth));
curl_setopt($ch, CURLOPT_USERAGENT, 'PHP-MCAPI/3.0');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_post);
print_r($json_post . "\n");
$result = curl_exec($ch);
var_dump($result . "\n");
print_r ($result . "\n");
If it helps anyone, here is what I got working in Python using the Python Requests library instead of CURL.
As explained by @staypuftman above, you will need your API Key and List ID from MailChimp and make sure your API Key suffix and URL prefix (i.e. us5) match.
Python:
#########################################################################################
# To add a single contact to MailChimp (using MailChimp v3.0 API), requires:
# + MailChimp API Key
# + MailChimp List Id for specific list
# + MailChimp API URL for adding a single new contact
#
# Note: the API URL has a 3/4 character location subdomain at the front of the URL string.
# It can vary depending on where you are in the world. To determine yours, check the last
# 3/4 characters of your API key. The API URL location subdomain must match API Key
# suffix e.g. us5, us13, us19 etc. but in this example, us5.
# (suggest you put the following 3 values in 'settings' or 'secrets' file)
#########################################################################################
MAILCHIMP_API_KEY = 'your-api-key-here-us5'
MAILCHIMP_LIST_ID = 'your-list-id-here'
MAILCHIMP_ADD_CONTACT_TO_LIST_URL = 'https://us5.api.mailchimp.com/3.0/lists/' + MAILCHIMP_LIST_ID + '/members/'
# Create new contact data and convert into JSON as this is what MailChimp expects in the API
# I've hardcoded some test data but use what you get from your form as appropriate
new_contact_data_dict = {
"email_address": "[email protected]", # 'email_address' is a mandatory field
"status": "subscribed", # 'status' is a mandatory field
"merge_fields": { # 'merge_fields' are optional:
"FNAME": "John",
"LNAME": "Smith"
}
}
new_contact_data_json = json.dumps(new_contact_data_dict)
# Create the new contact using MailChimp API using Python 'Requests' library
req = requests.post(
MAILCHIMP_ADD_CONTACT_TO_LIST_URL,
data=new_contact_data_json,
auth=('user', MAILCHIMP_API_KEY),
headers={"content-type": "application/json"}
)
# debug info if required - .text and .json also list the 'merge_fields' names for use in contact JSON above
# print req.status_code
# print req.text
# print req.json()
if req.status_code == 200:
# success - do anything you need to do
else:
# fail - do anything you need to do - but here is a useful debug message
mailchimp_fail = 'MailChimp call failed calling this URL: {0}\n' \
'Returned this HTTP status code: {1}\n' \
'Returned this response text: {2}' \
.format(req.url, str(req.status_code), req.text)