Marketo Connector Guide

The Marketo connector enables Tealfabric workflows to create and update leads, trigger campaigns, and read engagement data through the Marketo REST API. This guide explains secure OAuth setup, practical request patterns, and reliability practices for production marketing automation.

Document information
FieldValue
Canonical URL/docs/04_connecting-systems/connectors/m/marketo
Version (published date)2026-05-08
Tagsconnectors, reference, marketo
Connector IDmarketo-1.0.0

Marketo connector flow showing OAuth-secured API access, lead sync operations, and campaign trigger automation from Tealfabric workflows.

When to use this connector

Use this connector when workflows need to keep lead records synchronized, enrich profiles from product or CRM events, or trigger Marketo campaigns based on operational milestones. It is especially effective for lifecycle automation where marketing state and business state must stay aligned. A consistent identifier strategy, usually email or lead ID, improves data quality across systems.

Prerequisites

Before configuring the integration, register a LaunchPoint service in Marketo and enable API access in your Marketo instance. Confirm your base URL and OAuth credentials, then validate that scopes and API roles allow the operations your workflow will execute. Early permission validation prevents runtime failures during lead writes or campaign triggers.

Configuration reference

Connector credentials are stored in integration configuration and reused during execution. Keep tokens and secrets secure and rotate them according to policy.

The test operation validates OAuth app configuration (client_id, client_secret, redirect_uri) and confirms the current access token via GET rest/v1/leads.json. Other operations (send, receive, sync, batch) require a valid access_token and base_url at runtime.

  • base_url (required): Marketo REST API base URL, such as https://123-ABC-456.mktorest.com.
  • client_id (required for test and token refresh): OAuth client ID from Marketo LaunchPoint.
  • client_secret (required for test and token refresh): OAuth client secret paired with the client ID.
  • redirect_uri (required for test and token refresh): OAuth redirect URI configured for the integration.
  • access_token (required at execute time): Access token used for API calls.
  • refresh_token (optional): Refresh token for renewing access on HTTP 401.
  • scope (optional): OAuth scope string when required.
  • timeout_seconds (optional): Timeout for connector requests (default 30).

Create or update leads

The send operation is commonly used with createOrUpdate lead actions so workflow events can upsert lead records safely. Keep payloads minimal and include only fields you own to avoid unintended overwrites.

const baseUrl = "https://api.example.com/api/v1";
const tenantId = "<TENANT_ID>";
const apiKey = "<API_KEY>";

type MarketoUpsertResult = {
  id?: number;
  status?: string;
  reasons?: Array<{ code?: string; message?: string }>;
};

async function upsertMarketoLead(integrationId: string): Promise<MarketoUpsertResult> {
  const response = await fetch(
    `${baseUrl}/integrations/${encodeURIComponent(integrationId)}/execute`,
    {
      method: "POST",
      headers: {
        "X-API-Key": apiKey,
        "X-Tenant-ID": tenantId,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        operation: "send",
        endpoint: "rest/v1/leads.json",
        method: "POST",
        data: {
          action: "createOrUpdate",
          lookupField: "email",
          input: [
            {
              email: "lead@example.com",
              firstName: "Jordan",
              lastName: "Lee",
              company: "Example Corp",
            },
          },
        },
      }),
    }
  );

  if (!response.ok) throw new Error(`Request failed: ${response.status}`);
  const payload = (await response.json()) as {
    success?: boolean;
    data?: { data?: { status_code?: number; data?: MarketoUpsertResult } };
  };
  return payload.data?.data?.data ?? payload.data?.data;
}
curl -X POST "https://api.example.com/api/v1/integrations/<ENTITY_ID>/execute" \
  -H "X-API-Key: <API_KEY>" \
  -H "X-Tenant-ID: <TENANT_ID>" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "send",
    "endpoint": "rest/v1/leads.json",
    "method": "POST",
    "data": {
      "action": "createOrUpdate",
      "lookupField": "email",
      "input": [
        {
          "email": "lead@example.com",
          "firstName": "Jordan",
          "lastName": "Lee"
        }
      ]
    }
  }'
{
  "success": true,
  "data": {
    "message_count": 1,
    "data": {
      "status_code": 200,
      "data": {
        "success": true,
        "result": [
          { "id": 1234567, "status": "updated" }
        ]
      }
    },
    "response": {
      "status_code": 200,
      "data": {
        "success": true,
        "result": [
          { "id": 1234567, "status": "updated" }
        ]
      }
    }
  }
}

Retrieve leads and activity data

Use receive when workflows need lead snapshots, incremental updates, or activity data for segmentation and reporting. Pagination with nextPageToken is important for high-volume datasets.

const baseUrl = "https://api.example.com/api/v1";
const tenantId = "<TENANT_ID>";
const apiKey = "<API_KEY>";

type LeadRecord = {
  id?: number;
  email?: string;
  firstName?: string;
  lastName?: string;
};

async function fetchLeadByEmail(integrationId: string): Promise<LeadRecord[]> {
  const response = await fetch(
    `${baseUrl}/integrations/${encodeURIComponent(integrationId)}/execute`,
    {
      method: "POST",
      headers: {
        "X-API-Key": apiKey,
        "X-Tenant-ID": tenantId,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        operation: "receive",
        endpoint: "rest/v1/leads.json",
        query: {
          filterType: "email",
          filterValues: "lead@example.com",
          fields: "email,firstName,lastName,company",
        },
      }),
    }
  );

  if (!response.ok) throw new Error(`Request failed: ${response.status}`);
  const payload = (await response.json()) as { data?: { data?: LeadRecord[] } };
  return payload.data?.data ?? [];
}

Validate integration health and token lifecycle

Run test after token rotations, LaunchPoint permission changes, or endpoint updates. Most production errors are caused by expired tokens, invalid scopes, or request payload mismatches. Keep execution IDs and API error payloads in logs so incident triage is fast and repeatable.

curl -X POST "https://api.example.com/api/v1/integrations/<ENTITY_ID>/execute" \
  -H "X-API-Key: <API_KEY>" \
  -H "X-Tenant-ID: <TENANT_ID>" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "test"
  }'
{
  "success": true,
  "data": {
    "message": "Marketo connection test successful",
    "details": {
      "api_base_url": "https://123-ABC-456.mktorest.com"
    }
  }
}

Additional references

For endpoint-specific schemas and auth details, use the Marketo REST API documentation and Marketo authentication guide. Keeping field ownership and sync rules documented with your workflow logic improves long-term reliability.