Error 400: Entry has invalid root

Regular Participant

Error 400: Entry has invalid root

I'm using php, curl, and SimpleXML to move data around between CC and a web service. I have GETting and POSTing working perfectly (that is, retrieving and creating contacts).


Unfortunately, updating existing contacts is giving me some trouble. Whenever I try, I get the following error:


 


Error 400: Entry has invalid root oauth_consumer_key={API key}&oauth_nonce=d150169ba970baeda6bf4fc3ad9164c4&oauth_signature={sig}&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1297319197&oauth_token={access token}&oauth_version=1.0


 


I am PUTting to the following url: https://api.constantcontact.com/ws/customers/{My Username}/contacts/3


But all of the oauth details are appended to that url before the PUT, so it looks more like

https://api.constantcontact.com/ws/customers/{My Username}/contacts/3?oauth_consumer_key={API key}&oauth_nonce=d150169ba970baeda6bf4fc3ad9164c4&oauth_signature={sig}&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1297319197&oauth_token={access token}&oauth_version=1.0


 


The relevant code and XML is below. Bear in mind, my oauth signing and access is working without issue for the other methods. Thanks,


Wes Curtis


function PutContact($ccXML) {

$attributes = $ccXML->entry->content->Contact->attributes();

$url = $attributes;

$response = self::perform_signed_put($url, $ccXML->asXML());

return $response;

}


function perform_signed_put($url, $postData) {

$url = str_replace('http:', 'https:', $url);

$token = new OAuthToken($this->access_token, $this->access_token_secret);

$token_request = OAuthRequest::from_consumer_and_token($this->oauth_consumer, $token, 'PUT', $url);

$token_request->sign_request($this->sig_method, $this->oauth_consumer, $token);

$token_request_url = $token_request->to_url();

$response = self::perform_curl_put($token_request_url, $postData);

return $response;

}


public static function perform_curl_put($url, $postData)

{

$session = curl_init($url);

$putData = tmpfile();

fwrite($putData, $postData);

fseek($putData, 0);

curl_setopt($session, CURLOPT_INFILE, $putData);

curl_setopt($session, CURLOPT_INFILESIZE, strlen($postData));

curl_setopt($session, CURLOPT_PUT, 1);

curl_setopt($session, CURLOPT_HTTPHEADER, array('Content-Type: application/atom+xml;type=entry'));

curl_setopt($session, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($session, CURLOPT_SSL_VERIFYPEER, 0);

curl_setopt($session, CURLOPT_SSL_VERIFYHOST, 0);

$response = curl_exec($session);

fclose($putData);

$ret = '';

if(!$response) {

$ret = array('error' => curl_error($session), 'status' => curl_getinfo($session, CURLINFO_HTTP_CODE), 'data' => null);

}

else {

$ret = array('error' => null, 'status' => curl_getinfo($session, CURLINFO_HTTP_CODE), 'data'=>$response);

}

curl_close($session);

return $ret;

}


And, as an example of the XML (though I'm just modifying what I get from a retrieval in the first place):


<?xml version="1.0" encoding="UTF-8"?>


<feed xmlns="http://www.w3.org/2005/Atom">


<id>http://api.constantcontact.com/ws/customers/wtcurtis/contacts</id>


<title type="text">Contacts for Customer: wtcurtis</title>


<author> <name>wtcurtis</name> </author>


<updated>2011-02-10T06:46:45.434Z</updated>


<entry>


<link href="/ws/customers/wtcurtis/contacts/3" rel="edit"/> <id>http://api.constantcontact.com/ws/customers/wtcurtis/contacts/3</id>


<title type="text">Contact: asdf@hahaha.net</title>


<updated>2011-02-10T06:46:45.499Z</updated>


<author> <name>Constant Contact</name> </author>


<content type="application/vnd.ctct+xml">


<Contact xmlns="http://ws.constantcontact.com/ns/1.0/" id="http://api.constantcontact.com/ws/customers/wtcurtis/contacts/3">


<Status>Active</Status>


<EmailAddress>asdf@hahaha.net</EmailAddress>


<EmailType>HTML</EmailType>


<Name>Johnson, Test</Name>


<OptInTime>2011-02-10T04:45:07.133Z</OptInTime>


<OptInSource>ACTION_BY_CUSTOMER</OptInSource>


<Confirmed>false</Confirmed>


<InsertTime>2011-02-10T04:45:07.133Z</InsertTime>


<ContactLists>


<ContactList id="http://api.constantcontact.com/ws/customers/wtcurtis/lists/2"></ContactList>


</ContactLists></Contact>


</content>


</entry>


</feed> 

4 REPLIES 4
Regular Participant

 Incidentally, I just tried out a new method here on a hunch: I tried sending the oauth authorization details in the header, rather than in the url. No dice; now, I get Error 400: Entry has invalid root null (that is, null rather than the query string echoed back to me).

Moderator

400 error indicates that your OAuth authentication is passing and we're unable to parse the XML content.  Problem with your XML is adding in a <feed> node which should not be wrapped around the <entry> node.  Since we are expecting the root node to be <entry>, you are correctly receiving an Invalid Root Node error.  Here is an example of your XML working:


<?xml version="1.0" encoding="UTF-8"?>

<entry xmlns="http://www.w3.org/2005/Atom">

<link href="/ws/customers/wtcurtis/contacts/3" rel="edit"/>

<id>http://api.constantcontact.com/ws/customers/wtcurtis/contacts/3</id>

<title type="text">Contact: asdf@hahaha.net</title>

<updated>2011-02-10T06:46:45.499Z</updated>

<author> <name>Constant Contact</name> </author>

<content type="application/vnd.ctct+xml">

<Contact xmlns="http://ws.constantcontact.com/ns/1.0/" id="http://api.constantcontact.com/ws/customers/wtcurtis/contacts/3">

<Status>Active</Status>

<EmailAddress>asdf@hahaha.net</EmailAddress>

<EmailType>HTML</EmailType>

<Name>Johnson, Test</Name>

<OptInTime>2011-02-10T04:45:07.133Z</OptInTime>

<OptInSource>ACTION_BY_CUSTOMER</OptInSource>

<Confirmed>false</Confirmed>

<InsertTime>2011-02-10T04:45:07.133Z</InsertTime>

<ContactLists>

<ContactList id="http://api.constantcontact.com/ws/customers/wtcurtis/lists/2"></ContactList>

</ContactLists>

</Contact>

</content>

</entry>
Dave Berard
Senior Product Manager, Constant Contact
Regular Participant

 Unfortunately, this has not fixed my problem. Sending just the entry portion gives me precisely the same error as before.


Also, it does seem that the curl PUT is causing problems. If I switch the PUT to a POST, it gives me the 415 unsupported media error one would expect. Anyone have any experience with PUT in this context?

Regular Participant

Yep, actually that did fix my problem once I put in the correct xmlns attribute and xml version comment. Thanks for the help! 

Developer Portal

View API documentation, code samples, get your API key.

Visit Page