Over a year ago we posted Updating customer and prospect information in Marketo using the API. That post presented a code sample that could be run on a recurring basis to poll a external system for updates. The idea was to retrieve the external data and push it into Marketo to update lead information. The code sample presented used our SOAP API. This post will show you how to use Create/Update Leads REST endpoint to accomplish the same goal.
Program Input
It is likely that you will need to transform the data from the external system into a format that is consumable by Marketo REST APIs. Since we’re using the Create/Update Leads API, the data must be formatted as JSON which is sent in the request body. This is best explained by an example.
In the Java sample code below, we have placed mock lead data in an array of strings. Each string following data for each lead: first name, last name, email address, job title.
1 2 3 4 |
private static String externalLeadData[] = { "Henry, Adams, henry@superstar.com, Director of Demand Generation", "Suzie, Smith, ssmith@gmail.com, VP Marketing" }; |
The sample code transforms the array into the JSON block below.
1 2 3 4 5 6 7 |
{ "input": [ {"firstName":"Henry", "lastName":"Adams", "email":"henry@superstar.com", "title":"Director of Demand Generation"}, {"firstName":"Suzie", "lastName":"Smith", "email":"ssmith@gmail.com", "title":"VP Marketing"} ] } |
Each “input” array item corresponds to an individual lead in Marketo. The array items are JSON objects that contain one or more Marketo lead field names and their respective values.
The field names that you decide to specify (in this case firstName, lastName, email, and title) must match the REST API name defined for the Marketo subscription. You can find the REST API Names in the field management section within Marketo admin panel by exporting the field names.
The field names will be exported into an excel file as seen below.
Alternatively, you can find field names programmatically by calling the Describe Lead API. For example, here is a Describe response snippet that contains the REST API name for the First Name field.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "id": 29, "displayName": "First Name", "dataType": "string", "length": 255, "soap": { "name": "FirstName", "readOnly": false }, "rest": { "name": "firstName", "readOnly": false } }, |
Program Logic
Once the payload is in the proper format, we are ready to call Create/Update Leads. Note that in this sample we do not specify any of the optional parameters. The default behavior is to create or update lead records (upsert), use email for deduplication purposes, and use synchronous processing.
If the call to Create/Update leads is successful, then the response body contains a “result” array containing the Marketo Lead Id and the status of the Create/Update operation. Depending on the “action” parameter you passed in the request, the status can be either “updated”, “created”, or “skipped”.
Continuing with our example, suppose the first lead did not exist (Henry Adams), and the second lead did exist (Suzie Smith). A response similar to the following would indicate the first lead was created, and the second lead was updated.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "success":true, "requestId":"118f8#14f1a0b82fc", "result":[ { "id":318798, "status":"created" }, { "id":318797, "status":"updated" } ] } |
That’s it for now. Happy coding!
Program Code
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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
package com.marketo; // minimal-json library (https://github.com/ralfstx/minimal-json) import com.eclipsesource.json.JsonArray; import com.eclipsesource.json.JsonObject; import javax.net.ssl.HttpsURLConnection; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.net.MalformedURLException; import java.net.URL; import java.util.*; public class CreateUpdateLeads { // // Define Marketo REST API access credentials: Account Id, Client Id, Client Secret. For example: // public static String CUSTOM_SERVICE_DATA[] = // {"111-AAA-222", "2f4a4435-f6fa-4bd9-3248-098754982345", "asdf6IVE9h4Jjcl59cOMAKFSk78ut12W"}; // private static final String CUSTOM_SERVICE_DATA[] = { INSERT YOUR CUSTOM SERVICE DATA HERE }; // // Mock up data that could be read from an external data source. // An array of CSV strings the form: // "firstName, lastName, email, title" private static String externalLeadData[] = { "Henry, Adams, henry@superstar.com, Director of Demand Generation", "Suzie, Smith, ssmith@gmail.com, VP Marketing" }; public static void main(String[] args) { // Compose base URL String baseUrl = String.format("https://%s.mktorest.com", CUSTOM_SERVICE_DATA[0]); // Compose Identity URL String identityUrl = String.format("%s/identity/oauth/token?grant_type=%s&client_id=%s&client_secret=%s", baseUrl, "client_credentials", CUSTOM_SERVICE_DATA[1], CUSTOM_SERVICE_DATA[2]); // Call Identity API JsonObject identityObj = JsonObject.readFrom(httpRequest("GET", identityUrl, null)); String accessToken = identityObj.get("access_token").asString(); // Compose URL for Create/Update Leads String createUpdateLeadsUrl = String.format("%s/rest/v1/leads.json?access_token=%s", baseUrl, accessToken); // Convert String array into JsonArray to pass as part of request body JsonArray input = convertExternalLeadDataToJson(externalLeadData); // Build request body JSON JsonObject requestObj = new JsonObject(); requestObj.add("input", input); // Call Create/Update Lead API JsonArray result = new JsonArray(); JsonObject leadObj = JsonObject.readFrom(httpRequest("POST", createUpdateLeadsUrl, requestObj.toString())); if (leadObj.get("success").asBoolean()) { if (leadObj.get("result") != null) { result = leadObj.get("result").asArray(); } } // Print out results object System.out.println(result); System.exit(0); } // Convert array of CSV formatted Strings into an array of JSON objects private static JsonArray convertExternalLeadDataToJson(String input[]) { JsonArray output = new JsonArray(); // Loop through each CSV row in array for (int i = 0; i < input.length; i++) { // Split CSV row into separate fields List items = Arrays.asList(input[i].split(",")); // Add fields to JSON object JsonObject lead = new JsonObject(); lead.add("firstName", items.get(0)); lead.add("lastName", items.get(1)); lead.add("email", items.get(2)); lead.add("title", items.get(3)); output.add(lead); } return output; } // Perform HTTP request private static String httpRequest(String method, String endpoint, String body) { String data = ""; try { URL url = new URL(endpoint); HttpsURLConnection urlConn = (HttpsURLConnection) url.openConnection(); urlConn.setDoOutput(true); urlConn.setRequestMethod(method); switch (method) { case "GET": break; case "POST": urlConn.setRequestProperty("Content-type", "application/json"); urlConn.setRequestProperty("accept", "text/json"); OutputStreamWriter wr = new OutputStreamWriter(urlConn.getOutputStream()); wr.write(body); wr.flush(); break; default: System.out.println("Error: Invalid method."); return data; } int responseCode = urlConn.getResponseCode(); if (responseCode == 200) { InputStream inStream = urlConn.getInputStream(); data = convertStreamToString(inStream); } else { System.out.println(responseCode); data = "Status:" + responseCode; } } catch (MalformedURLException e) { System.out.println("URL not valid."); } catch (IOException e) { System.out.println("IOException: " + e.getMessage()); e.printStackTrace(); } return data; } private static String convertStreamToString(InputStream inputStream) { try { return new Scanner(inputStream).useDelimiter("A").next(); } catch (NoSuchElementException e) { return ""; } } } |