2

I’m struggling with the new MailChimp API and the batch functionality, specifically, how to return any errors from the underlying operations that were batched, not the batch operation itself.

My code is below and works to add the two test subscribers. The response only shows success for the overall batch:

[errored_operations] => 0

If I run it again, it will return a similar response, but with two errors:

[errored_operations] => 2

Other than that, there is no indication as to what failed or why. In this case, we know that it’s because the users are already subscribed. If I try to add a single user without the batch call, using POST /lists/{list_id}/members, I get a response that details exactly what failed.

stdClass Object
(
    [type] => http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/
    [title] => Member Exists
    [status] => 400
    [detail] => mary@jackson.net is already a list member. Use PUT to insert or update list members.
    [instance] => 
)

How can I capture individual errors when adding (or updating or deleting) hundreds of subscribers?

I have tried just looping through users, making multiple individual calls, and that works: it adds the users and/or provides detailed error reporting. But it seems goofy to make 500 calls when the API is set up to handle this in a single call. Thanks for any ideas!

Here is my code:

$list_id = 'xyz123';
$subscribers = array(
    array(
        'email'     => 'jeff@jackson.net',
        'status'    => 'subscribed',
        'firstname' => 'Jeff',
        'lastname'  => 'Jackson'
    ),
    array(
        'email'     => 'mary@jackson.net',
        'status'    => 'subscribed',
        'firstname' => 'Mary',
        'lastname'  => 'Jackson'
    )
);

$add_subs_batch = add_subs_batch($list_id, $subscribers);
echo '<pre>add_subs_batch: ';
print_r($add_subs_batch);
echo '</pre>';

function add_subs_batch($list_id, $data) {
    $method = 'POST'; 
    $batch_path = 'lists/' . $list_id . '/members';
    $result = mc_request_batch($method, $batch_path, $data);
    if($result && $result->id) {
        $batch_id = $result->id;
        $batch_status = get_batch_status($batch_id);
        return $batch_status;
    }
    else {
        return $result;
    }
}
function get_batch_status($batch_id, $i=1) {
    $method = 'GET'; 
    $target = 'batches/'.$batch_id;
    $result = mc_request($method, $target, $data);
    sleep(1); // wait 1 second and try
    if($result->status == 'finished' ) {
        return $result;
    }
    else {
        return get_batch_status($batch_id, $i+1);
    }
}
function mc_request_batch( $method, $batch_path, $data = false ) {
    $api_key = '12345-us1';
    $dataCenter = substr($api_key,strpos($api_key,'-')+1);
    $url = 'https://' . $dataCenter . '.api.mailchimp.com/3.0/';
    $target = 'batches';

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url . $target );
    curl_setopt($ch, CURLOPT_USERPWD, 'user:' . $api_key);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST' );
    curl_setopt($ch, CURLOPT_TIMEOUT, 10 );
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true );
    curl_setopt($ch, CURLOPT_USERAGENT, 'YOUR-USER-AGENT' );
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 

    if( $data ) {
        $batch_data = new stdClass();
        $batch_data->operations = array();
            foreach ($data as $item) {
                $batch = new stdClass();
                $batch->method = $method;
                $batch->path = $batch_path;
                $batch->body = json_encode( array(
                    'email_address' => $item['email'],
                    'status'        => $item['status'],
                    'merge_fields'  => array( 
                        'FNAME' => $item['firstname'],
                        'LNAME' => $item['lastname']
                    )
                ) );
                $batch_data->operations[] = $batch;
            }

        $batch_data = json_encode($batch_data);
        curl_setopt($ch, CURLOPT_POSTFIELDS,  $batch_data  );
        $response = curl_exec( $ch );
    }
    curl_close( $ch );
    return json_decode($response);
}
ekad
  • 14,436
  • 26
  • 44
  • 46
Stace
  • 147
  • 1
  • 2
  • 9

1 Answers1

5

You will get an id in response of the batch operation. This is 'Batch ID' which is a string that uniquely identifies the batch request.

To get the status of a batch request, you have to call a GET request to the URL, /batches/{batch_id}.

From the response, you can find a URL in response_body_url field which has the gzipped archive of the results of all the operations in the batch call.

Reference:

Note

For security reasons, response_body_url is only valid for 10 minutes. After 10 minutes, generate another with a GET call to /3.0/batches/{batch_id}.

After you make the batch operation request, results are available for 7 days.

Mûhámmàd Yäsår K
  • 1,492
  • 11
  • 24
  • Thank you for taking the time to reply. How can I access that gzipped archive file within my code? Is there any place else I can access that data using PHP? – Stace Oct 20 '16 at 16:16
  • You can write the code to 1. Download the file into your server [Ref](http://stackoverflow.com/questions/3938534/download-file-to-server-from-url) . 2. Read information from the downloaded gzip file [Ref](http://php.net/manual/en/function.gzfile.php). Please let us know if you have any roadblocks to do it. Thanks. :) – Mûhámmàd Yäsår K Oct 21 '16 at 04:41
  • Thanks again for the reply. I understand the flow you outlined, though the file is actually a .tar.gz, which presents another layer of complication, and I'm not able to download the file to the server. but the whole thing seems mighty complex to just get some basic error reporting. Is there really no other way to access this data? – Stace Oct 21 '16 at 19:31
  • I think there isn't any method to access this data, will check it and let you know if any. :) – Mûhámmàd Yäsår K Oct 24 '16 at 10:18
  • Thanks for the help so far. I feel like I'm nearly there but stuck on the last leg. I can download the file.tar.gz file to the server, I can decompress that to path/file.tar using PharData class and the decompress function. From there, I'm trying the phar:extractTo('path/file') but it throws the exception `Extraction from phar "/path/file.tar" failed: Cannot extract ".", internal error`. Any ideas? – Stace Nov 01 '16 at 20:50