Docs
Connectors

Salesforce Marketing Cloud connector

Marketing audiences, campaigns, messaging, and engagement data.

View Markdown

Use this as an implementation starting point: adapt the worked example to the requested dataset and the source documentation. See Custom API for the shared SDK pattern and document-upload workflow.

What this connector is for

Marketing audiences, campaigns, messaging, and engagement data.

Use this guide to choose the resources and row meanings for a Vortexify source integration. Connection ownership belongs to a connector; each dataset gets its own sync, configuration, and extraction behavior.

Data and tables you can pull

The following table families are a starting point for source selection. They describe possible datasets to implement using the vendor reference, not a guarantee that the example implements every table. Actual availability depends on the product edition, deployment, account permissions, and API/schema version.

Suggested tableOne row represents
data_extensionsa data extension
data_extension_rowsa data extension row
subscribersa subscriber
email_tracking_eventsa email tracking event
journeysa journey

Relationships and extraction considerations

These are proposed dataset names, not a universal schema guaranteed by the vendor. Preserve source object IDs and relationship references, and split nested child collections into separate tables when appropriate. Choose the concrete endpoint/report and row meaning from the vendor reference before implementing a sync.

Connecting to Salesforce Marketing Cloud

Select Marketing Cloud Engagement and its business-unit context for the listed resources. Installed-package OAuth, REST endpoints, SOAP retrieval, and data-extension schemas need separate handling. Other Marketing Cloud products use different APIs.

For HTTP reads, configure the connector client with the concrete API origin and source-authorized headers or authentication object. Actual credentials belong in platform secret configuration, not in this document or committed source.

requirements.in

Declare these packages in the resource's requirements.in. Use the published vortexify package for the SDK and the source-specific driver/client shown below. Choose compatible dependency versions for your runtime; the connector and sync reference explains where each file belongs.

vortexify==0.1.1
pandas>=2,<3
httpx

This HTTP starting point needs no native database driver. Add the source-specific SDK, signer, or XML parser if the selected interface requires it.

Worked example: adapt the documented read/query operation

This request recipe is for an agent to fill from the selected product/deployment reference. The resource path, request body, and record-array path remain explicit inputs because the source interface or account contract determines them. It executes one documented JSON read and shapes its records; it does not assert a universal endpoint or schema for this source.

request_spec uses HTTPX request arguments, for example method, url, params, and json. Select a read/query operation even when its HTTP method is POST. rows_path is the actual sequence of JSON object keys leading to its records array (an empty list selects a root array). For XML/SOAP or asynchronous exports, adapt the transport/decoder first using the source-specific notes below.

Source read

import pandas as pd


def read_documented_page(client, request_spec: dict, rows_path: list[str]):
    # Fill request_spec from a documented READ operation for this deployment.
    # It contains method, url, and optional params/json/content/headers.
    method = request_spec["method"].upper()
    if method not in {"GET", "POST"}:
        raise ValueError("Select the documented read/query operation")
    response = client.request(**request_spec)
    response.raise_for_status()
    payload = response.json()
    if isinstance(payload, dict) and (
        payload.get("errors") or payload.get("success") is False
    ):
        raise ValueError("Source returned an application error")
    rows = payload
    for key in rows_path:
        rows = rows[key]
    if not isinstance(rows, list) or any(not isinstance(row, dict) for row in rows):
        raise ValueError("rows_path must select the documented record array")
    return pd.json_normalize(rows)

What to adapt

Select Engagement REST, SOAP, or a data-extension query/export deliberately, using the installed-package business-unit context. Obtain the instance URLs through token acquisition. Data-extension rows have customer-defined fields; SOAP Retrieve requires XML parsing and continuation, not the JSON helper below.

Use the custom API SDK starting point to connect the read operation to Connector and Sync. For a source with its own driver, retain that client in Connector.client() and replace the HTTP request with the driver read. An extract(*, avg_row_size_bytes=None) implementation yields bounded DataFrames. An independent preview() uses a fresh connector and a small read; it must not call extraction or advance real state.

Choose explicit output columns and stable IDs for the requested table. The examples use json_normalize where useful to illustrate row shaping; nested arrays still need deliberate child tables and a stable declared output schema. A first-page sample is useful for development, while a full sync must follow all relevant continuation/parent-resource paths. Design incremental watermarks, update/deletion behavior, and rate-limit handling for the actual source before enabling incremental mode.

The purpose is to give a coding agent a concrete pattern to adapt, including for similar sources. These snippets are examples rather than a claim of complete vendor coverage. Check the source operation reference and representative responses before running with a customer's account; live vendor execution has not been verified here.

Sources and further reading