Note: In the Java examples below, we’ll be using the minimal-json package to handle JSON representations in our code. You can read more about this project here: https://github.com/ralfstx/minimal-json
One of the most common requirements when integrating with Marketo is the retrieval of lead data. Most, if not all integrations will require either the retrieval or submission of lead data from a Marketo subscription, so today we will take a look at a basic lead information retrieval task, by authenticating with a subscription and then retrieving lead data from it. If you haven’t yet provisioned an API user and a Custom Service, check out our Quick Start Guide for some quick configuration instructions.
To retrieve our leads, first we need to authenticate with the target Marketo instance using OAuth 2.0. There are three pieces of information we need to authenticate with Marketo, the client ID, client secret, and the host of the Marketo instance. Here’s the class we’ll be using to authenticate:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
package dev.marketo.blog_leads; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.net.MalformedURLException; import java.net.URL; import javax.net.ssl.HttpsURLConnection; import com.eclipsesource.json.JsonObject; public class Auth { protected String marketoInstance; //Instance Host obtained from Admin -> Web Service private String clientId; //clientId obtained from Admin -> Launchpoint -> View Details for selected service private String clientSecret; //clientSecret obtained from Admin -> Launchpoint -> View Details for selected service private String idEndpoint; //idEndpoint constructed to authenticate with service when constructor is used private String token; //token is stored for reuse until expiration private Long expiry; //used to store time of expiration //Creates an instance of Auth which is used to Authenticate with a particular service on a particular instance public Auth(String id, String secret, String instanceUrl) { this.clientId = id; this.clientSecret = secret; this.marketoInstance = instanceUrl; this.idEndpoint = marketoInstance + "/identity/oauth/token?grant_type=client_credentials&client_id=" + clientId + "&client_secret=" + clientSecret; } //The only public method of Auth, used to check if the current value of Token is valid, and then to retrieve a new one if it is not public String getToken(){ long now = System.currentTimeMillis(); if (expiry == null || expiry < now){ System.out.println("Token is empty or expired. Trying new authentication"); JsonObject jo = getData(); System.out.println("Got Authentication Response: " + jo); this.token = jo.get("access_token").asString(); //expires_in is reported as seconds, set expiry to system time in ms + expires * 1000 this.expiry = System.currentTimeMillis() + (jo.get("expires_in").asLong() * 1000); } return this.token; } //Executes the authentication request private JsonObject getData(){ JsonObject jsonObject = null; try { URL url = new URL(idEndpoint); HttpsURLConnection urlConn = (HttpsURLConnection) url.openConnection(); urlConn.setRequestMethod("GET"); urlConn.setRequestProperty("accept", "application/json"); System.out.println("Trying to authenticate with " + idEndpoint); int responseCode = urlConn.getResponseCode(); if (responseCode == 200) { InputStream inStream = urlConn.getInputStream(); Reader reader = new InputStreamReader(inStream); jsonObject = JsonObject.readFrom(reader); }else { throw new IOException("Status: " + responseCode); } } catch (MalformedURLException e) { e.printStackTrace(); }catch (IOException e) { e.printStackTrace(); } return jsonObject; } } |
This code allows you to create an instance of Auth with our client ID, client secret and host (as marketoInstance) from Admin -> Launchpoint (ID and Secret) and Admin -> Web Services (Host). It exposes the getToken method which tests whether the currently stored token is null or expired, and then returns either the existing token, or makes a new authentication request then returns the new token from the “access_token” member of the JSON response.
Now that you can authenticate with your Marketo instance, the next step is to retrieve our leads. We’ll be using this class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
package dev.marketo.blog_leads; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import javax.net.ssl.HttpsURLConnection; import com.eclipsesource.json.JsonObject; public class Leads { private StringBuilder endpoint; private Auth auth; public String filterType; public ArrayList filterValues = new ArrayList(); public Integer batchSize; public String nextPageToken; public ArrayList fields = new ArrayList(); public Leads(Auth a) { this.auth = a; this.endpoint = new StringBuilder(this.auth.marketoInstance + "/rest/v1/leads.json"); } public Leads setFilterType(String filterType) { this.filterType = filterType; return this; } public Leads setFilterValues(ArrayList filterValues) { this.filterValues = filterValues; return this; } public Leads addFilterValue(String filterVal) { this.filterValues.add(filterVal); return this; } public Leads setBatchSize(Integer batchSize) { this.batchSize = batchSize; return this; } public Leads setNextPageToken(String nextPageToken) { this.nextPageToken = nextPageToken; return this; } public Leads setFields(ArrayList fields) { this.fields = fields; return this; } public JsonObject getData() { JsonObject result = null; try { endpoint.append("?access_token=" + auth.getToken() + "&filterType=" + filterType + "&filterValues=" + csvString(filterValues)); if (batchSize != null && batchSize > 0 && batchSize <= 300){ endpoint.append("&batchSize=" + batchSize); } if (nextPageToken != null){ endpoint.append("&nextPageToken=" + nextPageToken); } if (fields != null){ endpoint.append("&fields=" + csvString(fields)); } URL url = new URL(endpoint.toString()); HttpsURLConnection urlConn = (HttpsURLConnection) url.openConnection(); urlConn.setRequestMethod("GET"); urlConn.setRequestProperty("accept", "text/json"); InputStream inStream = urlConn.getInputStream(); Reader reader = new InputStreamReader(inStream); result = JsonObject.readFrom(reader); } catch (MalformedURLException e) { System.out.println("URL not valid."); } catch (IOException e) { System.out.println("IOException: " + e.getMessage()); e.printStackTrace(); } return result; } private String csvString(ArrayList fields) { StringBuilder fieldCsv = new StringBuilder(); for (int i = 0; i < fields.size(); i++){ fieldCsv.append(fields.get(i)); if (i + 1 != fields.size()){ fieldCsv.append(","); } } return fieldCsv.toString(); } } |
This class has a single constructor which accepts an Auth object, and then exposes several setters for both optional and required parameters. In this case, we really only need to concern ourselves with setting the filterType and filterValues to perform get leads by email address. So we’ll use setFilterType for “email”, and addFilterValue for the email address that we need to retrieve an ID for. When you’ve set your parameters, you can use the getData method to retrieve a JsonObject from the leads endpoint, containing a results array which has a JSON representation of the lead records which were retrieved.
Putting it together
Now that we’ve gone through the sample code that we’ll be using let’s take a look at a simple example to retrieve leads matching a test email address, testlead@marketo.com. For this we’ll need to use setFilterType for “email”, and addFilterValue for the email address that we need to retrieve information for. When you’ve set your parameters, you can use the getData method to retrieve a JsonObject from the leads endpoint, containing a results array which has a JSON representation of the lead records which were retrieved.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package dev.marketo.blog_leads; import com.eclipsesource.json.JsonObject; public class App { public static void main( String[] args ) { //Create an instance of Auth so that we can authenticate with our Marketo instance //Change the credentials here to your own Auth auth = new Auth("CHANGE ME", "CHANGE ME", "CHANGE ME"); //Create and parameterize an instance of Leads Leads getLeads = new Leads(auth) .setFilterType("email") .addFilterValue("testlead@marketo.com"); //get the inner results array of the response JsonObject leadsResult = getLeads.getData(); System.out.println(leadsResult); } } |
In this main method example, we create an instance of Auth, and then pass this to a new Leads constructor. Using setFilterType, and addFilterValue, we configure our instance of Leads to retrieve just leads matching the email address “testlead@marketo.com.” This example prints this out to the console:
1 2 3 4 |
Token is empty or expired. Trying new authentication Trying to authenticate with https://299-BYM-827.mktorest.com/identity/oauth/token?grant_type=client_credentials&client_id=b417d98f-9289-47d1-a61f-db141bf0267f&client_secret=0DipOvz4h2wP1ANeVjlfwMvECJpo0ZYc Got Authentication Response: {"access_token":"ec0f02c0-28ac-4d6c-b7d7-00e47ae85ff1:st","token_type":"bearer","expires_in":538,"scope":"apiuser@mktosupport.com"} {"requestId":"14fb6#14e6a7a9ad6","result":[{"id":1026322,"updatedAt":"2015-07-07T21:43:25Z","lastName":"Lead","email":"testlead@marketo.com","createdAt":"2015-07-07T21:43:25Z","firstName":"Test"},{"id":1026323,"updatedAt":"2015-07-07T21:43:43Z","lastName":"Lead2","email":"testlead@marketo.com","createdAt":"2015-07-07T21:43:43Z","firstName":"Test"}],"success":true} |
Now we have lead data which we can process in whatever way that we need. Thanks for reading, and please leave any feedback you have in the comments.