Last updated: October 30, 2026, 15:50 (UTC+1).

Runtime verified

Verification scope: Live-org reads and the explicitly described bounded operations were tested. The operation-specific limitations still apply; this badge does not verify untested writes or general CRUD support.

Back to Data Cloud with Salesforce CLI. Start with its setup, placeholders and safety guidance before running these examples.

A segment selects an audience using rules. Publishing prepares it for use; refreshing recalculates it, while activation sends data to a destination. These are distinct from saving the definition. A unified DMO contains the combined profiles produced by identity resolution; use an existing one with its actual key.

The examples distinguish UI criteria built in Salesforce’s visual interface from DBT/Dbt, a SQL-based pipeline representation. You do not need to install a separate dbt command-line tool for the requests here. CRUD simply abbreviates create, read, update and delete.

MarketSegmentDefinition is the Metadata API XML definition of the same segment, not a separate segment type. Both metadata commands and runtime API requests below use Salesforce CLI. Saving XML alone need not create a usable live segment. The XML writes cover source-only API 65 DBT Metadata definition CRUD; cross-org replay and deployment without processing have not been verified. Being able to retrieve UI criteria does not establish UI-definition writes.

This API 65 runtime route creates a live segment. Unlike saving XML alone, it can begin processing immediately: NoRefresh can transition PROCESSING → ACTIVE. Empty-result SQL does not prevent scanning or processing either. Get permission for those effects before creating or updating a segment.

The example does not set up a send destination, export members or prove cross-org migration.

Route-specific SQL limits: Salesforce’s native DBT validation guide documents WHERE-only single-column subqueries and an optional key-qualifier join condition. The separately discovered MCP segment-create description is narrower: it disallows subqueries and compound join conditions. The native guide’s API version and the discovery provider’s underlying API version were not supplied. Do not transfer those rules between native API 65 examples, the API 67 org-local facade and hosted MCP, or treat documentation as live qualification of broader SQL edits.

Supplied workflows for Segments
RetrieveCreateUpdateDelete
Yes
CLI API
Partial
CLI API
Partial
CLI API
Partial
API

Yes: a usable scoped workflow is supplied. Partial: a usable bounded, combined or incomplete asynchronous workflow is supplied. Neither means universal capability. No: proven unavailable in an explicit scope. ?: unknown, untested or no usable workflow supplied. Neither No nor ? displays method icons. CLI means dedicated CLI commands; API means API-led requests or facades, even when invoked through the CLI. Two icons identify alternatives, not equivalent coverage. Read each operation's prerequisites and limits. An available operation tab may explain an illustrative mechanism without supplying a usable summary workflow.

Retrieve

  • CLI — Available: Save the XML definition; runtime settings and audience rows are not included.
  • API — Available: Read runtime configuration, not an XML file or audience export.
  • sf-plugin-data — Unknown: Not implemented in this guide; no workflow is supplied.

CLI

Save the XML definition

For an existing segment:

sf project retrieve start --metadata MarketSegmentDefinition:ActiveCustomers --target-org SOURCE_ALIAS --api-version 65.0 --wait 5 --json

This writes force-app/main/default/marketSegmentDefinitions/ActiveCustomers.marketSegmentDefinition-meta.xml. A UI retrieval example, separate from the DBT creation example, looks like this:

<MarketSegmentDefinition xmlns="http://soap.sforce.com/2006/04/metadata">
  <masterLabel>Active Customers</masterLabel>
  <segmentOn>UnifiedCustomer__dlm</segmentOn>
  <segmentType>UI</segmentType>
  <!-- Retrieved selection criteria omitted. -->
</MarketSegmentDefinition>

The XML omits lookback, schedule, state and dataspace. It does not publish, count or activate the segment. Referenced objects, fields and relationships remain dependencies; NO_REFRESH is not proof that a later deployment will do no initial processing.

API

Read runtime state through the CLI

sf api request rest '/services/data/v65.0/ssot/segments/ActiveCustomers' --method GET --target-org TARGET_ALIAS --json

The lookback is the time window used by the segment; P90D is duration notation for 90 days. Check the returned value rather than assuming every segment uses it.

GET wraps the segment in a segments array:

{ "segments": [{ "apiName": "ActiveCustomers", "segmentStatus": "ACTIVE", "lastSegmentMemberCount": 0, "publishInterval": "NO_REFRESH", "lookbackPeriod": "P90D", "dataSpace": "default", "segmentOnApiName": "UnifiedCustomer__dlm" }] }

Check the exact segment, SQL/model, type, dataspace, segment-on object, lookback and schedule. Wait for processing to settle before the next change. REST does not write the XML file for you. For audience rows rather than configuration, see Segment members.

Create

  • CLI — Available: Source-only API 65 DBT definition creation; runtime creation and processing-free deployment are not established.
  • API — Available: Live API 65 DBT creation can begin processing even with NoRefresh.
  • sf-plugin-data — Unknown: Not implemented in this guide; no workflow is supplied.

CLI

Store only an XML definition

Use a separate project containing only this owned definition, with a compatible existing unified DMO/key. Save force-app/main/default/marketSegmentDefinitions/CustomerDefinition.marketSegmentDefinition-meta.xml:

<?xml version="1.0" encoding="UTF-8"?>
<MarketSegmentDefinition xmlns="http://soap.sforce.com/2006/04/metadata">
  <includeCriteria>&lt;DbtPipeline xmlns=""&gt;&lt;models&gt;&lt;model&gt;&lt;name&gt;CustomerDefinition&lt;/name&gt;&lt;sql&gt;SELECT UnifiedCustomer__dlm.CustomerKey__c FROM UnifiedCustomer__dlm WHERE 1 = 0&lt;/sql&gt;&lt;/model&gt;&lt;/models&gt;&lt;/DbtPipeline&gt;</includeCriteria>
  <masterLabel>Customer Definition</masterLabel>
  <segmentType>DBT</segmentType>
</MarketSegmentDefinition>

Escaping preserves text that would otherwise be interpreted as file syntax: &lt; means <, &gt; means > and &amp; means & in XML text. Decoding reverses that representation; it does not execute the contents. Keep the escaping when saving nested XML, and do not replace it with raw tags.

includeCriteria contains XML-escaped pipeline XML. This DBT form has no segmentOn element. Replace the model and DMO/key consistently, and obtain permission for possible processing even with the empty-result SQL.

sf project deploy start --source-dir force-app --target-org SOURCE_ALIAS --api-version 65.0 --wait 5 --json
sf project retrieve start --metadata MarketSegmentDefinition:CustomerDefinition --target-org SOURCE_ALIAS --api-version 65.0 --wait 5 --json
{ "status": 0, "result": { "success": true, "status": "Succeeded", "details": { "componentSuccesses": [{ "componentType": "MarketSegmentDefinition", "fullName": "CustomerDefinition", "created": true, "changed": true, "success": true }] } } }

The second command downloads the definition for comparison. Check the decoded model/SQL, label and type. A successful deploy can still leave runtime GET returning ITEM_NOT_FOUND; --dry-run would not store anything at all. The project-wide selector above is why this project must contain no unrelated files.

API

Create a live segment

Save segment-create.json, replacing the existing unified DMO/key and model name consistently:

{
  "developerName": "ActiveCustomers",
  "displayName": "Active Customers",
  "description": "Customer segment with an empty initial audience",
  "segmentOnApiName": "UnifiedCustomer__dlm",
  "segmentType": "Dbt",
  "includeDbt": {
    "models": {
      "models": [{ "name": "ActiveCustomers", "sql": "SELECT UnifiedCustomer__dlm.CustomerKey__c FROM UnifiedCustomer__dlm WHERE 1 = 0" }]
    }
  },
  "publishSchedule": "NoRefresh"
}
sf api request rest '/services/data/v65.0/ssot/segments' --method POST --body '@segment-create.json' --target-org TARGET_ALIAS --json
{ "apiName": "ActiveCustomers", "segmentType": "DBT", "segmentStatus": "PROCESSING", "publishInterval": "NO_REFRESH", "lookbackPeriod": "P90D", "includeDbt": { "models": [{ "name": "ActiveCustomers", "sql": "SELECT UnifiedCustomer__dlm.CustomerKey__c FROM UnifiedCustomer__dlm WHERE 1 = 0" }] } }

There is an easy-to-miss difference: the request uses nested includeDbt.models.models, but the response has an array at includeDbt.models. Do not send the response back unchanged. P90D is an example returned lookback, not a universal writable default.

Update

  • CLI — Available: Only the owned DBT XML masterLabel change is qualified; Unchanged is not zero writes.
  • API — Available: Bounded full-definition label/description update or qualified forward empty-audience selected-primary-key predicate addition; reconcile unknown outcomes with reads.
  • sf-plugin-data — Unknown: Not implemented in this guide; no workflow is supplied.

CLI

Change only the XML definition’s label

In the owned DBT file, change only masterLabel to Customer Definition Updated. Keep the criteria, model, SQL and type intact:

sf project deploy start --source-dir force-app --target-org SOURCE_ALIAS --api-version 65.0 --wait 5 --json
sf project retrieve start --metadata MarketSegmentDefinition:CustomerDefinition --target-org SOURCE_ALIAS --api-version 65.0 --wait 5 --json

Expect changed: true for the label change. An identical repeat can report Unchanged. Unchanged is not zero writes: a deployment job still runs and package metadata can change. Broader SQL/criteria edits and live segment updates are not established by this route.

API

Change the live segment

A label-only PATCH is not enough here. Send the complete preserved definition, changing just the label and description. The example deliberately omits both publishSchedule and publishScheduleInfo to retain the existing no-refresh schedule. Do not re-send NoRefresh or invent a None schedule value.

Save segment-update.json:

{
  "displayName": "Active Customers Updated",
  "description": "Updated customer segment description",
  "segmentType": "Dbt",
  "segmentOnApiName": "UnifiedCustomer__dlm",
  "includeDbt": {
    "models": {
      "models": [{ "name": "ActiveCustomers", "sql": "SELECT UnifiedCustomer__dlm.CustomerKey__c FROM UnifiedCustomer__dlm WHERE 1 = 0" }]
    }
  }
}
sf api request rest '/services/data/v65.0/ssot/segments/ActiveCustomers' --method PATCH --body '@segment-update.json' --target-org TARGET_ALIAS --json
{ "apiName": "ActiveCustomers", "segmentStatus": "PROCESSING", "publishInterval": "NO_REFRESH", "lookbackPeriod": "P90D" }

GET again until ACTIVE, then compare the changed label/description and all preserved values. In one owned DBT update, separate reads observed PROCESSING → COUNTING → ACTIVE without intervention. COUNTING was not final success or proof of failure. The later ACTIVE read was about nine minutes after the observed COUNTING read; the exact transition time between those checks is unknown.

Independent runtime and standard XML retrieval then confirmed the exact updated label/description, original model/SQL/type, identities, dataspace, segment-on object, schedule/lookback and generated membership references. Description is runtime-only; the XML label agreed with runtime. The first command had already stopped with an unknown outcome: later API settlement does not retroactively make that command successful. Do not replay an update with an unknown outcome; reconcile it with reads. This label/description result does not establish arbitrary omitted-field preservation, general SQL/UI criteria updates or schedule/lookback editing.

A separate source-org existing-owner check correlated the runtime segment and its Metadata definition as one stable pair. Repeating the comparison against the unchanged desired definition found no further change to apply. Read and compare both views before deciding whether to PATCH; skip an already-matching update yourself. This is source-only comparison-before-write evidence, not API idempotency, processing-free deployment or unchanged-source cross-org replay.

Salesforce’s native DBT validation guide requires the segment-on primary key and any applicable key qualifiers in the projection. It documents WHERE-only, single-column subqueries and an optional key-qualifier join comparison. Those rules differ from the discovered MCP operation description; the discovery contract’s API version was not supplied. Keep native API and facade/hosted-MCP validation rules separate rather than treating either description as universal. These broader SQL forms were not live-qualified by the bounded updates on this page.

Qualified forward empty-audience predicate change

One separate source-only native API 65 update was verified on an existing owned ACTIVE, single-model DBT segment in the default dataspace. Its selected field was independently bound to the same PROFILE object’s primary key. Starting from the existing WHERE 1 = 0, the only SQL change appended AND <same selected object.field> IS NOT NULL:

SELECT UnifiedCustomer__dlm.CustomerKey__c FROM UnifiedCustomer__dlm WHERE 1 = 0 AND UnifiedCustomer__dlm.CustomerKey__c IS NOT NULL

The object and field above are placeholders: use the exact existing selected object and independently verified primary field, not a different field or a newly created segment. Keep the original model name, label, description, segment-on object and complete definition from the label-update request above, changing only its SQL. Continue to omit the schedule fields as described above. Obtain permission for possible processing before PATCH; the false predicate and NO_REFRESH do not guarantee processing-free execution.

After one PATCH, independent runtime GET returned ACTIVE with the exact desired SQL, and separate standard Metadata retrieval confirmed that same SQL in the definition. NO_REFRESH, P90D, labels, owner identities, generated membership references and the PROFILE primary-field dependency binding were preserved. This establishes that narrow persisted definition edit, not audience membership or successful computation. It does not qualify the reverse change, another predicate/field, simultaneous SQL and label changes, arbitrary SQL, UI criteria, CREATE or cross-org replay. Read and compare the current definition before writing; this result does not prove that sending an identical PATCH is mutation-free.

A separate source-only existing-owner check retained the same runtime/metadata identity pair, and an unchanged comparison repeat retained that pair and the complete configuration. This is bounded stable-owner/readback evidence, not a guarantee that an identical API PATCH is mutation-free or that the definition can be deployed to another org unchanged.

Delete

Do not delete shared unified DMOs or membership tables as extra cleanup. Previously downloaded source files remain local.

  • CLI — Available: Owned definition-only deletion; runtime and generated-data cleanup are not promised.
  • API — Available: Delete the owned live segment and independently confirm runtime and metadata absence.
  • sf-plugin-data — Unknown: Not implemented in this guide; no workflow is supplied.

CLI

Delete an owned definition-only component

Use the integration-supplied empty manifest/package.xml and this exact manifest/destructiveChangesPost.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
  <types>
    <members>CustomerDefinition</members>
    <name>MarketSegmentDefinition</name>
  </types>
  <version>65.0</version>
</Package>
sf project deploy start --manifest manifest/package.xml --post-destructive-changes manifest/destructiveChangesPost.xml --target-org SOURCE_ALIAS --api-version 65.0 --wait 5 --json
sf org list metadata --metadata-type MarketSegmentDefinition --target-org SOURCE_ALIAS --api-version 65.0 --json

The completed response reports deleted: true. Require independent inventory absence of CustomerDefinition as well. This deletes the definition only; it does not promise runtime or generated-data cleanup. The downloaded XML remains on your computer.

API

Delete the live segment and check its definition

For the owned segment, save segment-delete.json:

{ "url": "/services/data/v65.0/ssot/segments/ActiveCustomers", "method": "DELETE", "body": { "mode": "raw", "raw": "" } }
sf api request rest --file segment-delete.json --target-org TARGET_ALIAS --json
sf api request rest '/services/data/v65.0/ssot/segments/ActiveCustomers' --method GET --target-org TARGET_ALIAS --json
sf org list metadata --metadata-type MarketSegmentDefinition --target-org TARGET_ALIAS --api-version 65.0 --json

DELETE can return HTTP 204 without a body. Confirm that GET returns HTTP 404 / ITEM_NOT_FOUND and the exact metadata member is absent:

[{ "errorCode": "ITEM_NOT_FOUND", "message": "<segment not found>" }]