POST /bulk/v1/leads.json?format=csv with a multipart/form-data body containing the CSV file and a 'lookupField' parameter (e.g. 'email') to initiate the bulk import job; receive a 'batchId' in the response
Poll GET /bulk/v1/leads/batch/{batchId}.json until the 'status' field is 'Complete' or 'Failed', checking 'numOfRowsFailed' and 'numOfRowsWithWarning'
If numOfRowsFailed > 0, GET /bulk/v1/leads/batch/{batchId}/failures.json to download the CSV of failed rows with error descriptions in an appended column
If numOfRowsWithWarning > 0, GET /bulk/v1/leads/batch/{batchId}/warnings.json to review non-fatal issues
Map CSV column headers to Marketo field API names exactly — Marketo does not auto-match by display name; run GET /rest/v1/leads/describe.json first to confirm correct REST API names
Known gotchas
Marketo Bulk APIs use a separate base URL path (/bulk/v1/) distinct from the REST API (/rest/v1/); using the wrong path prefix returns a 404 without explanation
Bulk import jobs are queued and may not start immediately — Marketo processes one bulk job at a time per instance; during high queue periods jobs may wait minutes before execution begins
The lookupField determines deduplication behavior: if a lead with the lookup value already exists it is updated, not duplicated; if two rows in the import CSV share the same lookup value, the later row overwrites the earlier one silently
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp