Compare commits

...

3 Commits

Author SHA1 Message Date
mlieberD360
8eeef27e59
Merge 36f7a19206 into abe0d620a4 2026-07-09 09:55:21 -07:00
Hemant Singh Bisht
abe0d620a4
docs(W-23363336): add stability disclaimer to README (#307)
Add stability disclaimer to README

Skills are under active development and don't carry GA-level stability
guarantees. This note sets expectations for developers who fork or sync
the repo that skill names, structure, and availability may change without
notice.

Signed-off-by: Hemant Singh Bisht <hsinghbisht@salesforce.com>
2026-07-09 21:34:02 +05:30
Matthew Lieber
36f7a19206 feat: add segmenting-datacloud-api skill for REST API segment management
Adds a new skill covering the Data Cloud Connect REST API segments
endpoints via `sf api request rest`. Complements the existing
segmenting-datacloud skill (which uses the sf data360 plugin) with
full endpoint schemas, request/response examples, and error codes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-23 19:48:10 -07:00
4 changed files with 383 additions and 0 deletions

View File

@ -4,6 +4,8 @@ This repository provides a curated collection of Salesforce agent skills for bui
The skills are contributed by Salesforce and the broader community. Its optimized for Agentforce Vibes and can be used with any AI tool that supports skills.
> ⚠️ **Expect frequent changes.** The Salesforce skills library is evolving rapidly as we refine patterns and incorporate feedback. Skills may be renamed, restructured, or removed between releases — they do not follow the same stability guarantees as GA platform APIs. If youve forked or synced the repository, be prepared for upstream changes that may conflict with local modifications. This repository is always the source of truth.
## 🗂️ Structure
```

View File

@ -0,0 +1,5 @@
# Credits & Acknowledgments
Author: Matthew Lieber
This skill provides a REST API-first approach to Data Cloud segment management, complementing the `segmenting-datacloud` skill which uses the `sf data360` CLI plugin.

View File

@ -0,0 +1,35 @@
# segmenting-datacloud-api
Manage Salesforce Data Cloud segments via the Connect REST API (`sf api request rest`), without requiring the `sf data360` community plugin.
## Use this skill for
- creating, updating, and deleting segments via REST API
- publishing and deactivating segments
- getting segment details and member lists
- counting segment populations
- full endpoint schema reference (request/response bodies, query params, error codes)
## Example requests
```text
"Create a Dbt segment targeting individuals who purchased in the last 30 days"
"List all active waterfall segments in my org"
"Publish segment 1sgxx00000000PpAAI"
"Get the members of my High_Value_Customers segment"
"Delete the old test segment and recreate it on accounts"
```
## Common commands
```bash
sf api request rest "/services/data/v65.0/ssot/segments" -o myorg
sf api request rest "/services/data/v65.0/ssot/segments" -X POST -H "Content-Type:application/json" -b @/tmp/segment.json -o myorg
sf api request rest "/services/data/v65.0/ssot/segments/My_Segment/actions/publish" -X POST -H "Content-Type:application/json" -b '{}' -o myorg
sf api request rest "/services/data/v65.0/ssot/segments/My_Segment/members?limit=100" -o myorg
```
## References
- [SKILL.md](SKILL.md)
- [CREDITS.md](CREDITS.md)

View File

@ -0,0 +1,341 @@
---
name: segmenting-datacloud-api
description: "Manage Salesforce Data Cloud segments via the Connect REST API using `sf api request rest`. Use this skill when the user wants to create, list, get, update, delete, publish, deactivate, or count segments in Data Cloud — even if they say \"Data 360\", \"CDP segments\", or just \"segments\". Also use when the user asks about segment members or segment status. TRIGGER when: user manages segments via REST API, needs full endpoint schemas, or wants to bypass the sf data360 plugin. DO NOT TRIGGER when: user explicitly uses sf data360 CLI commands (use segmenting-datacloud), or the task is DMO/mapping/identity-resolution/activation work."
compatibility: "Requires an org with Data Cloud enabled and the sf CLI installed"
metadata:
version: "1.0"
---
# Data Cloud Segments — REST API via SF CLI
This skill manages Data Cloud segments through the Salesforce Connect API Segments endpoints, executed via `sf api request rest`.
## Authentication
All Segments endpoints require the **Core Salesforce token** (not the CDP token). The `sf api request rest` command handles authentication automatically using the target org.
Always include `-o <org-alias>` or rely on the default target org. The user's current default org is shown in the `sf api request rest --help` output.
## API Base Path
All endpoints live under `/services/data/v65.0/ssot/segments`. When calling `sf api request rest`, pass the full path starting with `/services/data/v65.0/`.
## Command Pattern
```bash
# GET request (no body)
sf api request rest "/services/data/v65.0/ssot/segments" -o <org>
# POST/PATCH with inline body
sf api request rest "/services/data/v65.0/ssot/segments" -X POST \
-H "Content-Type:application/json" \
-b '{"field":"value"}' \
-o <org>
# POST/PATCH with body from file
sf api request rest "/services/data/v65.0/ssot/segments" -X POST \
-H "Content-Type:application/json" \
-b @/tmp/segment-body.json \
-o <org>
# DELETE (requires empty JSON body due to sf CLI quirk)
sf api request rest "/services/data/v65.0/ssot/segments/MySegment" -X DELETE \
-H "Content-Type:application/json" \
-b '{}' \
-o <org>
```
**Important sf CLI quirks:**
- DELETE requests require `-H "Content-Type:application/json" -b '{}'` — the CLI errors without a body.
- POST endpoints that accept no body (publish, deactivate) also need `-H "Content-Type:application/json" -b '{}'`.
- For complex JSON bodies, prefer writing to a temp file first and using `-b @/tmp/file.json` to avoid shell quoting issues.
## Operations
### 1. List Segments
```bash
sf api request rest "/services/data/v65.0/ssot/segments?batchSize=20&offset=0" -o <org>
```
**Query parameters** (all optional):
| Parameter | Type | Description |
|-----------|------|-------------|
| `batchSize` | integer | 1-200, default 20 |
| `offset` | integer | Number of segments to skip |
| `orderby` | string | Sort field + direction, e.g. `Name ASC`, `MarketSegmentType DESC` |
| `dataspace` | string | Data space name (default data space if omitted) |
| `filters` | string | Up to 10 filters joined by AND. See Filters section below |
**Response:**
```json
{
"batchSize": 20,
"offset": 0,
"orderByExpression": "[Name asc]",
"segments": [ ... ],
"totalSize": 42
}
```
Each segment object in the array contains: `apiName`, `dataSpace`, `description`, `displayName`, `lastModifiedDate`, `marketSegmentDefinitionId`, `marketSegmentId`, `publishInterval`, `segmentOnApiName`, `segmentOnId`, `segmentStatus`, `segmentType`.
#### List Filters
Filterable fields: `Name` (displayName), `SegmentStatus`, `MarketSegmentType` (segmentType), `SegmentOn` (segmentOnApiName), `LastPublishedEndDateTime`.
Operators: `eq`, `contains`, `in` (comma-separated values), `!=`.
```
filters=Name contains MySegment AND SegmentStatus eq Active
filters=MarketSegmentType in Dbt,Waterfall AND SegmentOn eq individual
```
### 2. Create Segment
```bash
sf api request rest "/services/data/v65.0/ssot/segments" -X POST \
-H "Content-Type:application/json" \
-b @/tmp/create-segment.json \
-o <org>
```
**Required fields:**
| Field | Type | Description |
|-------|------|-------------|
| `description` | string | Segment description |
| `displayName` | string | Segment display name |
| `segmentOnApiName` | string | API name of the entity to segment on (e.g. `ssot__Individual__dlm`, `ssot__Account__dlm`) |
| `segmentType` | string | One of: `Dbt`, `Dynamic`, `Lookalike`, `Realtimez`, `Waterfall`. **Default to `Dbt` when the user does not specify a type.** |
**Optional fields:**
| Field | Type | Description |
|-------|------|-------------|
| `developerName` | string | API name for the segment (required for POST) |
| `additionalMetadata` | object | Map of additional metadata |
| `dataSpace` | string | Data space (use `dataspace` query param in v59+) |
| `publishSchedule` | string | Enum: `NoRefresh`, `One`, `Two`, `Four`, `Six`, `Twelve`, `TwentyFour` (hours) |
| `publishScheduleStartDateTime` | string | ISO datetime for schedule start — **must be in the future** |
| `publishScheduleEndDate` | string | ISO datetime for schedule end — despite the name, use full `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'` format |
| `includeDbt` | object | SQL-based segment definition for Dbt segments. Structure: `{"models": {"models": [{"name": "m1", "sql": "..."}]}}`. Note the nested `models.models` — the outer `models` is an object, the inner `models` is an array of model objects each with `name` and `sql`. The SQL SELECT must include both the primary key (`ssot__Id__c`) and the key qualifier (`KQ_Id__c`) of the segmentOn entity. See [Data Cloud SQL Reference](https://developer.salesforce.com/docs/data/data-cloud-query-guide/guide/dc-query-section.html) for query syntax |
| `lookalikeCriteria` | object | Lookalike criteria |
| `lookbackPeriod` | string | Lookback period |
**Example — create a Dbt segment (default type):**
```json
{
"description": "Customers with more than 5 purchases in the last 30 days",
"displayName": "Frequent Recent Buyers",
"developerName": "Frequent_Recent_Buyers",
"segmentOnApiName": "ssot__Individual__dlm",
"segmentType": "Dbt",
"additionalMetadata": {},
"includeDbt": {
"models": {
"models": [
{
"name": "m1",
"sql": "SELECT ssot__Individual__dlm.ssot__Id__c, ssot__Individual__dlm.KQ_Id__c FROM ssot__Individual__dlm WHERE ssot__Individual__dlm.ssot__Id__c IN (SELECT IndividualId__c FROM ssot__SalesOrder__dlm WHERE CreatedDate__c >= DATEADD(day, -30, CURRENT_DATE) GROUP BY IndividualId__c HAVING COUNT(*) > 5)"
}
]
}
},
"publishSchedule": "TwentyFour",
"publishScheduleStartDateTime": "2026-04-17T00:00:00.000Z",
"publishScheduleEndDate": "2026-05-17T23:59:59.000Z"
}
```
**Important notes on Dbt SQL:**
- The SQL SELECT must include both the primary key (`ssot__Id__c`) and the key qualifier (`KQ_Id__c`) of the segmentOn entity, or the API will return an `ENTITY_SAVE_ERROR`.
- The `includeDbt` structure uses nested `models.models` — the outer `models` is an object, the inner `models` is an array of model objects each with `name` (e.g. `"m1"`) and `sql`.
- The GET response flattens this to `includeDbt.models: [...]` (single-level array), but the POST body requires the nested `models.models` structure.
- The SQL must follow Data Cloud SQL syntax. See the [Data Cloud SQL Reference](https://developer.salesforce.com/docs/data/data-cloud-query-guide/guide/dc-query-section.html) for supported functions, operators, and DMO querying patterns.
**Response (200):** Returns the full segment object with `apiName`, `marketSegmentId`, `marketSegmentDefinitionId`, `segmentStatus` (typically `PROCESSING`), and all provided fields.
**Error responses:**
- 400: Invalid segment type, empty developerName/displayName, parse error
- 409: Segment already exists
### 3. Get Segment
```bash
sf api request rest "/services/data/v65.0/ssot/segments/<segmentApiNameOrId>" -o <org>
```
Pass either the segment API name (developerName) or the segment ID.
**Response (200):**
```json
{
"segments": [ { ...segment object... } ]
}
```
### 4. Update Segment
```bash
sf api request rest "/services/data/v65.0/ssot/segments/<segmentApiName>" -X PATCH \
-H "Content-Type:application/json" \
-b @/tmp/update-segment.json \
-o <org>
```
Uses the same body schema as Create, with these differences:
- `developerName` is **not supported** for PATCH (can't rename the API name)
- `segmentType` is **not supported** for PATCH (can't change type after creation)
- `additionalMetadata` is **not supported** for PATCH
Include only the fields you want to change. The required fields (`description`, `displayName`, `segmentOnApiName`) must still be present.
**Example — update description and publish schedule:**
```json
{
"description": "Updated description",
"displayName": "Recent High Value Customers",
"segmentOnApiName": "ssot__Individual__dlm",
"publishSchedule": "TwentyFour"
}
```
### 5. Delete Segment
```bash
sf api request rest "/services/data/v65.0/ssot/segments/<segmentApiName>" -X DELETE \
-H "Content-Type:application/json" \
-b '{}' \
-o <org>
```
Returns **204 No Content** on success (empty output).
### 6. Publish Segment
```bash
sf api request rest "/services/data/v65.0/ssot/segments/<segmentId>/actions/publish" -X POST \
-H "Content-Type:application/json" -b '{}' \
-o <org>
```
Uses the segment **ID** (not API name). No request body.
**Response (200):**
```json
{
"errors": [],
"jobId": "1f8f521f-0616-4bdf-a515-d95192475c95",
"partitionId": "1sgxx00000000Pp_6157146b-...",
"publishStatus": "PUBLISHING",
"segmentId": "1sgxx00000000PpAAI",
"success": true
}
```
### 7. Count Segment
```bash
sf api request rest "/services/data/v65.0/ssot/segments/<segmentApiName>/actions/count" -X POST \
-H "Content-Type:application/json" \
-b '{"preferApproxCount": true}' \
-o <org>
```
**Request body:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `preferApproxCount` | boolean | yes | `true` for approximate count (faster), `false` for exact |
**Response (200):**
```json
{
"errors": [],
"segmentId": "1sgxx00000000MbAAI",
"success": true
}
```
### 8. Deactivate Segment
By API name:
```bash
sf api request rest "/services/data/v65.0/ssot/segments/<segmentApiName>/actions/deactivate" -X POST \
-H "Content-Type:application/json" -b '{}' \
-o <org>
```
By segment ID:
```bash
sf api request rest "/services/data/v65.0/ssot/segments/<segmentId>/actions/deactivate" -X POST \
-H "Content-Type:application/json" -b '{}' \
-o <org>
```
**Response (200):**
```json
{
"errors": [],
"segmentApiName": "TestFilter",
"segmentId": "1sgxx00000000UfAAI",
"success": true
}
```
### 9. Get Segment Members
**The segment must be published before you can retrieve members.** If the segment has never been published, the API will return a 404 `ITEM_NOT_FOUND` error.
```bash
sf api request rest "/services/data/v65.0/ssot/segments/<segmentApiName>/members?limit=100&offset=0" -o <org>
```
**Query parameters** (all optional):
| Parameter | Type | Description |
|-----------|------|-------------|
| `fields` | string | Comma-separated: `Id__c`, `KQ_Id__c`, `Delta_Type__c`, `Segment_Id__c`, `Parent_Segment_Id__c`, `Snapshot_Type__c`, `Timestamp__c`, `Version_Stamp__c` |
| `filters` | string | e.g. `Delta_Type__c IN ('New','Existing') AND Timestamp__c IN 2026-04-09T14:12:41.111Z` |
| `limit` | integer | 1-1000, default 100 |
| `offset` | integer | Rows to skip |
| `orderBy` | string | e.g. `Timestamp__c DESC` |
**Response (200):**
```json
{
"data": [ ... ],
"endTime": "2025-04-11T15:16:10.000Z",
"filter": "Delta_Type__c in ( new , existing )",
"limit": 100,
"offSet": 0,
"orderBy": "Id__c asc",
"rowCount": 5,
"startTime": "2025-04-11T15:16:10.000Z",
"totalCount": 5
}
```
## Common Segment Entity API Names
| Entity | API Name |
|--------|----------|
| Individual | `ssot__Individual__dlm` |
| Account | `ssot__Account__dlm` |
When the user says "segment on individuals" or "segment on accounts", use these API names.
## Workflow: Create and Publish a Segment
A typical end-to-end flow:
1. **Create** the segment (POST) — returns `marketSegmentId`
2. **Get** the segment to confirm it was created and check status
3. **Publish** the segment using the `marketSegmentId` from step 1
4. **Check status** by getting the segment again — look at `segmentStatus`
5. **Count** the segment to trigger population count
6. **Get members** to see who's in the segment
## Troubleshooting
- **401 Unauthorized**: Run `sf org login web -a <alias>` to re-authenticate
- **404 Not Found**: Check the segment API name is correct (case-sensitive)
- **400 Bad Request**: Validate required fields are present; check `segmentType` enum values
- **409 Conflict**: Segment with that `developerName` already exists