# Tags

Maintain shared tags, organize records in batches, and verify current assignments.

Canonical HTML: https://developer.shelfcycle.com/guides/tags

Create and maintain shared business groupings, apply them across ShelfCycle records, and verify the exact tags carried by each record.

Public API v1.38 turns Tags into a complete organization workflow. A connected system can maintain the vocabulary, group records in batches, read one record's assignments, or retrieve every authorized record carrying an exact tag.

## Access

Use `tags:read` to browse tags, read a record's assignments, find tagged records, and receive related tags from Entity Resolution. Use `tags:write` to create or update tags and add or remove assignments.

The acting person also needs current Tags access. Assignment changes use that person's update access for the selected record type. `GET /me` reports:

- `effectiveCapabilities.tags.vocabulary` and `viewableEntityTypes` for reads.
- `effectiveCapabilities.writeReadiness.tags.create`, `update`, and `assignableEntityTypes` for changes.

## Supported record types

One tag can organize any combination of these record types:

| Value | Record |
| --- | --- |
| `customer` | Customer |
| `supplier` | Supplier |
| `product` | Product |
| `product_family` | Product family |
| `contact` | Customer or supplier contact |
| `opportunity` | Opportunity |
| `sales_order` | Sales order |
| `purchase_order` | Purchase order |
| `ship_to_address` | Customer ship-to address |
| `ship_from_address` | Supplier ship-from address |

## Browse the vocabulary

`GET /tags` returns each tag's stable `id`, full `label`, optional `description`, and `applicableEntityTypes`.

```bash
curl "$SHELFCYCLE_API_BASE_URL/tags?entityType=product&limit=25" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "X-ShelfCycle-Client: Product collection sync"
```

Use `entityType` to select tags that apply to one record type. Continue larger results with the returned `meta.nextCursor` and the same filters.

## Create a tag

Preview the tag with `dryRun=true`, then submit the same body without that query parameter.

```bash
curl "$SHELFCYCLE_API_BASE_URL/tags?dryRun=true" \
  -X POST \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Strategic Accounts",
    "description": "Accounts included in the strategic service program",
    "applicableEntityTypes": ["customer", "contact", "ship_to_address"]
  }'
```

The saved label is trimmed and lowercased, so exact-label reads and repeated creates resolve consistently. Omit `applicableEntityTypes` to make the tag available across all ten record types.

```json
{
  "data": {
    "id": "tag-id",
    "label": "strategic accounts",
    "description": "Accounts included in the strategic service program",
    "applicableEntityTypes": ["customer", "contact", "ship_to_address"],
    "changed": true
  }
}
```

## Update a tag

Use `PATCH /tags/{id}` to change the label, description, or applicable record types. A preview shows the proposed change without saving it.

```bash
curl "$SHELFCYCLE_API_BASE_URL/tags/tag-id?dryRun=true" \
  -X PATCH \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Customers and contacts included in the strategic service program",
    "applicableEntityTypes": ["customer", "contact"]
  }'
```

When the applicable record types become narrower, ShelfCycle removes assignments that no longer belong to the selected set and reports their types in `removedEntityTypes`.

## Assign a tag to records

`POST /tag-assignments` applies one tag to between 1 and 50 records of the same type. Preview the complete set first when your workflow uses a review step.

```bash
curl "$SHELFCYCLE_API_BASE_URL/tag-assignments?dryRun=true" \
  -X POST \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tagId": "tag-id",
    "entityType": "customer",
    "entityIds": ["customer-id-1", "customer-id-2"]
  }'
```

Remove `dryRun=true` to apply the assignment. Every requested record is evaluated together, and the response identifies each record and whether its assignment changed.

```json
{
  "data": {
    "tag": {
      "id": "tag-id",
      "label": "strategic accounts",
      "description": "Customers and contacts included in the strategic service program",
      "applicableEntityTypes": ["customer", "contact"],
      "changed": false
    },
    "entityType": "customer",
    "assignments": [
      {
        "entityClass": "customer",
        "id": "customer-id-1",
        "displayName": "Northstar Chemical",
        "externalId": "CRM-1842",
        "archived": false,
        "entityId": "customer-id-1",
        "changed": true
      }
    ]
  }
}
```

## Read one record's assignments

Use the record-specific assignment read to confirm its current tags:

```bash
curl "$SHELFCYCLE_API_BASE_URL/tag-assignments?entityType=customer&entityId=customer-id-1" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY"
```

```json
{
  "data": {
    "entityType": "customer",
    "entityId": "customer-id-1",
    "tags": [
      {
        "id": "tag-id",
        "label": "strategic accounts",
        "description": "Customers and contacts included in the strategic service program",
        "applicableEntityTypes": ["customer", "contact"],
        "changed": false
      }
    ]
  }
}
```

For contacts, use the customer- or supplier-contact ID. For ship-to addresses, use the customer address ID. For ship-from addresses, use the supplier ship-from ID. Other record types use the same ID as their public detail route.

## Remove assignments

Send the same assignment body with `DELETE /tag-assignments`. It supports the same preview and 1-to-50 record set as assignment creation.

```bash
curl "$SHELFCYCLE_API_BASE_URL/tag-assignments" \
  -X DELETE \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tagId": "tag-id",
    "entityType": "customer",
    "entityIds": ["customer-id-1", "customer-id-2"]
  }'
```

Tag vocabulary and assignment changes are safe to repeat with the same intended state. They do not use `Idempotency-Key` or `If-Match`; `changed` shows whether the request altered the current grouping.

## Find records carrying a tag

`GET /tagged-records` returns authorized records carrying one exact tag. Provide `entityType` and either the stable `tagId` or exact normalized `label`.

```bash
curl "$SHELFCYCLE_API_BASE_URL/tagged-records?tagId=tag-id&entityType=customer&nameQuery=northstar&limit=25" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY"
```

Use `nameQuery` to narrow the selected records. `includeArchived=true` includes archived records when the workflow intentionally manages those assignments. Continue with the returned cursor and the same filters.

## Pair Tags with Entity Resolution

Tags answer which authorized records carry one exact business grouping. Entity Resolution answers which single ID best matches familiar wording.

When both `search:read` and `tags:read` are available, Entity Resolution can include `relatedTags` for the requested class. Use that context to understand a candidate, then use `GET /tagged-records` for the complete authorized group or `GET /tag-assignments` for one record's current tags.
