@minipim/sdk 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -1
- package/dist/index.d.cts +11 -6
- package/dist/index.d.ts +11 -6
- package/dist/openapi.d.cts +169 -14
- package/dist/openapi.d.ts +169 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -126,7 +126,11 @@ for await (const p of paginate<Product>(pim, '/v1/products', { query: { status:
|
|
|
126
126
|
const all = await collectAll<Product>(pim, '/v1/products');
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
-
`paginate` manages `limit`/`offset`, honors the server's `hasMore`, and defaults to the 200-row max page size (override with `pageSize`).
|
|
129
|
+
`paginate` manages `limit`/`offset`, honors the server's `hasMore`, and defaults to the 200-row max page size (override with `pageSize`).
|
|
130
|
+
|
|
131
|
+
`withTotal: true` is supported by **`/v1/products` only** — it adds one `COUNT(*)`, so leave it off on hot reads. Other list endpoints never return `total`, and as of v0.7.0 their types say so rather than declaring a field that was always `undefined`.
|
|
132
|
+
|
|
133
|
+
Against API **0.14.0 and newer, `hasMore` is present and exact on every list endpoint** — the server reads one row past the page, so a final page that happens to be exactly full reports `false` instead of sending you after an empty one. Older deployments omitted `hasMore` everywhere except `/v1/products`; `paginate` keeps a short-page fallback for those, which is the whole reason not to hand-roll the loop.
|
|
130
134
|
|
|
131
135
|
Endpoints that return a **plain array** instead of the envelope (`/v1/categories` without `?limit=`, `/v1/attributes`, `/v1/products/{id}/variants`) are handled too (v0.3.0+): the array is treated as the one-and-only page, so `collectAll` works uniformly across every list endpoint.
|
|
132
136
|
|
|
@@ -167,6 +171,72 @@ await pim.GET('/v1/products', {
|
|
|
167
171
|
|
|
168
172
|
Needs API **0.9.0+**. Check `GET /healthz`.
|
|
169
173
|
|
|
174
|
+
## Tags
|
|
175
|
+
|
|
176
|
+
Tags are **canonicalized on write**, so what you read back is not verbatim what you sent:
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
await pim.POST('/v1/content', { body: { /* … */ tags: ['Buying Guide', 'buying guide', 'FAQ!'] } });
|
|
180
|
+
// stored, and returned as: ['buying-guide', 'faq']
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Each tag is lower-cased, stripped of diacritics, has runs of non-alphanumerics collapsed to `-`, is trimmed of leading/trailing `-`, and is truncated to **60 characters**. Empties are dropped and duplicates removed (first occurrence wins), so **the array you get back can be shorter than the one you sent**. Note that the schema's `maxLength` is 80: two tags differing only past character 60 collapse into one.
|
|
184
|
+
|
|
185
|
+
This is deliberate — it is what makes `Featured`, `featured` and `FEATURED` one tag rather than three. Filters are canonicalized identically, so you never have to pre-slugify one:
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
await pim.GET('/v1/content', { params: { query: { tag: 'Buying Guide' } } }); // matches buying-guide
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
`tag` is repeatable and ANDs: `{ tag: ['guide', 'seo'] }` returns only pages carrying both. `GET /v1/products/tags` and `GET /v1/content/tags` list the vocabulary actually in use, with counts — two **separate** vocabularies, since an editorial tag and a merchandising tag rarely mean the same thing.
|
|
192
|
+
|
|
193
|
+
Documented in the field descriptions from API **0.14.1+**, and in these types from v0.7.0.
|
|
194
|
+
|
|
195
|
+
## Ordering a content archive (API 0.19.0+)
|
|
196
|
+
|
|
197
|
+
`GET /v1/content` defaults to `updatedAt` descending — the order things were last *edited*, which is rarely the order an archive should read in. Sort by `publishedAt`, which imports preserve from the source system:
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
const { data } = await pim.GET('/v1/content', {
|
|
201
|
+
params: { query: { sortBy: 'publishedAt', sortDir: 'desc', limit: 20 } },
|
|
202
|
+
});
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Pages with no `publishedAt` sort **last in both directions** — an undated page is unscheduled, not newest. `sortBy` also accepts `updatedAt`, `createdAt` and `title`.
|
|
206
|
+
|
|
207
|
+
`categoryId` behaves exactly like it does on products: **self-only** unless you add `includeDescendants: true`. Content gets filed against leaf categories too, so filtering by a parent section returns an empty page without it.
|
|
208
|
+
|
|
209
|
+
## Uploading files
|
|
210
|
+
|
|
211
|
+
`POST /v1/media` is `multipart/form-data`, not JSON. The file field is named `file`; everything else is optional and lets you attach the upload in the same request:
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
const form = new FormData();
|
|
215
|
+
form.append('file', blob, 'sell-sheet.pdf');
|
|
216
|
+
form.append('entityType', 'product'); // 'product' | 'variant' | 'content_page'
|
|
217
|
+
form.append('entityId', productId);
|
|
218
|
+
form.append('role', 'technical'); // hero | gallery | thumbnail | technical | lifestyle | swatch
|
|
219
|
+
form.append('altText', JSON.stringify({ en_US: 'Sell sheet' })); // a JSON *string*, not an object
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
`altText` is parsed as JSON, so passing a real object rather than a string stores no alt text. Send `JSON.stringify(...)`.
|
|
223
|
+
|
|
224
|
+
That case no longer fails silently. From API **0.21.0** a malformed `altText` still lets the upload succeed — it never fails the request — but the response says what it ignored:
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
const { data } = await pim.POST('/v1/media', { body: form as never });
|
|
228
|
+
if (data?.warnings?.length) console.warn(data.warnings);
|
|
229
|
+
// ["altText was not valid JSON and no alt text was stored; expected an object keyed by locale, …"]
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
`warnings` is absent when there is nothing to report, so a clean upload's response is unchanged.
|
|
233
|
+
|
|
234
|
+
**You do not have to get the content type right.** From API **0.21.0** the leading bytes are sniffed whenever you send `application/octet-stream` or no type at all — so a PNG whose filename lost its extension uploads as a PNG. If a specific declared type contradicts the bytes, the bytes win. SVG, CSV, plain text and the Office formats have no distinguishing magic bytes and still need an explicit type.
|
|
235
|
+
|
|
236
|
+
`role` and `position` are validated: an unrecognised value is a 422 listing the accepted ones in `details.accepted`, not a 500.
|
|
237
|
+
|
|
238
|
+
Requires API **0.14.0+** to appear in the spec at all — before that this endpoint published no request body, so generated clients had nothing for it.
|
|
239
|
+
|
|
170
240
|
## Attribute helpers
|
|
171
241
|
|
|
172
242
|
Attribute values are `unknown` and keyed by `(locale, channel)`. List responses return the raw `{ code: [{ locale, channel, value }] }` shape (only product *detail* with `?locale=&channel=` returns a flat `resolvedAttributes`). The SDK ships the flatten + coercion helpers so you don't reimplement them:
|
package/dist/index.d.cts
CHANGED
|
@@ -78,12 +78,17 @@ declare function createMinipimClient(opts: CreateMinipimClientOptions): MinipimC
|
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
80
|
* Generic pagination helper. MiniPim list endpoints return
|
|
81
|
-
* `{ data, limit, offset }`,
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
81
|
+
* `{ data, limit, offset, hasMore }`, where `hasMore` is always present and
|
|
82
|
+
* exact — the server fetches one row past the page to decide it, so a final
|
|
83
|
+
* page that is exactly full reports `false` instead of sending you after an
|
|
84
|
+
* empty one. Yields one item at a time.
|
|
85
|
+
*
|
|
86
|
+
* `hasMore` stays OPTIONAL in the type below, and the short-page fallback
|
|
87
|
+
* stays, deliberately: this client talks to whatever version the deployment is
|
|
88
|
+
* running, and API ≤ 0.13.0 omitted the field everywhere except
|
|
89
|
+
* `/v1/products`. Keeping the fallback means an older instance paginates
|
|
90
|
+
* correctly rather than reading one page and stopping — which is exactly the
|
|
91
|
+
* bug a hand-rolled `while (hasMore)` loop hit against those versions.
|
|
87
92
|
*
|
|
88
93
|
* Typed loosely on purpose — openapi-fetch's per-path generics don't
|
|
89
94
|
* compose into a single reusable signature without a lot of conditional-
|
package/dist/index.d.ts
CHANGED
|
@@ -78,12 +78,17 @@ declare function createMinipimClient(opts: CreateMinipimClientOptions): MinipimC
|
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
80
|
* Generic pagination helper. MiniPim list endpoints return
|
|
81
|
-
* `{ data, limit, offset }`,
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
81
|
+
* `{ data, limit, offset, hasMore }`, where `hasMore` is always present and
|
|
82
|
+
* exact — the server fetches one row past the page to decide it, so a final
|
|
83
|
+
* page that is exactly full reports `false` instead of sending you after an
|
|
84
|
+
* empty one. Yields one item at a time.
|
|
85
|
+
*
|
|
86
|
+
* `hasMore` stays OPTIONAL in the type below, and the short-page fallback
|
|
87
|
+
* stays, deliberately: this client talks to whatever version the deployment is
|
|
88
|
+
* running, and API ≤ 0.13.0 omitted the field everywhere except
|
|
89
|
+
* `/v1/products`. Keeping the fallback means an older instance paginates
|
|
90
|
+
* correctly rather than reading one page and stopping — which is exactly the
|
|
91
|
+
* bug a hand-rolled `while (hasMore)` loop hit against those versions.
|
|
87
92
|
*
|
|
88
93
|
* Typed loosely on purpose — openapi-fetch's per-path generics don't
|
|
89
94
|
* compose into a single reusable signature without a lot of conditional-
|
package/dist/openapi.d.cts
CHANGED
|
@@ -914,11 +914,6 @@ interface paths {
|
|
|
914
914
|
content: {
|
|
915
915
|
"application/json": {
|
|
916
916
|
code?: string;
|
|
917
|
-
/**
|
|
918
|
-
* @default product
|
|
919
|
-
* @enum {string}
|
|
920
|
-
*/
|
|
921
|
-
entityKind?: "product" | "content";
|
|
922
917
|
label?: {
|
|
923
918
|
[key: string]: string;
|
|
924
919
|
};
|
|
@@ -1575,6 +1570,7 @@ interface paths {
|
|
|
1575
1570
|
categoryId?: string;
|
|
1576
1571
|
includeDescendants?: boolean | ("true" | "false" | "1" | "0");
|
|
1577
1572
|
brand?: string;
|
|
1573
|
+
/** @description Repeatable — `?tag=a&tag=b` matches records carrying ALL listed tags. Values are canonicalized exactly as writes are, so `?tag=Buying%20Guide` matches the stored `buying-guide`; you never have to pre-slugify a filter. Backed by the GIN index on `tags`. */
|
|
1578
1574
|
tag?: string | string[];
|
|
1579
1575
|
connectorId?: string;
|
|
1580
1576
|
updatedSince?: string;
|
|
@@ -1621,6 +1617,7 @@ interface paths {
|
|
|
1621
1617
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
1622
1618
|
[key: string]: unknown;
|
|
1623
1619
|
};
|
|
1620
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
1624
1621
|
tags: string[];
|
|
1625
1622
|
/** Format: uuid */
|
|
1626
1623
|
createdBy: string | null;
|
|
@@ -1631,7 +1628,7 @@ interface paths {
|
|
|
1631
1628
|
}[];
|
|
1632
1629
|
limit: number;
|
|
1633
1630
|
offset: number;
|
|
1634
|
-
hasMore
|
|
1631
|
+
hasMore: boolean;
|
|
1635
1632
|
total?: number;
|
|
1636
1633
|
};
|
|
1637
1634
|
};
|
|
@@ -1670,7 +1667,10 @@ interface paths {
|
|
|
1670
1667
|
value?: unknown;
|
|
1671
1668
|
}[];
|
|
1672
1669
|
};
|
|
1673
|
-
/**
|
|
1670
|
+
/**
|
|
1671
|
+
* @description Free-form tags, canonicalized on write and echoed back in canonical form — the response will NOT match your input verbatim. Each tag is lower-cased, stripped of diacritics, has every run of non-alphanumerics replaced with `-`, is trimmed of leading/trailing `-`, and is then truncated to 60 characters. So `"Buying Guide"` is stored and filtered as `buying-guide`. Tags that normalize to nothing (`""`, `"!!"`) are dropped, and duplicates are removed keeping first-occurrence order, so the array you get back may be SHORTER than the one you sent. Note the asymmetry with `maxLength`: an item may be up to 80 characters on input but is truncated to 60 once canonicalized, which can collapse two long tags into one.
|
|
1672
|
+
* @default []
|
|
1673
|
+
*/
|
|
1674
1674
|
tags?: string[];
|
|
1675
1675
|
};
|
|
1676
1676
|
};
|
|
@@ -1700,6 +1700,7 @@ interface paths {
|
|
|
1700
1700
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
1701
1701
|
[key: string]: unknown;
|
|
1702
1702
|
};
|
|
1703
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
1703
1704
|
tags: string[];
|
|
1704
1705
|
/** Format: uuid */
|
|
1705
1706
|
createdBy: string | null;
|
|
@@ -1766,6 +1767,7 @@ interface paths {
|
|
|
1766
1767
|
categoryId?: string;
|
|
1767
1768
|
includeDescendants?: boolean | ("true" | "false" | "1" | "0");
|
|
1768
1769
|
brand?: string;
|
|
1770
|
+
/** @description Repeatable — `?tag=a&tag=b` matches records carrying ALL listed tags. Values are canonicalized exactly as writes are, so `?tag=Buying%20Guide` matches the stored `buying-guide`; you never have to pre-slugify a filter. Backed by the GIN index on `tags`. */
|
|
1769
1771
|
tag?: string | string[];
|
|
1770
1772
|
connectorId?: string;
|
|
1771
1773
|
updatedSince?: string;
|
|
@@ -1985,6 +1987,7 @@ interface paths {
|
|
|
1985
1987
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
1986
1988
|
[key: string]: unknown;
|
|
1987
1989
|
};
|
|
1990
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
1988
1991
|
tags: string[];
|
|
1989
1992
|
/** Format: uuid */
|
|
1990
1993
|
createdBy: string | null;
|
|
@@ -2108,6 +2111,7 @@ interface paths {
|
|
|
2108
2111
|
value?: unknown;
|
|
2109
2112
|
}[];
|
|
2110
2113
|
};
|
|
2114
|
+
/** @description Replaces the full tag list when present. Free-form tags, canonicalized on write and echoed back in canonical form — the response will NOT match your input verbatim. Each tag is lower-cased, stripped of diacritics, has every run of non-alphanumerics replaced with `-`, is trimmed of leading/trailing `-`, and is then truncated to 60 characters. So `"Buying Guide"` is stored and filtered as `buying-guide`. Tags that normalize to nothing (`""`, `"!!"`) are dropped, and duplicates are removed keeping first-occurrence order, so the array you get back may be SHORTER than the one you sent. Note the asymmetry with `maxLength`: an item may be up to 80 characters on input but is truncated to 60 once canonicalized, which can collapse two long tags into one. */
|
|
2111
2115
|
tags?: string[];
|
|
2112
2116
|
};
|
|
2113
2117
|
};
|
|
@@ -2137,6 +2141,7 @@ interface paths {
|
|
|
2137
2141
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
2138
2142
|
[key: string]: unknown;
|
|
2139
2143
|
};
|
|
2144
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
2140
2145
|
tags: string[];
|
|
2141
2146
|
/** Format: uuid */
|
|
2142
2147
|
createdBy: string | null;
|
|
@@ -2304,6 +2309,7 @@ interface paths {
|
|
|
2304
2309
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
2305
2310
|
[key: string]: unknown;
|
|
2306
2311
|
};
|
|
2312
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
2307
2313
|
tags: string[];
|
|
2308
2314
|
/** Format: uuid */
|
|
2309
2315
|
createdBy: string | null;
|
|
@@ -2710,6 +2716,7 @@ interface paths {
|
|
|
2710
2716
|
productIds: string[];
|
|
2711
2717
|
/** @enum {string} */
|
|
2712
2718
|
mode: "add" | "remove" | "replace";
|
|
2719
|
+
/** @description Free-form tags, canonicalized on write and echoed back in canonical form — the response will NOT match your input verbatim. Each tag is lower-cased, stripped of diacritics, has every run of non-alphanumerics replaced with `-`, is trimmed of leading/trailing `-`, and is then truncated to 60 characters. So `"Buying Guide"` is stored and filtered as `buying-guide`. Tags that normalize to nothing (`""`, `"!!"`) are dropped, and duplicates are removed keeping first-occurrence order, so the array you get back may be SHORTER than the one you sent. Note the asymmetry with `maxLength`: an item may be up to 80 characters on input but is truncated to 60 once canonicalized, which can collapse two long tags into one. */
|
|
2713
2720
|
tags: string[];
|
|
2714
2721
|
};
|
|
2715
2722
|
};
|
|
@@ -3514,6 +3521,16 @@ interface paths {
|
|
|
3514
3521
|
/**
|
|
3515
3522
|
* List content pages
|
|
3516
3523
|
* @description Filters and pagination mirror `GET /v1/products`. `tag` is repeatable and matches pages carrying ALL listed tags.
|
|
3524
|
+
*
|
|
3525
|
+
* Ordering defaults to `updatedAt` descending. For a blog archive sort by `publishedAt`, which imports preserve from the source system:
|
|
3526
|
+
*
|
|
3527
|
+
* ```
|
|
3528
|
+
* curl 'https://api.minipim.com/v1/content?sortBy=publishedAt&sortDir=desc&limit=20'
|
|
3529
|
+
* ```
|
|
3530
|
+
*
|
|
3531
|
+
* Pages with no `publishedAt` sort LAST in both directions — an undated page is unscheduled, not newest.
|
|
3532
|
+
*
|
|
3533
|
+
* `categoryId` is SELF-ONLY. Content is filed against leaf categories, so filtering by a parent returns an empty page unless you add `includeDescendants=true` to match the whole subtree.
|
|
3517
3534
|
*/
|
|
3518
3535
|
get: {
|
|
3519
3536
|
parameters: {
|
|
@@ -3522,9 +3539,13 @@ interface paths {
|
|
|
3522
3539
|
q?: string;
|
|
3523
3540
|
familyId?: string;
|
|
3524
3541
|
categoryId?: string;
|
|
3542
|
+
includeDescendants?: boolean | ("true" | "false" | "1" | "0");
|
|
3525
3543
|
channelId?: string;
|
|
3544
|
+
/** @description Repeatable — `?tag=a&tag=b` matches records carrying ALL listed tags. Values are canonicalized exactly as writes are, so `?tag=Buying%20Guide` matches the stored `buying-guide`; you never have to pre-slugify a filter. */
|
|
3526
3545
|
tag?: string | string[];
|
|
3527
3546
|
updatedSince?: string;
|
|
3547
|
+
sortBy?: "publishedAt" | "updatedAt" | "createdAt" | "title";
|
|
3548
|
+
sortDir?: "asc" | "desc";
|
|
3528
3549
|
limit?: number;
|
|
3529
3550
|
offset?: number;
|
|
3530
3551
|
};
|
|
@@ -3563,6 +3584,7 @@ interface paths {
|
|
|
3563
3584
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
3564
3585
|
[key: string]: unknown;
|
|
3565
3586
|
};
|
|
3587
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
3566
3588
|
tags: string[];
|
|
3567
3589
|
/** Format: uuid */
|
|
3568
3590
|
createdBy: string | null;
|
|
@@ -3571,8 +3593,7 @@ interface paths {
|
|
|
3571
3593
|
}[];
|
|
3572
3594
|
limit: number;
|
|
3573
3595
|
offset: number;
|
|
3574
|
-
hasMore
|
|
3575
|
-
total?: number;
|
|
3596
|
+
hasMore: boolean;
|
|
3576
3597
|
};
|
|
3577
3598
|
};
|
|
3578
3599
|
};
|
|
@@ -3629,7 +3650,10 @@ interface paths {
|
|
|
3629
3650
|
value?: unknown;
|
|
3630
3651
|
}[];
|
|
3631
3652
|
};
|
|
3632
|
-
/**
|
|
3653
|
+
/**
|
|
3654
|
+
* @description Free-form tags, canonicalized on write and echoed back in canonical form — the response will NOT match your input verbatim. Each tag is lower-cased, stripped of diacritics, has every run of non-alphanumerics replaced with `-`, is trimmed of leading/trailing `-`, and is then truncated to 60 characters. So `"Buying Guide"` is stored and filtered as `buying-guide`. Tags that normalize to nothing (`""`, `"!!"`) are dropped, and duplicates are removed keeping first-occurrence order, so the array you get back may be SHORTER than the one you sent. Note the asymmetry with `maxLength`: an item may be up to 80 characters on input but is truncated to 60 once canonicalized, which can collapse two long tags into one.
|
|
3655
|
+
* @default []
|
|
3656
|
+
*/
|
|
3633
3657
|
tags?: string[];
|
|
3634
3658
|
};
|
|
3635
3659
|
};
|
|
@@ -3663,6 +3687,7 @@ interface paths {
|
|
|
3663
3687
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
3664
3688
|
[key: string]: unknown;
|
|
3665
3689
|
};
|
|
3690
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
3666
3691
|
tags: string[];
|
|
3667
3692
|
/** Format: uuid */
|
|
3668
3693
|
createdBy: string | null;
|
|
@@ -3739,6 +3764,63 @@ interface paths {
|
|
|
3739
3764
|
patch?: never;
|
|
3740
3765
|
trace?: never;
|
|
3741
3766
|
};
|
|
3767
|
+
"/v1/content/tags": {
|
|
3768
|
+
parameters: {
|
|
3769
|
+
query?: never;
|
|
3770
|
+
header?: never;
|
|
3771
|
+
path?: never;
|
|
3772
|
+
cookie?: never;
|
|
3773
|
+
};
|
|
3774
|
+
/**
|
|
3775
|
+
* List all content-page tags in use, with counts
|
|
3776
|
+
* @description Every distinct tag currently on at least one content page, ordered by usage. Powers tag autocomplete in the editor, which is what keeps a vocabulary from drifting into `guide` / `guides` / `Guides`. Filter pages by tag with `GET /v1/content?tag=<tag>` (repeatable; multiple tags AND together).
|
|
3777
|
+
*/
|
|
3778
|
+
get: {
|
|
3779
|
+
parameters: {
|
|
3780
|
+
query?: never;
|
|
3781
|
+
header?: never;
|
|
3782
|
+
path?: never;
|
|
3783
|
+
cookie?: never;
|
|
3784
|
+
};
|
|
3785
|
+
requestBody?: never;
|
|
3786
|
+
responses: {
|
|
3787
|
+
/** @description Default Response */
|
|
3788
|
+
200: {
|
|
3789
|
+
headers: {
|
|
3790
|
+
[name: string]: unknown;
|
|
3791
|
+
};
|
|
3792
|
+
content: {
|
|
3793
|
+
"application/json": {
|
|
3794
|
+
value: string;
|
|
3795
|
+
count: number;
|
|
3796
|
+
}[];
|
|
3797
|
+
};
|
|
3798
|
+
};
|
|
3799
|
+
/** @description Default Response */
|
|
3800
|
+
403: {
|
|
3801
|
+
headers: {
|
|
3802
|
+
[name: string]: unknown;
|
|
3803
|
+
};
|
|
3804
|
+
content: {
|
|
3805
|
+
"application/json": {
|
|
3806
|
+
error: {
|
|
3807
|
+
code: string;
|
|
3808
|
+
message: string;
|
|
3809
|
+
details?: unknown;
|
|
3810
|
+
};
|
|
3811
|
+
};
|
|
3812
|
+
};
|
|
3813
|
+
};
|
|
3814
|
+
};
|
|
3815
|
+
};
|
|
3816
|
+
put?: never;
|
|
3817
|
+
post?: never;
|
|
3818
|
+
delete?: never;
|
|
3819
|
+
options?: never;
|
|
3820
|
+
head?: never;
|
|
3821
|
+
patch?: never;
|
|
3822
|
+
trace?: never;
|
|
3823
|
+
};
|
|
3742
3824
|
"/v1/content/{id}": {
|
|
3743
3825
|
parameters: {
|
|
3744
3826
|
query?: never;
|
|
@@ -3786,6 +3868,7 @@ interface paths {
|
|
|
3786
3868
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
3787
3869
|
[key: string]: unknown;
|
|
3788
3870
|
};
|
|
3871
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
3789
3872
|
tags: string[];
|
|
3790
3873
|
/** Format: uuid */
|
|
3791
3874
|
createdBy: string | null;
|
|
@@ -3918,6 +4001,7 @@ interface paths {
|
|
|
3918
4001
|
value?: unknown;
|
|
3919
4002
|
}[];
|
|
3920
4003
|
};
|
|
4004
|
+
/** @description Replaces the full tag list when present. Free-form tags, canonicalized on write and echoed back in canonical form — the response will NOT match your input verbatim. Each tag is lower-cased, stripped of diacritics, has every run of non-alphanumerics replaced with `-`, is trimmed of leading/trailing `-`, and is then truncated to 60 characters. So `"Buying Guide"` is stored and filtered as `buying-guide`. Tags that normalize to nothing (`""`, `"!!"`) are dropped, and duplicates are removed keeping first-occurrence order, so the array you get back may be SHORTER than the one you sent. Note the asymmetry with `maxLength`: an item may be up to 80 characters on input but is truncated to 60 once canonicalized, which can collapse two long tags into one. */
|
|
3921
4005
|
tags?: string[];
|
|
3922
4006
|
};
|
|
3923
4007
|
};
|
|
@@ -3951,6 +4035,7 @@ interface paths {
|
|
|
3951
4035
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
3952
4036
|
[key: string]: unknown;
|
|
3953
4037
|
};
|
|
4038
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
3954
4039
|
tags: string[];
|
|
3955
4040
|
/** Format: uuid */
|
|
3956
4041
|
createdBy: string | null;
|
|
@@ -5913,7 +5998,44 @@ interface paths {
|
|
|
5913
5998
|
path?: never;
|
|
5914
5999
|
cookie?: never;
|
|
5915
6000
|
};
|
|
5916
|
-
requestBody
|
|
6001
|
+
requestBody: {
|
|
6002
|
+
content: {
|
|
6003
|
+
"multipart/form-data": {
|
|
6004
|
+
/**
|
|
6005
|
+
* Format: binary
|
|
6006
|
+
* @description The file to upload. Images, video, PDF, Office documents and glTF are accepted; the 422 response lists every allowed type in `details.allowed`. You do NOT have to get the content type right: when you send `application/octet-stream` (or no type at all), the leading bytes are sniffed and the detected type is used — so a PNG whose filename lost its extension uploads fine. SVG, CSV, plain text and Office formats have no distinguishing magic bytes and still need an explicit type. If a specific declared type contradicts the bytes, the bytes win.
|
|
6007
|
+
*/
|
|
6008
|
+
file: string;
|
|
6009
|
+
/**
|
|
6010
|
+
* @description Attach the upload in the same transaction. Requires `entityId`; supplying only one of the pair uploads the file WITHOUT associating it. A value outside the enum is a 422, not a silent miss.
|
|
6011
|
+
* @enum {string}
|
|
6012
|
+
*/
|
|
6013
|
+
entityType?: "product" | "variant" | "content_page";
|
|
6014
|
+
/**
|
|
6015
|
+
* Format: uuid
|
|
6016
|
+
* @description The id of the entity named by `entityType`.
|
|
6017
|
+
*/
|
|
6018
|
+
entityId?: string;
|
|
6019
|
+
/**
|
|
6020
|
+
* @description Association role. Ignored unless `entityType`+`entityId` are present. A value outside this enum is rejected with a 422 that lists the accepted values in `details.accepted`.
|
|
6021
|
+
* @default gallery
|
|
6022
|
+
* @enum {string}
|
|
6023
|
+
*/
|
|
6024
|
+
role?: "hero" | "gallery" | "thumbnail" | "technical" | "lifestyle" | "swatch";
|
|
6025
|
+
/**
|
|
6026
|
+
* @description Sort position within the entity’s gallery. Must be a non-negative integer; anything else is a 422.
|
|
6027
|
+
* @default 0
|
|
6028
|
+
*/
|
|
6029
|
+
position?: number;
|
|
6030
|
+
/**
|
|
6031
|
+
* @description A JSON OBJECT keyed by locale, sent as a STRING — e.g. `{"en_US":"Blue widget on white"}`. Unparseable JSON, or JSON that is not an object of locale → string, does NOT fail the upload: the file is stored, no alt text is saved, and the 201 response carries a `warnings` entry saying so. Check `warnings` if you send alt text programmatically. Omit the field entirely if you have none.
|
|
6032
|
+
*
|
|
6033
|
+
* (0.20.0 briefly made this a 422; 0.21.0 restored the original behaviour and added `warnings` instead, so the problem is reported without breaking callers.)
|
|
6034
|
+
*/
|
|
6035
|
+
altText?: string;
|
|
6036
|
+
};
|
|
6037
|
+
};
|
|
6038
|
+
};
|
|
5917
6039
|
responses: {
|
|
5918
6040
|
/** @description Default Response */
|
|
5919
6041
|
201: {
|
|
@@ -5966,6 +6088,8 @@ interface paths {
|
|
|
5966
6088
|
channelId: string | null;
|
|
5967
6089
|
};
|
|
5968
6090
|
url: string;
|
|
6091
|
+
/** @description Non-fatal problems with this upload — currently only malformed `altText`. The upload succeeded; something you sent was ignored. Absent when there is nothing to report. */
|
|
6092
|
+
warnings?: string[];
|
|
5969
6093
|
};
|
|
5970
6094
|
};
|
|
5971
6095
|
};
|
|
@@ -5985,6 +6109,36 @@ interface paths {
|
|
|
5985
6109
|
};
|
|
5986
6110
|
};
|
|
5987
6111
|
/** @description Default Response */
|
|
6112
|
+
413: {
|
|
6113
|
+
headers: {
|
|
6114
|
+
[name: string]: unknown;
|
|
6115
|
+
};
|
|
6116
|
+
content: {
|
|
6117
|
+
"application/json": {
|
|
6118
|
+
error: {
|
|
6119
|
+
code: string;
|
|
6120
|
+
message: string;
|
|
6121
|
+
details?: unknown;
|
|
6122
|
+
};
|
|
6123
|
+
};
|
|
6124
|
+
};
|
|
6125
|
+
};
|
|
6126
|
+
/** @description Default Response */
|
|
6127
|
+
422: {
|
|
6128
|
+
headers: {
|
|
6129
|
+
[name: string]: unknown;
|
|
6130
|
+
};
|
|
6131
|
+
content: {
|
|
6132
|
+
"application/json": {
|
|
6133
|
+
error: {
|
|
6134
|
+
code: string;
|
|
6135
|
+
message: string;
|
|
6136
|
+
details?: unknown;
|
|
6137
|
+
};
|
|
6138
|
+
};
|
|
6139
|
+
};
|
|
6140
|
+
};
|
|
6141
|
+
/** @description Default Response */
|
|
5988
6142
|
503: {
|
|
5989
6143
|
headers: {
|
|
5990
6144
|
[name: string]: unknown;
|
|
@@ -7471,7 +7625,7 @@ interface paths {
|
|
|
7471
7625
|
availability: "oss" | "hosted";
|
|
7472
7626
|
capabilities: {
|
|
7473
7627
|
/** @enum {string} */
|
|
7474
|
-
entity: "product" | "variant" | "media" | "category";
|
|
7628
|
+
entity: "product" | "variant" | "media" | "category" | "content_page";
|
|
7475
7629
|
/** @enum {string} */
|
|
7476
7630
|
direction: "push" | "pull" | "bidirectional";
|
|
7477
7631
|
}[];
|
|
@@ -8934,11 +9088,12 @@ interface paths {
|
|
|
8934
9088
|
}) | null;
|
|
8935
9089
|
/** Format: date-time */
|
|
8936
9090
|
createdAt: string;
|
|
9091
|
+
/** @description Display name for the actor: the user’s name or email for `user` rows, the connector’s name for `connector` rows, null when the actor is unattributed (`system`) or no longer resolvable. */
|
|
9092
|
+
actorLabel: string | null;
|
|
8937
9093
|
}[];
|
|
8938
9094
|
limit: number;
|
|
8939
9095
|
offset: number;
|
|
8940
|
-
hasMore
|
|
8941
|
-
total?: number;
|
|
9096
|
+
hasMore: boolean;
|
|
8942
9097
|
};
|
|
8943
9098
|
};
|
|
8944
9099
|
};
|
package/dist/openapi.d.ts
CHANGED
|
@@ -914,11 +914,6 @@ interface paths {
|
|
|
914
914
|
content: {
|
|
915
915
|
"application/json": {
|
|
916
916
|
code?: string;
|
|
917
|
-
/**
|
|
918
|
-
* @default product
|
|
919
|
-
* @enum {string}
|
|
920
|
-
*/
|
|
921
|
-
entityKind?: "product" | "content";
|
|
922
917
|
label?: {
|
|
923
918
|
[key: string]: string;
|
|
924
919
|
};
|
|
@@ -1575,6 +1570,7 @@ interface paths {
|
|
|
1575
1570
|
categoryId?: string;
|
|
1576
1571
|
includeDescendants?: boolean | ("true" | "false" | "1" | "0");
|
|
1577
1572
|
brand?: string;
|
|
1573
|
+
/** @description Repeatable — `?tag=a&tag=b` matches records carrying ALL listed tags. Values are canonicalized exactly as writes are, so `?tag=Buying%20Guide` matches the stored `buying-guide`; you never have to pre-slugify a filter. Backed by the GIN index on `tags`. */
|
|
1578
1574
|
tag?: string | string[];
|
|
1579
1575
|
connectorId?: string;
|
|
1580
1576
|
updatedSince?: string;
|
|
@@ -1621,6 +1617,7 @@ interface paths {
|
|
|
1621
1617
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
1622
1618
|
[key: string]: unknown;
|
|
1623
1619
|
};
|
|
1620
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
1624
1621
|
tags: string[];
|
|
1625
1622
|
/** Format: uuid */
|
|
1626
1623
|
createdBy: string | null;
|
|
@@ -1631,7 +1628,7 @@ interface paths {
|
|
|
1631
1628
|
}[];
|
|
1632
1629
|
limit: number;
|
|
1633
1630
|
offset: number;
|
|
1634
|
-
hasMore
|
|
1631
|
+
hasMore: boolean;
|
|
1635
1632
|
total?: number;
|
|
1636
1633
|
};
|
|
1637
1634
|
};
|
|
@@ -1670,7 +1667,10 @@ interface paths {
|
|
|
1670
1667
|
value?: unknown;
|
|
1671
1668
|
}[];
|
|
1672
1669
|
};
|
|
1673
|
-
/**
|
|
1670
|
+
/**
|
|
1671
|
+
* @description Free-form tags, canonicalized on write and echoed back in canonical form — the response will NOT match your input verbatim. Each tag is lower-cased, stripped of diacritics, has every run of non-alphanumerics replaced with `-`, is trimmed of leading/trailing `-`, and is then truncated to 60 characters. So `"Buying Guide"` is stored and filtered as `buying-guide`. Tags that normalize to nothing (`""`, `"!!"`) are dropped, and duplicates are removed keeping first-occurrence order, so the array you get back may be SHORTER than the one you sent. Note the asymmetry with `maxLength`: an item may be up to 80 characters on input but is truncated to 60 once canonicalized, which can collapse two long tags into one.
|
|
1672
|
+
* @default []
|
|
1673
|
+
*/
|
|
1674
1674
|
tags?: string[];
|
|
1675
1675
|
};
|
|
1676
1676
|
};
|
|
@@ -1700,6 +1700,7 @@ interface paths {
|
|
|
1700
1700
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
1701
1701
|
[key: string]: unknown;
|
|
1702
1702
|
};
|
|
1703
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
1703
1704
|
tags: string[];
|
|
1704
1705
|
/** Format: uuid */
|
|
1705
1706
|
createdBy: string | null;
|
|
@@ -1766,6 +1767,7 @@ interface paths {
|
|
|
1766
1767
|
categoryId?: string;
|
|
1767
1768
|
includeDescendants?: boolean | ("true" | "false" | "1" | "0");
|
|
1768
1769
|
brand?: string;
|
|
1770
|
+
/** @description Repeatable — `?tag=a&tag=b` matches records carrying ALL listed tags. Values are canonicalized exactly as writes are, so `?tag=Buying%20Guide` matches the stored `buying-guide`; you never have to pre-slugify a filter. Backed by the GIN index on `tags`. */
|
|
1769
1771
|
tag?: string | string[];
|
|
1770
1772
|
connectorId?: string;
|
|
1771
1773
|
updatedSince?: string;
|
|
@@ -1985,6 +1987,7 @@ interface paths {
|
|
|
1985
1987
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
1986
1988
|
[key: string]: unknown;
|
|
1987
1989
|
};
|
|
1990
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
1988
1991
|
tags: string[];
|
|
1989
1992
|
/** Format: uuid */
|
|
1990
1993
|
createdBy: string | null;
|
|
@@ -2108,6 +2111,7 @@ interface paths {
|
|
|
2108
2111
|
value?: unknown;
|
|
2109
2112
|
}[];
|
|
2110
2113
|
};
|
|
2114
|
+
/** @description Replaces the full tag list when present. Free-form tags, canonicalized on write and echoed back in canonical form — the response will NOT match your input verbatim. Each tag is lower-cased, stripped of diacritics, has every run of non-alphanumerics replaced with `-`, is trimmed of leading/trailing `-`, and is then truncated to 60 characters. So `"Buying Guide"` is stored and filtered as `buying-guide`. Tags that normalize to nothing (`""`, `"!!"`) are dropped, and duplicates are removed keeping first-occurrence order, so the array you get back may be SHORTER than the one you sent. Note the asymmetry with `maxLength`: an item may be up to 80 characters on input but is truncated to 60 once canonicalized, which can collapse two long tags into one. */
|
|
2111
2115
|
tags?: string[];
|
|
2112
2116
|
};
|
|
2113
2117
|
};
|
|
@@ -2137,6 +2141,7 @@ interface paths {
|
|
|
2137
2141
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
2138
2142
|
[key: string]: unknown;
|
|
2139
2143
|
};
|
|
2144
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
2140
2145
|
tags: string[];
|
|
2141
2146
|
/** Format: uuid */
|
|
2142
2147
|
createdBy: string | null;
|
|
@@ -2304,6 +2309,7 @@ interface paths {
|
|
|
2304
2309
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
2305
2310
|
[key: string]: unknown;
|
|
2306
2311
|
};
|
|
2312
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
2307
2313
|
tags: string[];
|
|
2308
2314
|
/** Format: uuid */
|
|
2309
2315
|
createdBy: string | null;
|
|
@@ -2710,6 +2716,7 @@ interface paths {
|
|
|
2710
2716
|
productIds: string[];
|
|
2711
2717
|
/** @enum {string} */
|
|
2712
2718
|
mode: "add" | "remove" | "replace";
|
|
2719
|
+
/** @description Free-form tags, canonicalized on write and echoed back in canonical form — the response will NOT match your input verbatim. Each tag is lower-cased, stripped of diacritics, has every run of non-alphanumerics replaced with `-`, is trimmed of leading/trailing `-`, and is then truncated to 60 characters. So `"Buying Guide"` is stored and filtered as `buying-guide`. Tags that normalize to nothing (`""`, `"!!"`) are dropped, and duplicates are removed keeping first-occurrence order, so the array you get back may be SHORTER than the one you sent. Note the asymmetry with `maxLength`: an item may be up to 80 characters on input but is truncated to 60 once canonicalized, which can collapse two long tags into one. */
|
|
2713
2720
|
tags: string[];
|
|
2714
2721
|
};
|
|
2715
2722
|
};
|
|
@@ -3514,6 +3521,16 @@ interface paths {
|
|
|
3514
3521
|
/**
|
|
3515
3522
|
* List content pages
|
|
3516
3523
|
* @description Filters and pagination mirror `GET /v1/products`. `tag` is repeatable and matches pages carrying ALL listed tags.
|
|
3524
|
+
*
|
|
3525
|
+
* Ordering defaults to `updatedAt` descending. For a blog archive sort by `publishedAt`, which imports preserve from the source system:
|
|
3526
|
+
*
|
|
3527
|
+
* ```
|
|
3528
|
+
* curl 'https://api.minipim.com/v1/content?sortBy=publishedAt&sortDir=desc&limit=20'
|
|
3529
|
+
* ```
|
|
3530
|
+
*
|
|
3531
|
+
* Pages with no `publishedAt` sort LAST in both directions — an undated page is unscheduled, not newest.
|
|
3532
|
+
*
|
|
3533
|
+
* `categoryId` is SELF-ONLY. Content is filed against leaf categories, so filtering by a parent returns an empty page unless you add `includeDescendants=true` to match the whole subtree.
|
|
3517
3534
|
*/
|
|
3518
3535
|
get: {
|
|
3519
3536
|
parameters: {
|
|
@@ -3522,9 +3539,13 @@ interface paths {
|
|
|
3522
3539
|
q?: string;
|
|
3523
3540
|
familyId?: string;
|
|
3524
3541
|
categoryId?: string;
|
|
3542
|
+
includeDescendants?: boolean | ("true" | "false" | "1" | "0");
|
|
3525
3543
|
channelId?: string;
|
|
3544
|
+
/** @description Repeatable — `?tag=a&tag=b` matches records carrying ALL listed tags. Values are canonicalized exactly as writes are, so `?tag=Buying%20Guide` matches the stored `buying-guide`; you never have to pre-slugify a filter. */
|
|
3526
3545
|
tag?: string | string[];
|
|
3527
3546
|
updatedSince?: string;
|
|
3547
|
+
sortBy?: "publishedAt" | "updatedAt" | "createdAt" | "title";
|
|
3548
|
+
sortDir?: "asc" | "desc";
|
|
3528
3549
|
limit?: number;
|
|
3529
3550
|
offset?: number;
|
|
3530
3551
|
};
|
|
@@ -3563,6 +3584,7 @@ interface paths {
|
|
|
3563
3584
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
3564
3585
|
[key: string]: unknown;
|
|
3565
3586
|
};
|
|
3587
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
3566
3588
|
tags: string[];
|
|
3567
3589
|
/** Format: uuid */
|
|
3568
3590
|
createdBy: string | null;
|
|
@@ -3571,8 +3593,7 @@ interface paths {
|
|
|
3571
3593
|
}[];
|
|
3572
3594
|
limit: number;
|
|
3573
3595
|
offset: number;
|
|
3574
|
-
hasMore
|
|
3575
|
-
total?: number;
|
|
3596
|
+
hasMore: boolean;
|
|
3576
3597
|
};
|
|
3577
3598
|
};
|
|
3578
3599
|
};
|
|
@@ -3629,7 +3650,10 @@ interface paths {
|
|
|
3629
3650
|
value?: unknown;
|
|
3630
3651
|
}[];
|
|
3631
3652
|
};
|
|
3632
|
-
/**
|
|
3653
|
+
/**
|
|
3654
|
+
* @description Free-form tags, canonicalized on write and echoed back in canonical form — the response will NOT match your input verbatim. Each tag is lower-cased, stripped of diacritics, has every run of non-alphanumerics replaced with `-`, is trimmed of leading/trailing `-`, and is then truncated to 60 characters. So `"Buying Guide"` is stored and filtered as `buying-guide`. Tags that normalize to nothing (`""`, `"!!"`) are dropped, and duplicates are removed keeping first-occurrence order, so the array you get back may be SHORTER than the one you sent. Note the asymmetry with `maxLength`: an item may be up to 80 characters on input but is truncated to 60 once canonicalized, which can collapse two long tags into one.
|
|
3655
|
+
* @default []
|
|
3656
|
+
*/
|
|
3633
3657
|
tags?: string[];
|
|
3634
3658
|
};
|
|
3635
3659
|
};
|
|
@@ -3663,6 +3687,7 @@ interface paths {
|
|
|
3663
3687
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
3664
3688
|
[key: string]: unknown;
|
|
3665
3689
|
};
|
|
3690
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
3666
3691
|
tags: string[];
|
|
3667
3692
|
/** Format: uuid */
|
|
3668
3693
|
createdBy: string | null;
|
|
@@ -3739,6 +3764,63 @@ interface paths {
|
|
|
3739
3764
|
patch?: never;
|
|
3740
3765
|
trace?: never;
|
|
3741
3766
|
};
|
|
3767
|
+
"/v1/content/tags": {
|
|
3768
|
+
parameters: {
|
|
3769
|
+
query?: never;
|
|
3770
|
+
header?: never;
|
|
3771
|
+
path?: never;
|
|
3772
|
+
cookie?: never;
|
|
3773
|
+
};
|
|
3774
|
+
/**
|
|
3775
|
+
* List all content-page tags in use, with counts
|
|
3776
|
+
* @description Every distinct tag currently on at least one content page, ordered by usage. Powers tag autocomplete in the editor, which is what keeps a vocabulary from drifting into `guide` / `guides` / `Guides`. Filter pages by tag with `GET /v1/content?tag=<tag>` (repeatable; multiple tags AND together).
|
|
3777
|
+
*/
|
|
3778
|
+
get: {
|
|
3779
|
+
parameters: {
|
|
3780
|
+
query?: never;
|
|
3781
|
+
header?: never;
|
|
3782
|
+
path?: never;
|
|
3783
|
+
cookie?: never;
|
|
3784
|
+
};
|
|
3785
|
+
requestBody?: never;
|
|
3786
|
+
responses: {
|
|
3787
|
+
/** @description Default Response */
|
|
3788
|
+
200: {
|
|
3789
|
+
headers: {
|
|
3790
|
+
[name: string]: unknown;
|
|
3791
|
+
};
|
|
3792
|
+
content: {
|
|
3793
|
+
"application/json": {
|
|
3794
|
+
value: string;
|
|
3795
|
+
count: number;
|
|
3796
|
+
}[];
|
|
3797
|
+
};
|
|
3798
|
+
};
|
|
3799
|
+
/** @description Default Response */
|
|
3800
|
+
403: {
|
|
3801
|
+
headers: {
|
|
3802
|
+
[name: string]: unknown;
|
|
3803
|
+
};
|
|
3804
|
+
content: {
|
|
3805
|
+
"application/json": {
|
|
3806
|
+
error: {
|
|
3807
|
+
code: string;
|
|
3808
|
+
message: string;
|
|
3809
|
+
details?: unknown;
|
|
3810
|
+
};
|
|
3811
|
+
};
|
|
3812
|
+
};
|
|
3813
|
+
};
|
|
3814
|
+
};
|
|
3815
|
+
};
|
|
3816
|
+
put?: never;
|
|
3817
|
+
post?: never;
|
|
3818
|
+
delete?: never;
|
|
3819
|
+
options?: never;
|
|
3820
|
+
head?: never;
|
|
3821
|
+
patch?: never;
|
|
3822
|
+
trace?: never;
|
|
3823
|
+
};
|
|
3742
3824
|
"/v1/content/{id}": {
|
|
3743
3825
|
parameters: {
|
|
3744
3826
|
query?: never;
|
|
@@ -3786,6 +3868,7 @@ interface paths {
|
|
|
3786
3868
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
3787
3869
|
[key: string]: unknown;
|
|
3788
3870
|
};
|
|
3871
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
3789
3872
|
tags: string[];
|
|
3790
3873
|
/** Format: uuid */
|
|
3791
3874
|
createdBy: string | null;
|
|
@@ -3918,6 +4001,7 @@ interface paths {
|
|
|
3918
4001
|
value?: unknown;
|
|
3919
4002
|
}[];
|
|
3920
4003
|
};
|
|
4004
|
+
/** @description Replaces the full tag list when present. Free-form tags, canonicalized on write and echoed back in canonical form — the response will NOT match your input verbatim. Each tag is lower-cased, stripped of diacritics, has every run of non-alphanumerics replaced with `-`, is trimmed of leading/trailing `-`, and is then truncated to 60 characters. So `"Buying Guide"` is stored and filtered as `buying-guide`. Tags that normalize to nothing (`""`, `"!!"`) are dropped, and duplicates are removed keeping first-occurrence order, so the array you get back may be SHORTER than the one you sent. Note the asymmetry with `maxLength`: an item may be up to 80 characters on input but is truncated to 60 once canonicalized, which can collapse two long tags into one. */
|
|
3921
4005
|
tags?: string[];
|
|
3922
4006
|
};
|
|
3923
4007
|
};
|
|
@@ -3951,6 +4035,7 @@ interface paths {
|
|
|
3951
4035
|
attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
|
|
3952
4036
|
[key: string]: unknown;
|
|
3953
4037
|
};
|
|
4038
|
+
/** @description Tags in canonical form. These are normalized on write (lower-cased, slugified, deduplicated, truncated), so this array will not necessarily match what was submitted — see the `tags` field on the create/update request body for the exact rules. Filter with `?tag=` using either form. */
|
|
3954
4039
|
tags: string[];
|
|
3955
4040
|
/** Format: uuid */
|
|
3956
4041
|
createdBy: string | null;
|
|
@@ -5913,7 +5998,44 @@ interface paths {
|
|
|
5913
5998
|
path?: never;
|
|
5914
5999
|
cookie?: never;
|
|
5915
6000
|
};
|
|
5916
|
-
requestBody
|
|
6001
|
+
requestBody: {
|
|
6002
|
+
content: {
|
|
6003
|
+
"multipart/form-data": {
|
|
6004
|
+
/**
|
|
6005
|
+
* Format: binary
|
|
6006
|
+
* @description The file to upload. Images, video, PDF, Office documents and glTF are accepted; the 422 response lists every allowed type in `details.allowed`. You do NOT have to get the content type right: when you send `application/octet-stream` (or no type at all), the leading bytes are sniffed and the detected type is used — so a PNG whose filename lost its extension uploads fine. SVG, CSV, plain text and Office formats have no distinguishing magic bytes and still need an explicit type. If a specific declared type contradicts the bytes, the bytes win.
|
|
6007
|
+
*/
|
|
6008
|
+
file: string;
|
|
6009
|
+
/**
|
|
6010
|
+
* @description Attach the upload in the same transaction. Requires `entityId`; supplying only one of the pair uploads the file WITHOUT associating it. A value outside the enum is a 422, not a silent miss.
|
|
6011
|
+
* @enum {string}
|
|
6012
|
+
*/
|
|
6013
|
+
entityType?: "product" | "variant" | "content_page";
|
|
6014
|
+
/**
|
|
6015
|
+
* Format: uuid
|
|
6016
|
+
* @description The id of the entity named by `entityType`.
|
|
6017
|
+
*/
|
|
6018
|
+
entityId?: string;
|
|
6019
|
+
/**
|
|
6020
|
+
* @description Association role. Ignored unless `entityType`+`entityId` are present. A value outside this enum is rejected with a 422 that lists the accepted values in `details.accepted`.
|
|
6021
|
+
* @default gallery
|
|
6022
|
+
* @enum {string}
|
|
6023
|
+
*/
|
|
6024
|
+
role?: "hero" | "gallery" | "thumbnail" | "technical" | "lifestyle" | "swatch";
|
|
6025
|
+
/**
|
|
6026
|
+
* @description Sort position within the entity’s gallery. Must be a non-negative integer; anything else is a 422.
|
|
6027
|
+
* @default 0
|
|
6028
|
+
*/
|
|
6029
|
+
position?: number;
|
|
6030
|
+
/**
|
|
6031
|
+
* @description A JSON OBJECT keyed by locale, sent as a STRING — e.g. `{"en_US":"Blue widget on white"}`. Unparseable JSON, or JSON that is not an object of locale → string, does NOT fail the upload: the file is stored, no alt text is saved, and the 201 response carries a `warnings` entry saying so. Check `warnings` if you send alt text programmatically. Omit the field entirely if you have none.
|
|
6032
|
+
*
|
|
6033
|
+
* (0.20.0 briefly made this a 422; 0.21.0 restored the original behaviour and added `warnings` instead, so the problem is reported without breaking callers.)
|
|
6034
|
+
*/
|
|
6035
|
+
altText?: string;
|
|
6036
|
+
};
|
|
6037
|
+
};
|
|
6038
|
+
};
|
|
5917
6039
|
responses: {
|
|
5918
6040
|
/** @description Default Response */
|
|
5919
6041
|
201: {
|
|
@@ -5966,6 +6088,8 @@ interface paths {
|
|
|
5966
6088
|
channelId: string | null;
|
|
5967
6089
|
};
|
|
5968
6090
|
url: string;
|
|
6091
|
+
/** @description Non-fatal problems with this upload — currently only malformed `altText`. The upload succeeded; something you sent was ignored. Absent when there is nothing to report. */
|
|
6092
|
+
warnings?: string[];
|
|
5969
6093
|
};
|
|
5970
6094
|
};
|
|
5971
6095
|
};
|
|
@@ -5985,6 +6109,36 @@ interface paths {
|
|
|
5985
6109
|
};
|
|
5986
6110
|
};
|
|
5987
6111
|
/** @description Default Response */
|
|
6112
|
+
413: {
|
|
6113
|
+
headers: {
|
|
6114
|
+
[name: string]: unknown;
|
|
6115
|
+
};
|
|
6116
|
+
content: {
|
|
6117
|
+
"application/json": {
|
|
6118
|
+
error: {
|
|
6119
|
+
code: string;
|
|
6120
|
+
message: string;
|
|
6121
|
+
details?: unknown;
|
|
6122
|
+
};
|
|
6123
|
+
};
|
|
6124
|
+
};
|
|
6125
|
+
};
|
|
6126
|
+
/** @description Default Response */
|
|
6127
|
+
422: {
|
|
6128
|
+
headers: {
|
|
6129
|
+
[name: string]: unknown;
|
|
6130
|
+
};
|
|
6131
|
+
content: {
|
|
6132
|
+
"application/json": {
|
|
6133
|
+
error: {
|
|
6134
|
+
code: string;
|
|
6135
|
+
message: string;
|
|
6136
|
+
details?: unknown;
|
|
6137
|
+
};
|
|
6138
|
+
};
|
|
6139
|
+
};
|
|
6140
|
+
};
|
|
6141
|
+
/** @description Default Response */
|
|
5988
6142
|
503: {
|
|
5989
6143
|
headers: {
|
|
5990
6144
|
[name: string]: unknown;
|
|
@@ -7471,7 +7625,7 @@ interface paths {
|
|
|
7471
7625
|
availability: "oss" | "hosted";
|
|
7472
7626
|
capabilities: {
|
|
7473
7627
|
/** @enum {string} */
|
|
7474
|
-
entity: "product" | "variant" | "media" | "category";
|
|
7628
|
+
entity: "product" | "variant" | "media" | "category" | "content_page";
|
|
7475
7629
|
/** @enum {string} */
|
|
7476
7630
|
direction: "push" | "pull" | "bidirectional";
|
|
7477
7631
|
}[];
|
|
@@ -8934,11 +9088,12 @@ interface paths {
|
|
|
8934
9088
|
}) | null;
|
|
8935
9089
|
/** Format: date-time */
|
|
8936
9090
|
createdAt: string;
|
|
9091
|
+
/** @description Display name for the actor: the user’s name or email for `user` rows, the connector’s name for `connector` rows, null when the actor is unattributed (`system`) or no longer resolvable. */
|
|
9092
|
+
actorLabel: string | null;
|
|
8937
9093
|
}[];
|
|
8938
9094
|
limit: number;
|
|
8939
9095
|
offset: number;
|
|
8940
|
-
hasMore
|
|
8941
|
-
total?: number;
|
|
9096
|
+
hasMore: boolean;
|
|
8942
9097
|
};
|
|
8943
9098
|
};
|
|
8944
9099
|
};
|