Last updated: October 28, 2026, 19:23 (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.

Data Model Object (DMO) — CustomObject with the __dlm suffix.

A DMO is the model your data is mapped into, such as a customer or order. It uses the suffix __dlm. Salesforce CLI treats its definition as a CustomObject, with a separate XML file for each field.

Supplied workflows for Data Model Object (DMO)
RetrieveCreateUpdateDelete
Yes
CLI
?
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: Retrieve the object XML and individual field definitions, not the complete data setup.
  • API — Unknown: No API retrieval workflow is supplied here.
  • sf-plugin-data — Unknown: Not implemented in this guide; no workflow is supplied.

CLI

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

Look for these files:

  • force-app/main/default/objects/Customer__dlm/Customer__dlm.object-meta.xml
  • force-app/main/default/objects/Customer__dlm/fields/Id__c.field-meta.xml
  • Further files in fields/ for the other fields, including system fields and lookups.

The object file contains information such as the label and dataspace:

<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
  <label>Customer</label>
  <mktDataModelAttributes>
    <creationType>Custom</creationType>
    <dataSpaceName>default</dataSpaceName>
    <!-- Other retrieved attributes omitted. -->
  </mktDataModelAttributes>
</CustomObject>

Keep the field files too. In particular, preserve the primary-key and key-qualifier attributes rather than trying to reconstruct them from field names. This export is not a complete set of mappings, relationships or ingestion settings. An isEnabled flag alone does not tell you whether processing is active.

Create

Creating a DMO by deploying its XML has not been verified. Downloading an object does not mean you can recreate it that way.

A native API 65.0 POST /services/data/v65.0/ssot/data-model-objects returned HTTP 201 for a newly owned custom DMO in category Other, default dataspace, with a Text primary key, two nonprimary Text fields and four generated system/key-qualifier fields. This was an empty object without mappings or relationships. That bounded creation supported the additive update test below; it is not a general XML-deployment or arbitrary-schema creation recipe.

  • CLI — Unknown: DMO creation by XML deployment has not been verified.
  • API — Unknown: A bounded native API creation was observed, but no creation recipe is supplied.
  • sf-plugin-data — Unknown: Not implemented in this guide; no workflow is supplied.

Update

General DMO XML updates, including schema changes through Metadata API, have not been verified either.

  • CLI — Unknown: General DMO XML and Metadata API schema updates have not been verified.
  • API — Available: Only the addition-only nonprimary Text-field PATCH on the qualified owned empty DMO.
  • sf-plugin-data — Unknown: Not implemented in this guide; no workflow is supplied.

API

A separate native API 65.0 fields-only PATCH did add one nonprimary Text field to the newly owned, empty custom Other/default DMO described above. It was not mapped or related, and its existing fields were not dynamic lookups.

Save this addition-only body as dmo-add-field.json beside force-app, omitting all existing fields and object properties:

{"fields":[{"name":"AddedValue__c","label":"Added value","dataType":"Text"}]}

Use the exact API name returned for your owned DMO, not a guessed name:

sf api request rest /services/data/v65.0/ssot/data-model-objects/OWNED_DMO_API_NAME --target-org SOURCE_ALIAS --method PATCH --include --body @dmo-add-field.json
sf api request rest /services/data/v65.0/ssot/data-model-objects/OWNED_DMO_API_NAME --target-org SOURCE_ALIAS --method GET --include

The PATCH returned HTTP 200, but its response still showed the old seven fields. Do not treat the mutation echo as confirmation or replay the write. Independent runtime GET observed eight fields about 28 seconds later and retained them at about 70 seconds; separate API 65 Metadata CustomObject reads independently confirmed the addition in both rounds. These timings are observations, not a settlement guarantee.

Removing only AddedValue__c from each readback made the entire runtime object and entire Metadata object equal to baseline, comparing fields by exact identity and without excluding unfamiliar properties. All old field properties, primary-key and key-qualifier settings, system fields, object properties and the empty relationship inventory were preserved. The new Metadata field was Text, length 60, required=false, isDynamicLookup=false, with no primary designation.

This qualifies only that addition-only, nonprimary Text variant. Do not add primary/dynamic flags, descriptions, category changes or mixed edits to this request. Populated, mapped or related DMOs, other types/categories/dataspaces/API versions, arbitrary schema changes and universal nullable/default semantics remain unverified. The test object was retained; no deletion or processing/ingestion claim follows from this update.

An existing DMO needs a separate, authoritative eligibility check before applying this empty-object-only result. Disabled or unmapped flags, ownership and schema presence do not prove zero records. A native SQL query against an existing DMO can return SQLSTATE 42P01 (table does not exist), even when runtime and Metadata reads find its configuration; an explicit default-data-space query can fail the same way. That error is not an empty result or proof that no record store exists. No authoritative zero-record or record-store-absence check was established for that nonqueryable variant, so do not use this example as a general update recipe for existing objects. Even a successful fresh zero-row query would be a point-in-time observation, not an atomic guarantee against concurrent ingestion before PATCH.

Delete

The deletion route is limited to an empty custom DMO that you own, after a fresh dependency check. It can also delete the DMO’s sole owned mapping. It does not delete the DLO, and it is not a safe recipe for arbitrary business objects or shared dependencies.

  • CLI — Available: Only an owned empty custom DMO after fresh dependency checks; the DLO remains.
  • API — Unknown: No API deletion workflow is supplied here.
  • sf-plugin-data — Unknown: Not implemented in this guide; no workflow is supplied.

CLI

The integration supplies an empty package.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
  <version>65.0</version>
</Package>

Its destructiveChangesPost.xml selects only the intended DMO:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
  <types>
    <members>Customer__dlm</members>
    <name>CustomObject</name>
  </types>
  <version>65.0</version>
</Package>

With those files and checks in place:

sf project deploy start --manifest package.xml --post-destructive-changes destructiveChangesPost.xml --target-org TARGET_ALIAS --api-version 65.0 --test-level NoTestRun --wait 5 --json

A completed deletion can look like this:

{ "status": 0, "result": { "done": true, "success": true, "status": "Succeeded", "details": { "componentSuccesses": [{ "componentType": "CustomObject", "fullName": "Customer__dlm", "deleted": true, "success": true }] } } }

Check afterward that the exact DMO and its owned mapping are gone and the DLO remains. Downstream insights, segments, identity resolution and activations can block deletion; no single dependency list is guaranteed to show everything. Local object, field and mapping XML remain. sf project delete source is not an interchangeable verified alternative and would also remove local files.