Skip to content

Commit aefb50d

Browse files
salacosteclaude
andcommitted
docs: add comprehensive createCardsList() guide and fix common validation errors
Added new guide to prevent user confusion with createCardsList() pagination. ## Added - **New Guide**: Working with Product Cards (`docs/guides/working-with-product-cards.md`) - Complete createCardsList() usage with 8+ code examples - First request vs pagination explained in detail - Common Mistakes section (empty cursor fields, missing settings wrapper) - Comprehensive troubleshooting for validation errors - All filtering options documented with examples - Best practices for rate limiting and error handling ## Changed - **Troubleshooting Guide**: Added Issue 13a for createCardsList() validation errors - **Method Reference**: Updated Products table with correct createCardsList() method - **Product Catalog Examples**: Fixed all code to use correct API methods - **Guides Index**: Added Working with Product Cards to navigation ## Fixed - Removed references to non-existent getAllProducts() and listProducts() helpers - Corrected pagination examples to use proper cursor structure - Documented that empty updatedAt/nmID cause validation failures - Clarified settings wrapper requirement in all examples Resolves common user issue where empty cursor fields cause "Validation failed" errors. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent e9b9705 commit aefb50d

File tree

5 files changed

+1115
-30
lines changed

5 files changed

+1115
-30
lines changed

CHANGELOG.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,46 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Added
11+
12+
#### Documentation
13+
- **NEW: Working with Product Cards Guide** (`docs/guides/working-with-product-cards.md`)
14+
- Complete guide to `createCardsList()` method with cursor pagination
15+
- First request vs pagination requests explained with examples
16+
- All filtering options documented (photos, brands, tags, categories)
17+
- Common mistakes section preventing validation errors
18+
- Comprehensive troubleshooting with real-world solutions
19+
- Complete pagination example with rate limiting
20+
- Response structure documentation with TypeScript types
21+
- 8 code examples covering all use cases
22+
- **Troubleshooting Updates** (`docs/guides/troubleshooting.md`)
23+
- New Issue 13a: `createCardsList()` validation errors (most common issue)
24+
- Updated Method Reference table with correct `createCardsList()` method
25+
- Quick reference links to detailed product cards guide
26+
- **Example Updates** (`docs/examples/use-cases/product-catalog.md`)
27+
- Fixed all examples to use correct `createCardsList()` API
28+
- Removed references to non-existent `getAllProducts()` helper
29+
- Added proper pagination implementation in all examples
30+
- Cross-reference to detailed product cards guide
31+
32+
### Changed
33+
34+
#### Documentation Structure
35+
- **Guides Index** - Added "Working with Product Cards" to Product Management section
36+
- **Method Reference** - Corrected product listing method name from `listProducts()`/`getAllProducts()` to `createCardsList()`
37+
38+
### Fixed
39+
40+
#### User Confusion Prevention
41+
- **Common Validation Error**: Documented that empty `updatedAt: ""` and `nmID: 0` cause validation failures
42+
- **Cursor Structure**: Clarified first request (only `limit`) vs pagination (with `updatedAt`/`nmID`)
43+
- **Settings Wrapper**: Highlighted requirement to wrap all parameters in `settings` object
44+
- **Limit Maximum**: Documented 1000 max limit with 100 recommended
45+
46+
---
47+
848
## [2.4.0] - 2025-12-25
949

1050
### ⚠️ CRITICAL - Wildberries API Deprecation Notice

docs/examples/use-cases/product-catalog.md

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Synchronize your product catalog with Wildberries.
66

77
This use case demonstrates how to manage your product catalog on Wildberries, including listing products, updating information, and syncing with external systems.
88

9+
> **📖 For detailed guide on fetching product cards, see [Working with Product Cards Guide](/guides/working-with-product-cards)**
10+
911
## Get All Products
1012

1113
```typescript
@@ -15,15 +17,38 @@ const sdk = new WildberriesSDK({
1517
apiKey: process.env.WB_API_KEY!
1618
});
1719

18-
// Get all products using the helper method (handles pagination automatically)
20+
// Get all products with pagination
1921
async function getAllProducts() {
20-
const products = await sdk.products.getAllProducts({
21-
locale: 'ru',
22-
withPhoto: 1 // Include photo URLs
23-
});
22+
const allCards = [];
23+
let cursor: any = { limit: 100 };
24+
25+
while (true) {
26+
const response = await sdk.products.createCardsList({
27+
settings: {
28+
filter: { withPhoto: -1 }, // All cards
29+
cursor
30+
}
31+
}, { locale: 'ru' });
32+
33+
if (response.cards) {
34+
allCards.push(...response.cards);
35+
}
36+
37+
if ((response.cards?.length ?? 0) < 100 || !response.cursor?.updatedAt) {
38+
break;
39+
}
2440

25-
console.log(`Total products: ${products.length}`);
26-
return products;
41+
cursor = {
42+
limit: 100,
43+
updatedAt: response.cursor.updatedAt,
44+
nmID: response.cursor.nmID
45+
};
46+
47+
await new Promise(resolve => setTimeout(resolve, 650));
48+
}
49+
50+
console.log(`Total products: ${allCards.length}`);
51+
return allCards;
2752
}
2853

2954
const products = await getAllProducts();
@@ -32,21 +57,19 @@ const products = await getAllProducts();
3257
## Get Products with Filtering
3358

3459
```typescript
35-
// Get products with specific settings
60+
// Get products with specific filters
3661
async function getProductsFiltered() {
37-
const response = await sdk.products.listProducts({
38-
limit: 100,
39-
offset: 0,
40-
locale: 'ru',
41-
withPhoto: 1
42-
});
43-
44-
// Filter by specific criteria
45-
const activeProducts = response.cards?.filter(
46-
card => card.nmID && !card.trash
47-
);
62+
const response = await sdk.products.createCardsList({
63+
settings: {
64+
filter: {
65+
withPhoto: 1, // Only with photos
66+
brands: ['MyBrand']
67+
},
68+
cursor: { limit: 100 }
69+
}
70+
}, { locale: 'ru' });
4871

49-
return activeProducts;
72+
return response.cards ?? [];
5073
}
5174
```
5275

@@ -117,8 +140,8 @@ interface ExternalProduct {
117140
}
118141

119142
async function syncFromExternalSystem(externalProducts: ExternalProduct[]) {
120-
// 1. Get existing WB products
121-
const wbProducts = await sdk.products.getAllProducts({ locale: 'ru' });
143+
// 1. Get existing WB products (using getAllProducts helper from above)
144+
const wbProducts = await getAllProducts();
122145

123146
// 2. Create lookup map
124147
const wbProductMap = new Map(
@@ -176,11 +199,8 @@ interface CatalogExport {
176199
}
177200

178201
async function exportCatalog(): Promise<CatalogExport[]> {
179-
// Get all products
180-
const products = await sdk.products.getAllProducts({
181-
locale: 'ru',
182-
withPhoto: 1
183-
});
202+
// Get all products (using getAllProducts helper from above)
203+
const products = await getAllProducts();
184204

185205
// Get stock levels
186206
const stocks = await sdk.reports.getStocks(
@@ -219,7 +239,8 @@ writeFileSync('catalog.json', JSON.stringify(catalog, null, 2));
219239

220240
```typescript
221241
async function checkProductHealth() {
222-
const products = await sdk.products.getAllProducts({ locale: 'ru' });
242+
// Get all products (using getAllProducts helper from above)
243+
const products = await getAllProducts();
223244
const stocks = await sdk.reports.getStocks(
224245
new Date().toISOString().split('T')[0]
225246
);
@@ -263,6 +284,7 @@ async function checkProductHealth() {
263284

264285
## Related Materials
265286

287+
- **[Working with Product Cards Guide](/guides/working-with-product-cards)** - Complete guide to `createCardsList()` with troubleshooting
266288
- [API Reference: ProductsModule](/api/classes/ProductsModule)
267289
- [Pricing Updates](pricing-updates.md)
268290
- [Stock Management](stock-management.md)

docs/guides/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ In-depth guides for production deployment and advanced SDK usage.
2020
## Module Guides
2121

2222
### Product Management
23+
- **[Working with Product Cards](/guides/working-with-product-cards)** - Complete guide to fetching, filtering, and paginating product cards
2324
- **[Product Card Merging & Analytics](/guides/product-card-merging)** - Merged cards (склейки), advertising traffic distribution, and cross-variant analytics
2425

2526
### Advertising & Marketing

docs/guides/troubleshooting.md

Lines changed: 132 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Quick solutions for common Wildberries SDK issues. This guide helps you diagnose
4141
- [Rate limit exceeded](#issue-6-429-too-many-requests)
4242
- [Connection timeout](#issue-11-etimedout)
4343
- [Validation error](#issue-13-validation-error)
44+
- [**createCardsList() validation errors**](#issue-13a-createcardslist-validation-errors--common-issue)**NEW**
4445
- [Module not found](#issue-17-module-not-found)
4546

4647
---
@@ -53,10 +54,11 @@ Quick lookup table for common operations and their actual SDK methods. Copy thes
5354

5455
### Products & Catalog
5556

57+
> **📖 For detailed guide on product cards, see [Working with Product Cards](/guides/working-with-product-cards)**
58+
5659
| Operation | Actual SDK Method | Notes |
5760
|-----------|-------------------|-------|
58-
| List all products | `sdk.products.listProducts(filters?)` | Returns first page only (up to 100 products). Use `getAllProducts()` for automatic pagination |
59-
| Get all products | `sdk.products.getAllProducts(filters?, options?)` | Automatically paginates through all products. Use for large catalogs (10,000+ products) |
61+
| List product cards | `sdk.products.createCardsList({ settings })` | **Main method** - Returns cards with cursor pagination. See [detailed guide](/guides/working-with-product-cards) |
6062
| Create new product | `sdk.products.createProduct(data)` | Single product creation |
6163
| Update product | `sdk.products.updateProduct(data[])` | Accepts array of updates |
6264
| Delete product | `sdk.products.deleteProduct(nmIDs[])` | Permanently removes products |
@@ -1135,6 +1137,134 @@ Field: categoryId - Must be a valid category ID
11351137

11361138
---
11371139

1140+
### Issue 13a: createCardsList() Validation Errors ⚠️ COMMON ISSUE
1141+
1142+
> **📖 For complete troubleshooting guide, see [Working with Product Cards](/guides/working-with-product-cards#troubleshooting)**
1143+
1144+
**Error Message:**
1145+
```
1146+
ValidationError: Validation failed
1147+
```
1148+
1149+
**Cause:** Incorrect request structure for `createCardsList()` method.
1150+
1151+
**What Went Wrong:**
1152+
1153+
This is **the most common mistake** with `createCardsList()`:
1154+
1155+
**Mistake 1: Empty cursor fields in first request**
1156+
```typescript
1157+
// ❌ WRONG - Causes validation error
1158+
await sdk.products.createCardsList({
1159+
settings: {
1160+
cursor: {
1161+
limit: 100,
1162+
updatedAt: "", // Empty string causes validation error!
1163+
nmID: 0 // Zero causes validation error!
1164+
}
1165+
}
1166+
});
1167+
```
1168+
1169+
**Mistake 2: Missing `settings` wrapper**
1170+
```typescript
1171+
// ❌ WRONG - Missing settings wrapper
1172+
await sdk.products.createCardsList({
1173+
cursor: { limit: 100 },
1174+
filter: { withPhoto: -1 }
1175+
});
1176+
```
1177+
1178+
**Mistake 3: Limit exceeds maximum**
1179+
```typescript
1180+
// ❌ WRONG - Max limit is 1000
1181+
await sdk.products.createCardsList({
1182+
settings: {
1183+
cursor: { limit: 5000 }
1184+
}
1185+
});
1186+
```
1187+
1188+
**Solution:**
1189+
1190+
**For FIRST request:**
1191+
```typescript
1192+
// ✅ CORRECT - Only include limit
1193+
const response = await sdk.products.createCardsList({
1194+
settings: {
1195+
cursor: {
1196+
limit: 100 // ONLY limit, omit updatedAt and nmID
1197+
},
1198+
filter: {
1199+
withPhoto: -1 // -1 = all cards
1200+
}
1201+
}
1202+
});
1203+
```
1204+
1205+
**For PAGINATION requests:**
1206+
```typescript
1207+
// ✅ CORRECT - Copy cursor from previous response
1208+
const nextResponse = await sdk.products.createCardsList({
1209+
settings: {
1210+
cursor: {
1211+
limit: 100,
1212+
updatedAt: response.cursor.updatedAt, // From previous response
1213+
nmID: response.cursor.nmID // From previous response
1214+
},
1215+
filter: {
1216+
withPhoto: -1
1217+
}
1218+
}
1219+
});
1220+
```
1221+
1222+
**Complete Working Example:**
1223+
```typescript
1224+
async function getAllCards() {
1225+
const allCards = [];
1226+
let cursor: any = { limit: 100 }; // Start with only limit
1227+
1228+
while (true) {
1229+
const response = await sdk.products.createCardsList({
1230+
settings: {
1231+
filter: { withPhoto: -1 },
1232+
cursor
1233+
}
1234+
});
1235+
1236+
if (response.cards) {
1237+
allCards.push(...response.cards);
1238+
}
1239+
1240+
// Check if more data available
1241+
if ((response.cards?.length ?? 0) < 100 || !response.cursor?.updatedAt) {
1242+
break;
1243+
}
1244+
1245+
// Update cursor for next request
1246+
cursor = {
1247+
limit: 100,
1248+
updatedAt: response.cursor.updatedAt,
1249+
nmID: response.cursor.nmID
1250+
};
1251+
1252+
await new Promise(resolve => setTimeout(resolve, 650));
1253+
}
1254+
1255+
return allCards;
1256+
}
1257+
```
1258+
1259+
**How to Prevent:**
1260+
- ✅ First request: Only `limit` in cursor
1261+
- ✅ Pagination: Copy `updatedAt` and `nmID` from response
1262+
- ✅ Always wrap in `settings` object
1263+
- ✅ Use `limit: 100` (max 1000)
1264+
- ✅ See [Complete Guide](/guides/working-with-product-cards) for all details
1265+
1266+
---
1267+
11381268
### Issue 14: Missing Required Field
11391269

11401270
**Error Message:**

0 commit comments

Comments
 (0)