jaybo Posted August 25, 2021 Share Posted August 25, 2021 Working with Mailchimp API, I'm trying to add contacts without success by sending in PHP Async Request batch call to their endpoint. I've gone trough their documentation may times but still without success, trying to replicate their example. https://mailchimp.com/developer/marketing/guides/run-async-requests-batch-endpoint/ I am using the php sdk. Would be great if someone could point me in the right direction why the second example is not working. #################START OF CODE ############################# <?php require_once('vendor/autoload.php'); require_once('config.php'); include 'dbh.php'; include 'testDbh.php'; $mailchimp = new MailchimpMarketing\ApiClient(); $mailchimp->setConfig([ 'apiKey' => $key, 'server' => $server ]); // build json array from mysql db $users = []; $conn = mysqli_connect("localhost","root","","mailchimpapi"); //check connection if(!$conn){ echo "Failed to connect to MySQL: " . mysqli_connect_error(); exit(); }else{ echo 'Connection Successful! <br><br>'; } $sql = "SELECT * FROM mailchimpbatch"; //mysqli write query and get result $results = mysqli_query($conn, $sql); $users = mysqli_fetch_all($results, MYSQLI_ASSOC); $operations = []; foreach($users as $user) { $operation = [ 'method' => 'POST', 'path' => "/lists/$listId/members", 'operation_id' => $user['id'], 'body' => json_encode([ 'email_address' => $user['email'], 'status' => $user['status'], 'merge_fields' => 'FNAME' => $user['fname'], 'LNAME' => $user['lname'] ] ]) ]; array_push($operations, $operation); } try { $response = $mailchimp->batches->start($operations); echo $response; } catch (\MailchimpMarketing\ApiException $e) { echo $e->getMessage(); } ############################END OF CODE ########################## Here is the print_r of $users I pull from the database (made up people); Array ( [0] => Array ( [id] => 1 [status] => subscribed [email] => test1@example.com [fname] => David [lname] => Tester ) [1] => Array ( [id] => 2 [status] => subscribed [email] => test2@example.com [fname] => Kevin [lname] => Ishere ) [2] => Array ( [id] => 3 [status] => subscribed [email] => happy@example.com [fname] => Gerald [lname] => Happy ) [3] => Array ( [id] => 4 [status] => subscribed [email] => Tim@example.com [fname] => Tim [lname] => Toolman ) [4] => Array ( [id] => 5 [status] => subscribed [email] => grealish@example.com [fname] => Jack [lname] => Grealish ) ) The error I receive is a 400 BAD REQUEST, INVALID RESOURCE (full error returned is at the bottom of this post). *****Upon reaching out to Mailchimp they responded with the following: While we are unable to assist with editing or making PHP calls, we can see the Request is being sent over as an array, and does not have any reference to the required "operations". For example, we would expect to see something like: ``` { "operations": [ { "method": "POST", "path": "\/lists\/$listID\/members", "operation_id": "1", "body": "{\"email_address\":\"test1@example.com\",\"status\":\"subscribed\",\"merge_fields\":{\"FNAME\":\"David\",\"LNAME\":\"Tester\"}}" } ] } ``` The request must be an object, rather than an array. So now I am working on that change, but i'm unsure how to implement that - any ideas? ################################################################### *Full error returned = **Fatal error**: Uncaught GuzzleHttp\Exception\ClientException: Client error: `POST https://us6.api.mailchimp.com/3.0/batches` resulted in a `400 Bad Request` response: {"type":"https://mailchimp.com/developer/marketing/docs/errors/","title":"Invalid Resource","status":400,"detail":"The r (truncated...) in C:\xampp\htdocs\dashboard\MailchimpAPI\vendor\guzzlehttp\guzzle\src\Exception\RequestException.php:113 Stack trace: #0 C:\xampp\htdocs\dashboard\MailchimpAPI\vendor\guzzlehttp\guzzle\src\Middleware.php(69): GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Psr7\Request), Object(GuzzleHttp\Psr7\Response), NULL, Array, NULL) #1 C:\xampp\htdocs\dashboard\MailchimpAPI\vendor\guzzlehttp\promises\src\Promise.php(204): GuzzleHttp\Middleware::GuzzleHttp\{closure}(Object(GuzzleHttp\Psr7\Response)) #2 C:\xampp\htdocs\dashboard\MailchimpAPI\vendor\guzzlehttp\promises\src\Promise.php(153): GuzzleHttp\Promise\Promise::callHandler(1, Object(GuzzleHttp\Psr7\Response), NULL) #3 C:\xampp\htdocs\dashboard\MailchimpAPI\vendor\guzzlehttp\promises\src\TaskQueue.php(48): GuzzleHttp\Promise\Promise::GuzzleHttp\Promise\{closure}() #4 C:\xampp\htdocs\dashboard\MailchimpAPI\vendor\guzzlehttp\promises\src\Promise.php(248): GuzzleHttp\Promise\TaskQueue->run(true) #5 C:\xampp\htdocs\dashboard\MailchimpAPI\vendor\guzzlehttp\promises\src\Promise.php(224): GuzzleHttp\Promise\Promise->invokeWaitFn() #6 C:\xampp\htdocs\dashboard\MailchimpAPI\vendor\guzzlehttp\promises\src\Promise.php(269): GuzzleHttp\Promise\Promise->waitIfPending() #7 C:\xampp\htdocs\dashboard\MailchimpAPI\vendor\guzzlehttp\promises\src\Promise.php(226): GuzzleHttp\Promise\Promise->invokeWaitList() #8 C:\xampp\htdocs\dashboard\MailchimpAPI\vendor\guzzlehttp\promises\src\Promise.php(62): GuzzleHttp\Promise\Promise->waitIfPending() #9 C:\xampp\htdocs\dashboard\MailchimpAPI\vendor\guzzlehttp\guzzle\src\Client.php(123): GuzzleHttp\Promise\Promise->wait() #10 C:\xampp\htdocs\dashboard\MailchimpAPI\vendor\mailchimp\marketing\lib\Api\BatchesApi.php(538): GuzzleHttp\Client->send(Object(GuzzleHttp\Psr7\Request), Array) #11 C:\xampp\htdocs\dashboard\MailchimpAPI\vendor\mailchimp\marketing\lib\Api\BatchesApi.php(527): Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/ Share on other sites More sharing options...
requinix Posted August 25, 2021 Share Posted August 25, 2021 You have an $operations array but there needs to be an "operations" in the request body too. As in the body looks like a PHP array of ["operations" => $operations] Â Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1589353 Share on other sites More sharing options...
jaybo Posted August 25, 2021 Author Share Posted August 25, 2021 Thank you requinix, where exactly do I place that? Â I attempted to add it in the $operation array which returned the same error. Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1589366 Share on other sites More sharing options...
requinix Posted August 25, 2021 Share Posted August 25, 2021 Try to understand what the code is doing when it comes to sending API requests to MailChimp. It's sending a certain request body right now which is not entirely correct. You need to modify that body it's trying to send to be more correct. So some questions for you to answer include "how am I sending API requests?" and "what and where is the request body?". Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1589368 Share on other sites More sharing options...
jaybo Posted September 3, 2021 Author Share Posted September 3, 2021 I am sending a POST request and the request body is the string containing the JSON. These are both within the $operation array.  I am not sure how to begin to structure this. 🤔 Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1589625 Share on other sites More sharing options...
jaybo Posted January 7, 2022 Author Share Posted January 7, 2022 requinix I'm back to this one and i'm still stumped. Trying to learn as I go - I am on my own with this and appreciate your pushing me to keep on learning. Do you have the next hint for me? Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593235 Share on other sites More sharing options...
requinix Posted January 9, 2022 Share Posted January 9, 2022 The Mailchimp SDK isn't the smartest thing around. When you give it requests to execute, you have to match exactly what the API says you're supposed to use. Here, the API wants the request body to be an object with an "operations" key that is the array of operations. You almost but not quite have that. Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593245 Share on other sites More sharing options...
jaybo Posted January 10, 2022 Author Share Posted January 10, 2022 Thank you again, I am drawing a blank - I tried to json decode each operation but that just prints an array of objects. Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593264 Share on other sites More sharing options...
requinix Posted January 10, 2022 Share Posted January 10, 2022 ...Why are you adding a json_decode? Read the docs: the request body is an object containing an "operations" key whose value is an array of the operations to perform. You have the array of operations to perform already. What you don't have is them inside an object. Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593267 Share on other sites More sharing options...
jaybo Posted January 10, 2022 Author Share Posted January 10, 2022 Yes I don't quite get how I do that. I have been reading the docs, specifically noting "expects a JSON object with a single key: operations, which is an array of objects that describe the API calls you want to make". I see, as you mentioned, that I have the $operations array all set. I have tried a couple of methods to create an object and then put the key:value pair inside, which is how I'm conceptualizing this part... // create object to put $operations array inside // $operationsObject = (object)['operations'=>$operations]; This brings about the same error. Â I feel I'm missing something that is more straight forward than what I am trying. Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593270 Share on other sites More sharing options...
requinix Posted January 10, 2022 Share Posted January 10, 2022 FYI it doesn't have to be a PHP object: PHP's arrays will serialize into a JSON object when they are associative (have keys). So you can remove the (object) typecast. Having that array looks right to me. You're definitely passing $operationsObject to the API, right, and not $operations? What's your full code look like now? Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593272 Share on other sites More sharing options...
jaybo Posted January 10, 2022 Author Share Posted January 10, 2022 response now= Fatal error: Uncaught Error: Object of class stdClass could not be converted to string in C:\xampp\htdocs\dashboard\MailchimpAPI\batchRequestAddMem.php:141 Stack trace: #0 {main} thrown in C:\xampp\htdocs\dashboard\MailchimpAPI\batchRequestAddMem.php on line 141 Â code now: Â $operations = []; // create object to put $operations array inside $operationsObject = ['operations'=>$operations]; foreach($users as $user) { $operation = [ 'method' => 'POST', 'path' => "/lists/$listId/members", 'operation_id' => $user['id'], 'body' => json_encode([ 'email_address' => $user['email'], 'status' => $user['status'], // Create sync/button to allow BFCMA back end to change this with the DB to then update with daily/weekly batch request //add additional fields to insert into MC 'merge_fields' => [ // 8/10/21 Stackoverflow suggests to use merge-fields *not currently working with it included 'FNAME' => $user['fname'], 'LNAME' => $user['lname'] ] ]) ]; array_push($operations, $operation); } try { $response = $mailchimp->batches->start($operationsObject); echo $response; } catch (\MailchimpMarketing\ApiException $e) { echo $e->getMessage(); } Â Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593274 Share on other sites More sharing options...
requinix Posted January 10, 2022 Share Posted January 10, 2022 And what line is 141? Is it the one where you try to echo $response? You can't just output objects like that. Try print_r. But you've got a pretty big bug here: when you create $operationsObject, $operations is an empty array. You add to $operations later but that's too late because $operationsObject has already been created. Move that line until after the array is ready to be used. Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593281 Share on other sites More sharing options...
jaybo Posted January 11, 2022 Author Share Posted January 11, 2022 Thanks - yes I missed that one. After using print_r for $response and moving the $operationsObject after the array has been populated I get the following response indicating that there are no operations passed in the request; stdClass Object ( [id] => snxzha6dug [status] => pending [total_operations] => 0 [finished_operations] => 0 [errored_operations] => 0 [submitted_at] => 2022-01-11T00:42:23+00:00 [completed_at] => [response_body_url] => [_links] => Array ( [0] => stdClass Object ( [rel] => parent [href] => https://us6.api.mailchimp.com/3.0/batches [method] => GET [targetSchema] => https://us6.api.mailchimp.com/schema/3.0/Definitions/Batches/CollectionResponse.json [schema] => https://us6.api.mailchimp.com/schema/3.0/Paths/Batches/Collection.json ) [1] => stdClass Object ( [rel] => self [href] => https://us6.api.mailchimp.com/3.0/batches/snxzha6dug [method] => GET [targetSchema] => https://us6.api.mailchimp.com/schema/3.0/Definitions/Batches/Response.json ) [2] => stdClass Object ( [rel] => delete [href] => https://us6.api.mailchimp.com/3.0/batches/snxzha6dug [method] => DELETE ) ) )  If I also print_r $operationsObject then I get the following which again indicates an array, not an object; Array ( [operations] => Array ( [0] => Array ( [method] => POST [path] => /lists/6ecc1e6884/members [operation_id] => 1 [body] => {"email_address":"test1@example.com","status":"subscribed","merge_fields":{"FNAME":"David","LNAME":"Tester"}} ) [1] => Array ( [method] => POST [path] => /lists/6ecc1e6884/members [operation_id] => 2 [body] => {"email_address":"test2@example.com","status":"subscribed","merge_fields":{"FNAME":"Kevin","LNAME":"Ishere"}} ) [2] => Array ( [method] => POST [path] => /lists/6ecc1e6884/members [operation_id] => 3 [body] => {"email_address":"happy@example.com","status":"subscribed","merge_fields":{"FNAME":"Gerald","LNAME":"Happy"}} ) [3] => Array ( [method] => POST [path] => /lists/6ecc1e6884/members [operation_id] => 4 [body] => {"email_address":"Tim@example.com","status":"subscribed","merge_fields":{"FNAME":"Tim","LNAME":"Toolman"}} ) [4] => Array ( [method] => POST [path] => /lists/6ecc1e6884/members [operation_id] => 5 [body] => {"email_address":"grealish@example.com","status":"subscribed","merge_fields":{"FNAME":"Jack","LNAME":"Grealish"}} ) ) )  I tried to json_encode $operationsObject and then pass that through with the request, which appears to pass through the correct object format, but it returns the same $response message.    Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593293 Share on other sites More sharing options...
requinix Posted January 11, 2022 Share Posted January 11, 2022 Now that you've fixed the $operationsObject stuff, what does the code look like? Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593304 Share on other sites More sharing options...
Solution jaybo Posted January 11, 2022 Author Solution Share Posted January 11, 2022 Code now; $operations = []; foreach($users as $user) { $operation = [ 'method' => 'POST', 'path' => "/lists/$listId/members", 'operation_id' => $user['id'], 'body' => json_encode([ 'email_address' => $user['email'], 'status' => $user['status'], // Create sync/button to allow BFCMA back end to change this with the DB to then update with daily/weekly batch request //add additional fields to insert into MC 'merge_fields' => [ // 8/10/21 Stackoverflow suggests to use merge-fields *not currently working with it included 'FNAME' => $user['fname'], 'LNAME' => $user['lname'] ] ]) ]; array_push($operations, $operation); } // create object to put $operations array inside $operationsObject = ['operations'=>$operations]; echo '<pre> '; print_r($operationsObject); echo '</pre>'; try { $response = $mailchimp->batches->start($operationsObject); // echo $response; echo '<pre> '; print_r($response); echo '</pre>'; } catch (\MailchimpMarketing\ApiException $e) { echo $e->getMessage(); } Â In addition, here is the final part of the code if you were to include the json_encode; // create object to put $operations array inside $operationsObject = ['operations'=>$operations]; echo '<pre> '; print_r($operationsObject); echo '</pre>'; $json = json_encode($operationsObject, JSON_PRETTY_PRINT); echo '<pre> '; print_r($json); echo '</pre>'; try { $response = $mailchimp->batches->start($json); // echo $response; echo '<pre> '; print_r($response); echo '</pre>'; } catch (\MailchimpMarketing\ApiException $e) { echo $e->getMessage(); } Â Â Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593305 Share on other sites More sharing options...
requinix Posted January 12, 2022 Share Posted January 12, 2022 I don't know. Can you get the SDK to show you exactly what request it's sending? Maybe it's doing something unexpected. I already complained about the lack of documentation, right? Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593308 Share on other sites More sharing options...
jaybo Posted January 12, 2022 Author Share Posted January 12, 2022 You did indeed, Mailchimp responded back to me yesterday: Quote Jumping right in, unfortunately, we are unable to view historic calls through our API monitoring tool. This means that we are unable to see calls that were made before the monitoring tool was turned on. However, I was able to turn on our monitoring tool (that will monitor calls for the next 48 hours). What I can do is let that run for 24-48 hours, then reach back out tomorrow with any errors that we see on our end. This way, you will be able to receive the proper error messages that are being transmitted. So I sent through both requests (with and without the json_encode) for them to review and respond with error messages. It is unfortunate that they do not allow the api monitoring tool to be used on the client end.  Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593313 Share on other sites More sharing options...
requinix Posted January 12, 2022 Share Posted January 12, 2022 It is all PHP code, though. You could go through their code looking for the place where it sends a request through Guzzle, then insert a bit of code to log it or something. 1 Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593318 Share on other sites More sharing options...
jaybo Posted January 14, 2022 Author Share Posted January 14, 2022 Great help thank you! I haven't done that before - limited use of Guzzle up to now. I will explore! Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593331 Share on other sites More sharing options...
jaybo Posted January 17, 2022 Author Share Posted January 17, 2022 still to explore guzzle - but we have a resolution! The final code that we got to was indeed correct! The issue at that point was with the mailchimp audience logic. The emails that I was passing (made up emails) were causing the errors as they were invalid emails. I then was able to pass through real email addresses and this allowed the API request to process correctly. As previously discussed the Mailchimp API document for php is incomplete and using their API dashboard you cannot get more detailed error information. Contacting mailchimp and asking them to set up the API watcher for your account for 24-48hrs to check the API requests made during that period is one way of collecting that information. Quote Link to comment https://forums.phpfreaks.com/topic/313600-mailchimp-api-batch-request/#findComment-1593393 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.