[SalesForce] HttpResponse StatusCode=200, but 3rd party request (Pardot) not made

ObJective:
I am attempting to create a new prospect in Pardot when a lead that had no email gets updated with an email (Pardot will sync accounts but until the lead email exist there is no prospect to sync, hence this trigger)

Problem:
Using the afterUpdate trigger context I was able to verify the email status to make this call only when expected, but the problem is making the dynamically generated email "execute." So my Pardot class method creates the URL like so:

String add_prospect = 'https://pi.pardot.com/prospect/sync/email/'+l.Email+'?lead_id='+l.Id+'&sessionid='+UserInfo.getSessionId()+'&serverurl='+l.Partner_Server_URL__c;

Then I send the URL to the sendHttpRequest() method and from what I can see the developer console shows success but my Pardot account does not show the new account. In addition when I take the generated URL from the developer console and paste into address bar and run it I get directed to Pardot where the prospect is successfully created.

Here is the Developer Console response:

13:02:58:065 CALLOUT_REQUEST [38]|System.HttpRequest[Endpoint=https://pi.pardot.com/prospect/sync/email/newprospect@email.com?lead_id={my_lead_id}&sessionid={my_sessionid}&serverurl=https://cs10.salesforce.com/services/Soap/u/9.0/{org_id}, Method=POST]
13:03:00:421 CALLOUT_RESPONSE [38]|System.HttpResponse[Status=OK, StatusCode=200]

And here is the method in question:

@future (callout=true) // future method needed to run callouts from Triggers

static void sendHttpRequest(String url){
    /* Instantiate a new http object */
    Http h = new Http();

    /* Instantiate a new HTTP request, specify the method (GET) as well as the endpoint */
    HttpRequest req = new HttpRequest();
    req.setEndpoint(url);
    req.setMethod('POST'); //I tried GET as well
    req.setTimeout(60000);

    // Send the request, and return a response
    HttpResponse res = h.send(req);
}

This is my first trigger/class so apologies if I'm missing something obvious but hoping if that's the case that the SF community can help me out. If there is a details I left out that you need let me know in comments and I'll get that added

References:
http://www.pardot.com/faqs/salesforce/setting-up-salesforce-com-person-accounts-for-pardot-syncing/#Send_to_Pardot_button

Best Answer

The problem was simply that when the call was made I did not have access, using the Pardot API I realized to make an API call I will need to first get an API key (by sending email, password, and user_key), then every API call will require the api_key and the user_key along with any parameters need for the request you're making.

In short here is the code from my approach.

In my Pardot.cls (which is used by my trigger and trigger handler class) I have methods like createProspectsByLead() which fires APIRequest() that first gets the API Key, and then uses that key and the user_key to make another HttpRequest.

The full code implementation can be found here

All API Request use this method

@future (callout=true)
private static void APIRequest(String url, String body){
    HttpResponse response = httpCallout( url, 'user_key='+getConnectorUserKey()+'&api_key='+getAPIKey()+'&'+ body );
}

Get API Key

public static String getAPIKey(){
    HttpResponse response = httpCallout(
        'https://pi.pardot.com/api/login/version/3?', //URL
        'email='+getConnectorEmail()+'&password='+getConnectorPassword()+'&user_key='+ getConnectorUserKey() //Body
    );

    /* Parse API Response */
    Dom.Document doc = new Dom.Document();
    doc.load(response.getBody());
    Dom.XMLNode root = doc.getRootElement();
    if(root.getName()=='rsp') {
        for(Dom.XMLNode node1: root.getChildElements()) {
            if(node1.getName()=='err') {
                String err = root.getChildElement('err', null).getText();
                String code = root.getChildElement('err', null).getAttribute('code', null);
                System.debug('::API REQUEST ERROR:: '+code+' - '+err);
                return err;
            }
            if(node1.getName()=='api_key') {
                /* Store API in variable */
                // TODO: Store API for 1 hour in Global__c
                String api_key = root.getChildElement('api_key', null).getText();
                return api_key;
            }
        }
    }

    /* This should never happen */
    return '';
}

Each callout uses the httpCallout method

public static HttpResponse httpCallout(String url, String body){
    HttpRequest     request     = new HttpRequest();
    HttpResponse    response    = new HttpResponse();
    Http            http        = new Http();

    request.setEndPoint(url);
    request.setBody(body);
    request.setMethod('POST');

    /* Try to send the request */
    try {
        response = http.send(request);
        System.debug('::RESPONSE::'+response.getBody());
        return response;
    } catch(System.CalloutException e) {
        System.debug('ERROR: '+ e);
        return null;
    }
}

Be sure to see my github repo of this complete implementation and even contribute to it as a community resource.

Related Topic