Skip to main content

CDP reverse ETL and data share

The CDP integrations page (/integrations/cdp) carries two reverse-ETL families and one data-share family, and each family owns a distinct pipeline:
  • Sources (reverse-ETL) — pull warehouse rows into the CDP event stream (Postgres today; BigQuery, Snowflake, and Databricks connectors route the same emit path).
  • Reverse-ETL destinations — push CDP contacts, events, and computed profile traits out to a warehouse you own (BigQuery, Snowflake, Redshift, Postgres, Databricks, ClickHouse).
  • Interaction data share — push Orbit’s own core interaction records (calls, messages, conversations) into an Iceberg/S3, BigQuery, or Snowflake warehouse under a versioned schema contract.
This guide walks each surface end to end, in the order an operator uses them on the page: the source import first, then the outbound destinations, then the data-share tab. For the outbound push destination model, read the reverse-ETL destination model; for the per-destination setup recipes, read the reverse-ETL warehouse exports guide. This page is the operational map — which tab owns what.

1. What reverse ETL does (the Sources tab)

The Sources (reverse-ETL) tab answers the inbound direction: pull rows out of a warehouse you own and emit them into your CDP event stream, so the warehouse becomes a first-class CDP source next to your SDK and HTTP endpoints. Each source row carries a name, a connector kind, an encrypted connection string, a parameterised SQL query, and a schedule:
  • Connector kindspostgres (self-managed) is the direct-connection path; bigquery, snowflake, and databricks route through API-driven connectors that share the same emit + cursor-advance path as Postgres.
  • The SQL query is a read-only SELECT with a single {cursor} placeholder. The scheduler binds the placeholder as a parameter, and the service layer rejects non-SELECT statements, so the query can never write.
  • cursor_column names the watermark column the scheduler advances between runs.
  • event_name is the CDP event type each row lands under (default warehouse.row).
  • schedule_minutes sets the poll cadence (5 minutes to 24 hours; default hourly).
  • Status is active, paused, or errored.
Create a source from the tab or the API:
The connection string is stored encrypted at rest and never returned by any read; GET /api/v1/cdp/sources returns only the non-secret shape. Pausing is a confirm-gated action in the tab because it silently halts the import; deleting is confirm-gated the same way.

2. Destinations panel (GET /cdp/reverse-etl/destinations)

The Destinations panel on the page answers the outbound question in one table: which reverse-ETL destinations are wired, which are enabled, and which are healthy. It consumes the aggregated read model GET /api/v1/cdp/reverse-etl/destinations — one query for the whole destination overview instead of one config GET per destination. Each row shows the destination name and category from the connector catalog, a state badge (Enabled / Paused / Not configured), a credentials-presence flag, and the derived health. A row carries a Sync now action only when the destination is configured and enabled — the server advertises that gate per row, so a disabled destination can never receive a sync request. Use the panel to answer “which destinations are wired?” at a glance; drill into the per-warehouse editor (next section) to change a destination’s settings.

3. Warehouse editor (Snowflake + Redshift, sibling to BigQuery)

The Reverse ETL config cards edit each destination’s connection. GET /api/v1/cdp/reverse-etl owns the BigQuery destination; GET /api/v1/cdp/reverse-etl/warehouse/:warehouse owns the non-Google warehouses — snowflake, redshift, postgres, databricks, clickhouse. For Snowflake, the editor asks for the account, warehouse name, role, database, schema, table prefix, cadence, and an RSA key pair. For Redshift and Postgres, host, port, database, schema, and credentials. The credential field is write-only: GET never returns it, the editor shows a “configured” badge when one is stored, and leaving the field blank keeps the existing secret. Saves are explicit, and identifier validation runs server-side. For the full Snowflake key-pair and BigQuery service-account recipes, use the reverse-ETL warehouse exports guide.

4. Segment exports (GET /cdp/reverse-etl/segment-exports)

The Segment exports card answers the segment side: which of your segments sync membership into which warehouse destination. It consumes the aggregated read model GET /api/v1/cdp/reverse-etl/segment-exports. Every destination row carries a capability verdict — native (first-class segment-membership propagation), organic (reachable via SQL over the exported rows), or not_configured — and every blocked segment carries an explicit block_reason, so you always see why a segment is not propagating instead of silently missing it. The card is read-only; destination credentials are edited on the sibling config cards.

5. Profile exports (GET /cdp/reverse-etl/profile-exports)

The Profile exports card is the trait-side twin: which of your computed traits propagate with the exported contacts entity into which destination. It consumes GET /api/v1/cdp/reverse-etl/profile-exports and renders the same capability verdicts as the segment card — native traits land as first-class columns on BigQuery, Snowflake, Redshift, and Postgres; organic destinations (Databricks, ClickHouse) expose the trait data via SQL over the exported rows instead. A paused or archived trait shows its block_reason rather than vanishing.

6. Field mappings editor and sync-runs history

The Field mappings card edits the optional per-table exclude / rename map applied row-by-row before push. It writes the field_mappings key on the BigQuery config (PATCH /api/v1/cdp/reverse-etl); the id column is locked so the dedup key always survives. The Sync-runs card surfaces the latest export run for every configured warehouse destination in one table, consuming GET /api/v1/cdp/reverse-etl/sync-runs. Per destination you see the last-run timestamp, row counts (rows_contacts / rows_events), a derived health badge (ok, failing, stale, never_run, or disabled), the last-error detail, and two on-demand actions — Sync now (run the normal forward delta at the next scheduler tick) and Backfill (replay history from an optional instant) — both gated on a configured + enabled destination. Health is derived server-side and rendered as-is. PATCH the BigQuery config with a field-mappings block directly:

7. How errors surface

Failures never stay silent. A destination’s read surfaces carry a sanitized last_error code — a coarse enum such as config_or_credential, tenant_client_open, or export_stream — never the raw driver message, so the error panel is safe to share with an audit channel. The Sources tab surfaces its own sanitized source-side codes through the same mapping. Watch the consecutive_failures count on the sync-runs read; the dashboard paints a warning once it exceeds zero.

8. Interaction data share (raw interaction records)

The Data share (warehouse) tab is a distinct family from reverse ETL. Where the destinations above fan out CDP audiences, segments, events, and profiles, this tab shares the platform’s own core interaction records — calls, messages, and conversations — into your warehouse under a governed, versioned schema contract, with a historical-backfill request.
  • Schema contractGET /api/v1/cdp/interaction-data-share/schema-contract lists every published contract version and the exact field list per dataset (calls, messages, conversations). Fields are never removed or retyped within a version once published; a new field only ever appears in a new version, so a warehouse model pinned to an older version keeps working.
  • TargetsGET/PATCH /api/v1/cdp/interaction-data-share/:provider for iceberg_s3, bigquery, or snowflake. The PATCH writes connection identifiers, the datasets to share, the governing contract version, and the encrypted credential (Iceberg REST-catalog token or AWS secret access key, service-account JSON, or Snowflake password / private key). The credential is encrypted at rest and never returned; the tab shows a “configured” badge.
  • BackfillPOST /api/v1/cdp/interaction-data-share/:provider/backfill requests a one-off historical backfill for a subset of the configured datasets over a date range. Only one backfill is in flight per provider, and the request is rejected unless the target is enabled and fully configured.
Config, validation, the schema-contract registry, and the backfill request are live today; the scheduled egress worker that carries the rows advances the last_run_* / backfill status fields the tab renders read-only. Pick data share when you need raw interaction records (calls, messages, conversations) for your own BI or data-science layer. Pick reverse ETL when you need the CDP’s modeled entities — contacts, events, segments, and computed profile traits.

9. Admin path versus DPO

The reverse-ETL and data-share surfaces are config surfaces: the fields they write (connection identifiers, cadences, dataset lists, contract versions) are tenant-owned controls, and the secrets they accept are stored encrypted and never returned. That is the surface a normal admin path needs. A data-protection review cares about a different question — where does personal data live before it fans out to a destination? Route that review to the Data catalog and Erasure propagation surfaces, which classify per property and set per-destination delete-versus-suppress policy. Keep the reverse-ETL tabs for the wiring itself; do not use them as the audit surface.