Custom Objects

Custom Object Endpoint Reference

Marketo allows users to define custom objects which are related either to lead records, or account records.  For information on defining these, please see this article.

Custom Objects are unavailable for some Marketo subscription types.  If you don’t have access to this feature, please, speak to your account manager.


In addition to the standard describe, query, update, and delete calls available for lead database objects, Custom Objects have a list call available.  Calling this endpoint will return a response with a list of custom objects available in the destination instance, along with additional metadata about the objects.

The response will give a list of the relationships present on each object.  A relationship will have a “field” member which indicates the field on the object which holds the link value, a “type” member which indicates if the relationship is to a parent or a child type object, and a “relatedTo” object indicating the name of the related object, and the link field on that object.


The describe call for custom objects follows the same pattern as that of Opportunities and Companies, with the addition of the “relationships” array in the response and a “name” path parameter in the URI which takes the name of the custom object type to be described.  Like the list call, this will list any relationships that are available for this custom object type.


Querying custom objects is slightly different from other Lead Database APIs, and takes “name” path parameter like describe.  For a normal filterType parameters, the query is a simple GET like queries for other types of records, and requires a filterType and filterValues.  It will optionally accept fields, batchSize, and nextPageToken parameters.

Alternatively, when querying with compound keys, the API behaves like the Opportunity Roles API, accepting a POST with a JSON body.  The JSON body may have the same members as a GET query, except for filterValues.  Instead of filter values, there is an “input” array which takes objects which contain a member named for each of the object type’s dedupeFields.

Create and Update

To create or update records, custom objects follow the standard pattern for lead database objects, and is largely based on the information available in the description of the object type.  In an example car object, there is just one dedupe field, “vin.”  In order to update or create records when using dedupeFields mode, each record in our input needs to include at least a “vin” field.

When performing updates via idField mode, the idField will always be marketoGUID, so each record will always require a marketoGUID field.  Remember that idField is only valid for the updateOnly action type, as this field is always system managed.  Your response will include the status of each individual record in the result array, and either a marketoGUID or a reasons array depending on whether or not the operation was successful for an individual record.


Deleting records is very straightforward.  Just select your deleteBy mode, either idField or dedupeFields, and include the corresponding fields in each of the records in your input.

Like updating, your result will contain a status for each individual record, and either a marketoGUID or a reasons array depending on whether the delete was successful.

Bulk Import

Bulk Import functionality is not available until Winter ’17 Release.


//TODO: link “bulk API” to custom object bulk api


For large amounts of custom object records, you may import custom objects asynchronously using the bulk API.  This allows you to import a list of records into Marketo using a flat file with delimiters (comma, tab, or semicolon).  The file can contain any number of records, provided it’s size is less than 10MB.

The contents of the file will depend on your custom object definition.  The first row always contains a header that lists the REST API fields to map values of each row into.  The remaining rows contain custom object data records, each record separated into fields.

Before making use of any of the bulk APIs, you must first create your custom object.  Let’s look at an example.  Suppose we create a custom object named “Car” and give it 4 fields: “Color”, “Make”, “Model”, “VIN”.  We’ll use the VIN field for deduplication.  Below we have highlighted the REST API names because they must be sent to bulk import-related endpoints.

Example Custom Object


Example Custom Object Fields


Now suppose that we want to import 3 records.  The file could look like this:



To make the bulk import request, you must include REST API name of the custom object in the path.  You must also include a “file” parameter that references the name of your flat file and a”format” parameter that specifies the format of your flat file (“csv”, “tsv”, or “ssv”).

A simple way to replicate this request is to use cURL from the command line:


Notice in the response to our call, here is no listing of successes or failures like you would get back from Sync Custom Objects.  Instead, you receive a “batchId”.  This is because the call is asynchronous, and can return a status of “Queued”, “Importing”, or “Failed”.  You should retain the “batchId” so that you can get status of the import job, or retrieve failures and/or warnings upon completion.  Note that the “batchId” remains valid for 7 days.

Import Status

Once the import job has been created, you need to query it’s status.  It is best practice to poll the import job every 5-30 seconds.  Do this with the Get Import Custom Object Status API.

This response shows a completed import, but the status can be one of:

  • Complete
  • Queued
  • Importing
  • Failed

If the job has completed, you will have a listing of the number of rows processed, with failures, and with warnings.  The message attribute is also a good place to look for additional job information.


If “numOfRowsFailed” attribute is not zero, then call Get Import Custom Object Failure File to obtain a file with error detail.  You must pass the REST API name and “batchId” in the path.

Continuing with the example, we can force an error by modifying the header and change “vin” to ” vin” (by adding a space between the comma and “vin”).

When we import and check the status we see this response with “numRowsFailed” : 3

Now we’ll make another call to get additional error detail:

And we can see that we’re missing our deduplication field “vin”.


If “numOfRowsWithWarning” attribute is not zero, then call Get Import Custom Object Warning File to obtain a file with warning detail.  You must pass the REST API name and “batchId” in the path.