← Files WixARCHIVED FILE
skills/wix-manage/references/cms/cms-data-items-crud.md
22.1 KB · Oct 8, 2026 · 12:02 UTC
---
name: "CMS Data Items CRUD"
description: "Add, query, update, and delete items in CMS collections, one at a time or in bulk. Also covers counting items, upserting with bulk save, truncating a collection, aggregating data with a pipeline, linking items through single- and multi-reference fields, and reading items with their referenced items expanded."
---
# CMS Data Items CRUD
> **Standard call shape (every curl below).** The `<AUTH>` placeholder is shorthand for `Authorization: Bearer <TOKEN>` only. Body-bearing requests also need `Content-Type: application/json`.
This recipe covers Create, Read, Update, Delete (CRUD) operations for Wix CMS data items, plus count, upsert, truncate, aggregate, and reference-field links.
## Prerequisites
1. Wix CMS enabled on the site (appDefId: `e593b0bd-b783-45b8-97c2-873d42aacaf4`)
2. Collections already created (see [CMS Schema Management](cms-schema-management.md))
3. API access with CMS permissions
## Required APIs
- **Data Items API**: [REST](https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/introduction)
---
## Know the Schema First
Before inserting or updating items, you need to know the collection's field names and types. If you don't already know the schema:
1. **Query existing items** - Fetch a few items to infer field names from the data
2. **Get collection schema** - Use `GET https://www.wixapis.com/wix-data/v2/collections/{dataCollectionId}` for full field definitions, **including `plugins`** — don't omit the `plugins` field when fetching or listing schemas
3. **List collections** - Use `GET https://www.wixapis.com/wix-data/v2/collections?fields=displayName,plugins` to see what collections exist (see [Schema Management](cms-schema-management.md))
It may be, that user refers to schema by its `displayName` rather than `id`, if collection is not found list all collections to find the right `id` (`dataCollectionId`) to use.
**Check for the Draft Items plugin.** If the collection's `plugins` include the Draft Items plugin, this collection gates items behind a draft/publish workflow. **Stop and load [CMS Draft & Publish Workflow](cms-publishing-flow.md)** before making any data changes, and follow its instructions instead of the plain CRUD flow below for that collection.
---
## Insert Data Item
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/items`
**Request Body**:
```json
{
"dataCollectionId": "Products",
"dataItem": {
"data": {
"title": "Wireless Headphones",
"price": 149.99,
"description": "Premium wireless headphones with noise cancellation",
"inStock": true,
"tags": ["wireless", "audio", "premium"]
}
}
}
```
**Response**:
```json
{
"dataItem": {
"id": "generated-item-id",
"dataCollectionId": "Products",
"data": {
"_id": "generated-item-id",
"title": "Wireless Headphones",
"price": 149.99,
"_createdDate": { "$date": "2024-01-15T10:00:00.000Z" },
"_updatedDate": { "$date": "2024-01-15T10:00:00.000Z" }
}
}
}
```
## Bulk Insert Items
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/bulk/items/insert`
**Request Body**:
```json
{
"dataCollectionId": "Products",
"dataItems": [
{
"data": {
"title": "Bluetooth Speaker",
"price": 79.99,
"inStock": true
}
},
{
"data": {
"title": "USB-C Cable",
"price": 12.99,
"inStock": true
}
},
{
"data": {
"title": "Laptop Stand",
"price": 49.99,
"inStock": false
}
}
],
"returnEntity": true
}
```
## Query Data Items
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/items/query`
**Basic Query**:
```json
{
"dataCollectionId": "Products",
"query": {
"filter": {
"inStock": true
},
"sort": [
{
"fieldName": "price",
"order": "ASC"
}
],
"paging": {
"limit": 50,
"offset": 0
}
}
}
```
**Advanced Query with Multiple Conditions**:
```json
{
"dataCollectionId": "Products",
"query": {
"filter": {
"$and": [
{ "inStock": true },
{ "price": { "$gte": 50, "$lte": 200 } }
]
}
}
}
```
**Text Search**:
```json
{
"dataCollectionId": "Products",
"query": {
"filter": {
"title": {
"$contains": "wireless"
}
}
}
}
```
## Get Single Item
**Endpoint**: `GET https://www.wixapis.com/wix-data/v2/items/{itemId}?dataCollectionId={collectionId}`
```bash
curl -X GET \
'https://www.wixapis.com/wix-data/v2/items/abc123?dataCollectionId=Products' \
-H 'Authorization: <AUTH>'
```
## Update Data Item
**Endpoint**: `PUT https://www.wixapis.com/wix-data/v2/items/{itemId}`
**Request Body**:
```json
{
"dataCollectionId": "Products",
"dataItem": {
"data": {
"title": "Wireless Headphones Pro",
"price": 199.99,
"description": "Updated premium wireless headphones",
"inStock": true
}
}
}
```
## Patch Data Item (Partial Update - Single Item)
**Endpoint**: `PATCH https://www.wixapis.com/wix-data/v2/items/{dataItemId}`
Unlike Update, this only modifies the specified fields — all other fields remain unchanged.
> **Note**: Only works on user-created collections. Wix app collections (e.g. Wix Stores Products) cannot be patched.
```json
{
"dataCollectionId": "Products",
"patch": {
"dataItemId": "item-guid",
"fieldModifications": [
{
"fieldPath": "price",
"action": "SET_FIELD",
"setFieldOptions": {
"value": 159.99
}
},
{
"fieldPath": "description",
"action": "REMOVE_FIELD"
},
{
"fieldPath": "viewCount",
"action": "INCREMENT_FIELD",
"incrementFieldOptions": {
"value": 1
}
}
]
}
}
```
## Bulk Update Items
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/bulk/items/update`
> There is no update-by-filter endpoint. To update the items matching a filter, query them first (see [Query Data Items](#query-data-items)), then send their ids to bulk update or bulk patch.
> **Important**: Use `id` (not `_id`) at the element level. The `data` object should NOT contain `_id`.
```json
{
"dataCollectionId": "Products",
"dataItems": [
{
"id": "item-guid-1",
"data": {
"price": 159.99,
"inStock": true
}
},
{
"id": "item-guid-2",
"data": {
"price": 89.99,
"inStock": false
}
}
]
}
```
> **Note**: This replaces the entire item. Include all fields you want to keep, not just the ones you're changing.
## Bulk Patch Items (Partial Update)
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/bulk/items/patch`
Unlike bulk update, this only modifies the specified fields - other fields remain unchanged. **Use this for partial updates.**
> **Important**: This endpoint uses `patches` array with `fieldModifications`, NOT `dataItems`. Do not confuse with bulk update.
```json
{
"dataCollectionId": "Products",
"patches": [
{
"dataItemId": "item-guid-1",
"fieldModifications": [
{
"fieldPath": "price",
"action": "SET_FIELD",
"setFieldOptions": {
"value": 159.99
}
}
]
},
{
"dataItemId": "item-guid-2",
"fieldModifications": [
{
"fieldPath": "price",
"action": "SET_FIELD",
"setFieldOptions": {
"value": 89.99
}
}
]
}
]
}
```
**Setting a single `REFERENCE` field** (the value is one item ID; for `MULTI_REFERENCE` the value shape differs, see the next example):
```json
{
"dataCollectionId": "events",
"patches": [
{
"dataItemId": "event-id",
"fieldModifications": [
{
"fieldPath": "venue",
"action": "SET_FIELD",
"setFieldOptions": {
"value": "venue-item-id"
}
}
]
}
]
}
```
**Setting a `MULTI_REFERENCE` field** (verified live): the value is an **array of item IDs**, and `SET_FIELD` **replaces the whole link set**. To add links without dropping the existing ones, use [Insert Multi-Reference Links](#insert-multi-reference-links) instead. A plain string, or `APPEND_TO_ARRAY`, fails per item with `WDE0303` inside a 200 bulk response — check `results[].itemMetadata`.
```json
{
"dataCollectionId": "Projects",
"patches": [
{
"dataItemId": "project-item-id",
"fieldModifications": [
{
"fieldPath": "team",
"action": "SET_FIELD",
"setFieldOptions": {
"value": ["alice-item-id", "bob-item-id"]
}
}
]
}
]
}
```
**Available actions**: `SET_FIELD`, `REMOVE_FIELD`, `INCREMENT_FIELD`, `APPEND_TO_ARRAY`, `REMOVE_FROM_ARRAY`
> **Common error**: If you get `WDE0080: patches must not be empty`, you sent `dataItems` instead of `patches`. Use the format above.
> **Recommended**: Use bulk patch instead of bulk update when you only need to change specific fields.
> **Reference fields**: a single `REFERENCE` field is set like any other value (`"venue": "venue-item-id"`, as above). `MULTI_REFERENCE` links are written only by a `SET_FIELD` patch (single or bulk) or by the reference endpoints in [Reference Fields](#reference-fields) below; insert, bulk insert, bulk save, PUT and bulk update all return 200 but silently drop multi-reference values (verified live) — read the item back after any of them.
## Delete Data Item
> Deletes are irreversible. Confirm with the user before calling either delete endpoint unless the request already names the items to remove.
**Endpoint**: `DELETE https://www.wixapis.com/wix-data/v2/items/{itemId}?dataCollectionId={collectionId}`
```bash
curl -X DELETE \
'https://www.wixapis.com/wix-data/v2/items/abc123?dataCollectionId=Products' \
-H 'Authorization: <AUTH>'
```
## Bulk Delete Items
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/bulk/items/remove`
```json
{
"dataCollectionId": "Products",
"dataItemIds": ["item-id-1", "item-id-2", "item-id-3"]
}
```
## Count Data Items
Count items in a collection, optionally with filters.
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/items/count`
**Count All Items**:
```json
{
"dataCollectionId": "Products"
}
```
**Response**:
```json
{
"totalCount": 42
}
```
**Count with Filter**:
```json
{
"dataCollectionId": "Products",
"filter": {
"$and": [
{ "inStock": true },
{ "price": { "$gte": 50 } }
]
}
}
```
Count returns only `totalCount`. When the user needs to know *which* items match, run Query Data Items with the same filter instead of, or after, counting.
## Bulk Save (Upsert)
Insert new items or update existing items in a single operation. This is useful for syncing data.
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/bulk/items/save`
```json
{
"dataCollectionId": "Products",
"dataItems": [
{
"id": "existing-item-id",
"data": {
"title": "Updated Product",
"price": 199.99,
"inStock": true
}
},
{
"data": {
"title": "New Product",
"price": 79.99,
"inStock": true
}
}
],
"returnEntity": true
}
```
| Scenario | Action |
|----------|--------|
| No `id` provided | INSERT - Creates new item with generated ID |
| `id` provided, doesn't exist | INSERT - Creates new item with provided ID |
| `id` provided, exists | UPDATE - Replaces existing item |
> **Warning**: When updating, the entire item is replaced. Include all fields you want to keep. Confirm with the user before saving over existing items.
## Truncate Collection
Remove all items from a collection.
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/items/truncate`
```json
{
"dataCollectionId": "TestCollection"
}
```
> **Warning**: This permanently deletes ALL items in the collection and cannot be undone. Ask the user to confirm before calling it.
## Aggregate Data
Perform calculations on collection data using a pipeline of sequential stages. The example shows one `group` stage; the full set of stages (`filter`, `group`, `sort`, `projection`, `unwindArray`, `skip`, `limit`) and accumulators is in the [Aggregate Pipeline Data Items reference](https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/aggregate-pipeline-data-items).
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/items/aggregate-pipeline`
**Count by Category**:
```json
{
"dataCollectionId": "Products",
"pipeline": {
"stages": [
{
"group": {
"groupIds": [
{"key": "category", "expression": {"fieldPath": "category"}}
],
"accumulators": [
{
"resultFieldName": "count",
"sum": {"expression": {"numeric": 1}}
}
]
}
}
]
}
}
```
## Operation Comparison
| Operation | Use Case | Behavior |
|-----------|----------|----------|
| **Bulk Insert** | Add new items only | Fails if ID exists |
| **Bulk Update** | Update existing items | Fails if ID doesn't exist, replaces entire item |
| **Bulk Save** | Upsert (insert or update) | Creates or updates based on ID |
| **Bulk Patch** | Partial update | Only modifies specified fields |
## Reference Fields
Reference fields link items across collections. A single `REFERENCE` field holds one item ID and is set like any other value in insert, update, or patch. A `MULTI_REFERENCE` field holds many links, and only two kinds of write create them: a `SET_FIELD` patch on the field (single or bulk), or the reference endpoints below, which add, replace, or remove links without touching the rest of the item. To add a reference field to a collection, see [Add a Reference Field](cms-schema-management.md#add-a-reference-field).
> **Warning (verified live)**: writing IDs into a `MULTI_REFERENCE` field through insert, bulk insert, bulk save, or PUT update returns **200 and silently drops that field's value** — no error is raised. Bulk update is a full-item replace like PUT and does the same: `success: true`, value dropped (verified live, bulk save on both its insert and update paths). Never trust the write response for reference links: read the item back with `includeReferencedItems` and confirm the linked items are there.
Linking flow, every time:
1. Resolve the referring item ID and the referenced item IDs (query by a field value; never guess IDs).
2. Write the links with the reference endpoints below, or with a `SET_FIELD` patch on the reference field. If the field already has links, `insert-references` adds without dropping them; `replace-references` and `SET_FIELD` discard the rest — confirm with the user before replacing unless the request says to.
3. **Read the referring item back** with Query Data Items and `includeReferencedItems: ["<field>"]` (or `includeReferences: [{ "field": "<field>" }]`), and confirm the linked items are present. The write's 200 is not proof; only the read-back is.
### Insert Multi-Reference Links
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/bulk/items/insert-references`
```json
{
"dataCollectionId": "Products",
"dataItemReferences": [
{
"referringItemId": "product-item-id",
"referringItemFieldName": "tags",
"referencedItemId": "tag-1-item-id"
},
{
"referringItemId": "product-item-id",
"referringItemFieldName": "tags",
"referencedItemId": "tag-2-item-id"
}
],
"returnEntity": true
}
```
### Replace All References
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/items/replace-references`
```json
{
"dataCollectionId": "Products",
"referringItemId": "product-item-id",
"referringItemFieldName": "tags",
"newReferencedItemIds": ["new-tag-1-id", "new-tag-2-id", "new-tag-3-id"]
}
```
> **Note**: To remove all references, pass an empty array for `newReferencedItemIds`.
### Remove References (Bulk)
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/bulk/items/remove-references`
```json
{
"dataCollectionId": "Products",
"dataItemReferences": [
{
"referringItemId": "product-id-1",
"referringItemFieldName": "tags",
"referencedItemId": "tag-to-remove-id"
}
]
}
```
### Query with Referenced Items Expanded
**Endpoint**: `POST https://www.wixapis.com/wix-data/v2/items/query`
```json
{
"dataCollectionId": "Products",
"query": {
"filter": {
"inStock": true
}
},
"includeReferencedItems": ["category", "tags"]
}
```
The method article documents the same expansion as `"includeReferences": [{ "field": "category" }, { "field": "tags", "limit": 50 }]`; both forms work (verified live). Either way the expanded value is an **array of item objects** (with `_id`, `name`, …), not an array of IDs. Without one of these properties a `MULTI_REFERENCE` field is absent from the returned item, and a single `REFERENCE` field is returned as the item ID string (it is stored on the item; verified live).
### Reference Query Operators
| Operator | Description | Example |
|----------|-------------|---------|
| `$eq` | Exact match (single reference) | `{ "category": "id" }` |
| `$hasSome` | Has at least one of | `{ "tags": { "$hasSome": ["id1", "id2"] } }` |
| `$hasAll` | Has all of | `{ "tags": { "$hasAll": ["id1", "id2"] } }` |
## Field Types Reference
| Type | Description | Example Value |
|------|-------------|---------------|
| `TEXT` | String | `"Hello World"` |
| `NUMBER` | Numeric | `99.99` |
| `BOOLEAN` | True/false | `true` |
| `DATE` | Date only | `"2024-01-15"` |
| `DATETIME` | Date and time | `{ "$date": "2024-01-15T10:00:00.000Z" }` |
| `IMAGE` | Image reference (HTTP url or wix:image://v1/{mediaId}/{friendlyName}) | `"wix:image://v1/3f72369f2219e2ee853e9e3df0217ce1.jpg/Colorful%20Business%20Cards.jpg"` |
| `VIDEO` | Video reference (HTTP url or wix:video://v1/{mediaId}/{friendlyName}) | `"wix:video://v1/11062b_484182533ede4b9a81329daf20238867/Sketching%20Design%20Concepts#posterUri=11062b_484182533ede4b9a81329daf20238867f000.jpg&posterWidth=1920&posterHeight=1080"` |
| `DOCUMENT` | Document reference (HTTP url or wix:document://v1/{mediaId}) | `"wix:document://v1/..."` |
| `MEDIA_IMAGE` | Wix Media Image | `{ "id": "<mediaId>", "url": "http://...", "height": 640, "width": 480, "altText": "Picture" }` |
| `MEDIA_VECTOR_ART` | Wix Media Vector Art | `{ "uri": "wix:vector://v1/...", "viewBox": "0 0 100 100", "contentType": "shape", "svgContent": "<svg>...</svg>" }` |
| `URL` | Web URL | `"https://example.com"` |
| `RICH_TEXT` | HTML content | `"<p>Rich text</p>"` |
| `EMAIL` | Email | `"example@wix.com"` |
| `RICH_CONTENT` | Structured content | Complex object |
| `ADDRESS` | Address object | Address fields |
| `ARRAY_STRING` | Array of strings | `["tag1", "tag2"]` |
| `OBJECT` | JSON object | `{"key": "value"}` |
| `REFERENCE` | Single reference | Item ID string |
| `MULTI_REFERENCE` | Multiple references. Write with a `SET_FIELD` patch (array of item IDs, replaces the set) or the *reference* endpoints (add / replace / remove); expand in queries with `includeReferencedItems` or `includeReferences` | Write: array of item IDs (`SET_FIELD`). Read: absent unless expanded with `includeReferencedItems` / `includeReferences`, then an array of item objects |
---
## Query Operators
| Operator | Description | Example |
|----------|-------------|---------|
| `$eq` | Equal | `{ "status": { "$eq": "active" } }` |
| `$ne` | Not equal | `{ "status": { "$ne": "archived" } }` |
| `$gt` | Greater than | `{ "price": { "$gt": 100 } }` |
| `$gte` | Greater or equal | `{ "price": { "$gte": 100 } }` |
| `$lt` | Less than | `{ "price": { "$lt": 50 } }` |
| `$lte` | Less or equal | `{ "price": { "$lte": 50 } }` |
| `$in` | In array | `{ "status": { "$in": ["active", "pending"] } }` |
| `$contains` | Contains string | `{ "title": { "$contains": "pro" } }` |
| `$startsWith` | Starts with | `{ "title": { "$startsWith": "Wireless" } }` |
| `$and` | All conditions | `{ "$and": [{...}, {...}] }` |
| `$or` | Any condition | `{ "$or": [{...}, {...}] }` |
---
## Pagination
### Offset-Based (Simple)
```json
{
"query": {
"paging": {
"limit": 50,
"offset": 100
}
}
}
```
### Cursor-Based (Large Datasets)
```json
{
"query": {
"cursorPaging": {
"limit": 50,
"cursor": "cursor-from-previous-response"
}
}
}
```
---
## Error Handling
### Recovering from WDE0110
`WDE0110` means the Wix CMS (Wix Data) app is not installed on the site. If the user has
explicitly asked to install it, install the app before retrying the data-item request:
```http
POST https://www.wixapis.com/apps-installer-service/v1/app-instance/install
```
```json
{
"tenant": {
"tenantType": "SITE",
"id": "<SITE_ID>"
},
"appInstance": {
"appDefId": "e593b0bd-b783-45b8-97c2-873d42aacaf4"
}
}
```
After the installation succeeds, retry the original `POST https://www.wixapis.com/wix-data/v2/items` request. If the
user only asks what the error means or how to fix it, explain this installation step and ask for
confirmation before performing the install.
| Error | Cause | Solution |
|-------|-------|----------|
| `COLLECTION_NOT_FOUND` | Invalid collection ID | Check collection exists |
| `ITEM_NOT_FOUND` | Invalid item ID | Verify item exists |
| `VALIDATION_ERROR` | Invalid field value | Check field types |
| `DUPLICATE_KEY` | Duplicate unique field | Use unique values |
| `PERMISSION_DENIED` | Insufficient access | Check API permissions |
| `WDE0007` | Bulk update: wrong ID field name | Use `id` not `_id` at element level |
| `WDE0080` | Validation failed (multiple causes) | Bulk update: don't include `_id` in `data`; Bulk patch: use `patches` array not `dataItems` |
| `WDE0303` | Multi-reference field value is not an array of item IDs (a single ID string, or `APPEND_TO_ARRAY`); reported per item inside a 200 bulk response | Send `"value": ["id1", "id2"]` with `SET_FIELD`, or use the reference endpoints |
| `WDE0110` | Wix CMS (Wix Data) application is not installed | Install application with appDefId: `e593b0bd-b783-45b8-97c2-873d42aacaf4` |
---
## Related Documentation
- [Data Items API Reference](https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/introduction)
- [CMS Schema Management](cms-schema-management.md) - Creating and modifying collections
- [CMS Draft & Publish Workflow](cms-publishing-flow.md) - Collections gated behind a draft/publish (Draft Items plugin) workflow
SHA-256: 52facc42d48f9dd6b3d0c39b43f03fe3ad0216b2c2b43c5fd19172508fbadfa5