@minipim/sdk 0.3.1 → 0.4.1

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/dist/openapi.d.ts CHANGED
@@ -143,9 +143,12 @@ interface paths {
143
143
  put?: never;
144
144
  /**
145
145
  * Create an organization (tenant)
146
- * @description Creates a new tenant and adds the authenticated caller as its admin member. Requires an existing auth context (you must already be in *some* org to create another). Blocked entirely in `single` tenant mode — the deployment ships one bootstrap org and that's the entire surface.
146
+ * @description Creates a new tenant. Two callers:
147
147
  *
148
- * TODO: a true "first-org signup" flow needs an auth provider that returns a user identity without an org context. Until then, the bootstrap org seeded at install time is everyone's entry point.
148
+ * - **Self-serve** (a logged-in user already in some org): the caller becomes the new org's admin.
149
+ * - **Service provisioning** (`x-pim-service-key` header): the org is created *on behalf of* the `initialAdmin` (email or userId) — an existing user is seated as admin immediately; a not-yet-registered email gets a pending admin invite that auto-claims on sign-in. This is how the hosted control plane creates client orgs, and how OSS operators script tenant provisioning.
150
+ *
151
+ * Emits `organization.created` on both paths. Blocked entirely in `single` tenant mode — the deployment ships one bootstrap org and that's the entire surface.
149
152
  */
150
153
  post: {
151
154
  parameters: {
@@ -164,6 +167,12 @@ interface paths {
164
167
  default_channel?: string;
165
168
  default_currency?: string;
166
169
  };
170
+ initialAdmin?: {
171
+ /** Format: email */
172
+ email?: string;
173
+ /** Format: uuid */
174
+ userId?: string;
175
+ };
167
176
  };
168
177
  };
169
178
  };
@@ -205,6 +214,21 @@ interface paths {
205
214
  };
206
215
  };
207
216
  /** @description Default Response */
217
+ 404: {
218
+ headers: {
219
+ [name: string]: unknown;
220
+ };
221
+ content: {
222
+ "application/json": {
223
+ error: {
224
+ code: string;
225
+ message: string;
226
+ details?: unknown;
227
+ };
228
+ };
229
+ };
230
+ };
231
+ /** @description Default Response */
208
232
  422: {
209
233
  headers: {
210
234
  [name: string]: unknown;
@@ -364,6 +388,103 @@ interface paths {
364
388
  };
365
389
  trace?: never;
366
390
  };
391
+ "/v1/organizations/{id}": {
392
+ parameters: {
393
+ query?: never;
394
+ header?: never;
395
+ path?: never;
396
+ cookie?: never;
397
+ };
398
+ get?: never;
399
+ put?: never;
400
+ post?: never;
401
+ /**
402
+ * Delete an organization (tenant) — irreversible
403
+ * @description Exports the tenant to storage, emits `organization.deleted`, then hard-cascade-deletes it. The caller must be an `admin` of the target org (the one they are currently in), and `confirm` must equal the org slug. Never calls out to connected platforms: the cascade is DB-local and emits no per-entity events, so no destructive webhooks are sent.
404
+ */
405
+ delete: {
406
+ parameters: {
407
+ query?: never;
408
+ header?: never;
409
+ path: {
410
+ id: string;
411
+ };
412
+ cookie?: never;
413
+ };
414
+ requestBody: {
415
+ content: {
416
+ "application/json": {
417
+ confirm: string;
418
+ };
419
+ };
420
+ };
421
+ responses: {
422
+ /** @description Default Response */
423
+ 200: {
424
+ headers: {
425
+ [name: string]: unknown;
426
+ };
427
+ content: {
428
+ "application/json": {
429
+ exportKey: string;
430
+ deletedCounts: {
431
+ [key: string]: number;
432
+ };
433
+ };
434
+ };
435
+ };
436
+ /** @description Default Response */
437
+ 403: {
438
+ headers: {
439
+ [name: string]: unknown;
440
+ };
441
+ content: {
442
+ "application/json": {
443
+ error: {
444
+ code: string;
445
+ message: string;
446
+ details?: unknown;
447
+ };
448
+ };
449
+ };
450
+ };
451
+ /** @description Default Response */
452
+ 404: {
453
+ headers: {
454
+ [name: string]: unknown;
455
+ };
456
+ content: {
457
+ "application/json": {
458
+ error: {
459
+ code: string;
460
+ message: string;
461
+ details?: unknown;
462
+ };
463
+ };
464
+ };
465
+ };
466
+ /** @description Default Response */
467
+ 422: {
468
+ headers: {
469
+ [name: string]: unknown;
470
+ };
471
+ content: {
472
+ "application/json": {
473
+ error: {
474
+ code: string;
475
+ message: string;
476
+ details?: unknown;
477
+ };
478
+ };
479
+ };
480
+ };
481
+ };
482
+ };
483
+ options?: never;
484
+ head?: never;
485
+ patch?: never;
486
+ trace?: never;
487
+ };
367
488
  "/v1/attribute-groups": {
368
489
  parameters: {
369
490
  query?: never;
@@ -511,7 +632,7 @@ interface paths {
511
632
  [key: string]: unknown;
512
633
  };
513
634
  /** @enum {string} */
514
- type: "text" | "textarea" | "richtext" | "number" | "decimal" | "boolean" | "date" | "datetime" | "select" | "multiselect" | "reference" | "media" | "measurement" | "url" | "email" | "json" | "money" | "tags";
635
+ type: "text" | "textarea" | "richtext" | "number" | "decimal" | "boolean" | "date" | "datetime" | "select" | "multiselect" | "reference" | "media" | "measurement" | "url" | "email" | "json" | "money" | "tags" | "file";
515
636
  /** Format: uuid */
516
637
  groupId: string | null;
517
638
  isLocalizable: boolean;
@@ -552,7 +673,7 @@ interface paths {
552
673
  [key: string]: string;
553
674
  };
554
675
  /** @enum {string} */
555
- type: "text" | "textarea" | "richtext" | "number" | "decimal" | "boolean" | "date" | "datetime" | "select" | "multiselect" | "reference" | "media" | "measurement" | "url" | "email" | "json" | "money" | "tags";
676
+ type: "text" | "textarea" | "richtext" | "number" | "decimal" | "boolean" | "date" | "datetime" | "select" | "multiselect" | "reference" | "media" | "measurement" | "url" | "email" | "json" | "money" | "tags" | "file";
556
677
  /** Format: uuid */
557
678
  groupId?: string | null;
558
679
  /** @default false */
@@ -593,7 +714,7 @@ interface paths {
593
714
  [key: string]: unknown;
594
715
  };
595
716
  /** @enum {string} */
596
- type: "text" | "textarea" | "richtext" | "number" | "decimal" | "boolean" | "date" | "datetime" | "select" | "multiselect" | "reference" | "media" | "measurement" | "url" | "email" | "json" | "money" | "tags";
717
+ type: "text" | "textarea" | "richtext" | "number" | "decimal" | "boolean" | "date" | "datetime" | "select" | "multiselect" | "reference" | "media" | "measurement" | "url" | "email" | "json" | "money" | "tags" | "file";
597
718
  /** Format: uuid */
598
719
  groupId: string | null;
599
720
  isLocalizable: boolean;
@@ -674,7 +795,7 @@ interface paths {
674
795
  [key: string]: unknown;
675
796
  };
676
797
  /** @enum {string} */
677
- type: "text" | "textarea" | "richtext" | "number" | "decimal" | "boolean" | "date" | "datetime" | "select" | "multiselect" | "reference" | "media" | "measurement" | "url" | "email" | "json" | "money" | "tags";
798
+ type: "text" | "textarea" | "richtext" | "number" | "decimal" | "boolean" | "date" | "datetime" | "select" | "multiselect" | "reference" | "media" | "measurement" | "url" | "email" | "json" | "money" | "tags" | "file";
678
799
  /** Format: uuid */
679
800
  groupId: string | null;
680
801
  isLocalizable: boolean;
@@ -770,7 +891,7 @@ interface paths {
770
891
  [key: string]: string;
771
892
  };
772
893
  /** @enum {string} */
773
- type?: "text" | "textarea" | "richtext" | "number" | "decimal" | "boolean" | "date" | "datetime" | "select" | "multiselect" | "reference" | "media" | "measurement" | "url" | "email" | "json" | "money" | "tags";
894
+ type?: "text" | "textarea" | "richtext" | "number" | "decimal" | "boolean" | "date" | "datetime" | "select" | "multiselect" | "reference" | "media" | "measurement" | "url" | "email" | "json" | "money" | "tags" | "file";
774
895
  /** Format: uuid */
775
896
  groupId?: string | null;
776
897
  /** @default false */
@@ -811,7 +932,7 @@ interface paths {
811
932
  [key: string]: unknown;
812
933
  };
813
934
  /** @enum {string} */
814
- type: "text" | "textarea" | "richtext" | "number" | "decimal" | "boolean" | "date" | "datetime" | "select" | "multiselect" | "reference" | "media" | "measurement" | "url" | "email" | "json" | "money" | "tags";
935
+ type: "text" | "textarea" | "richtext" | "number" | "decimal" | "boolean" | "date" | "datetime" | "select" | "multiselect" | "reference" | "media" | "measurement" | "url" | "email" | "json" | "money" | "tags" | "file";
815
936
  /** Format: uuid */
816
937
  groupId: string | null;
817
938
  isLocalizable: boolean;
@@ -1042,10 +1163,140 @@ interface paths {
1042
1163
  };
1043
1164
  put?: never;
1044
1165
  post?: never;
1045
- delete?: never;
1166
+ /**
1167
+ * Delete an attribute family
1168
+ * @description Refuses (409) while any product still uses the family — the FK is ON DELETE RESTRICT. Reassign or delete those products first. Attribute attachments (the join rows) cascade away.
1169
+ */
1170
+ delete: {
1171
+ parameters: {
1172
+ query?: never;
1173
+ header?: never;
1174
+ path: {
1175
+ id: string;
1176
+ };
1177
+ cookie?: never;
1178
+ };
1179
+ requestBody?: never;
1180
+ responses: {
1181
+ /** @description Default Response */
1182
+ 204: {
1183
+ headers: {
1184
+ [name: string]: unknown;
1185
+ };
1186
+ content: {
1187
+ "application/json": "null" | null;
1188
+ };
1189
+ };
1190
+ /** @description Default Response */
1191
+ 404: {
1192
+ headers: {
1193
+ [name: string]: unknown;
1194
+ };
1195
+ content: {
1196
+ "application/json": {
1197
+ error: {
1198
+ code: string;
1199
+ message: string;
1200
+ details?: unknown;
1201
+ };
1202
+ };
1203
+ };
1204
+ };
1205
+ /** @description Default Response */
1206
+ 409: {
1207
+ headers: {
1208
+ [name: string]: unknown;
1209
+ };
1210
+ content: {
1211
+ "application/json": {
1212
+ error: {
1213
+ code: string;
1214
+ message: string;
1215
+ details?: unknown;
1216
+ };
1217
+ };
1218
+ };
1219
+ };
1220
+ };
1221
+ };
1046
1222
  options?: never;
1047
1223
  head?: never;
1048
- patch?: never;
1224
+ /** Update an attribute family (label, description) */
1225
+ patch: {
1226
+ parameters: {
1227
+ query?: never;
1228
+ header?: never;
1229
+ path: {
1230
+ id: string;
1231
+ };
1232
+ cookie?: never;
1233
+ };
1234
+ requestBody: {
1235
+ content: {
1236
+ "application/json": {
1237
+ label?: {
1238
+ [key: string]: string;
1239
+ };
1240
+ description?: string | null;
1241
+ };
1242
+ };
1243
+ };
1244
+ responses: {
1245
+ /** @description Default Response */
1246
+ 200: {
1247
+ headers: {
1248
+ [name: string]: unknown;
1249
+ };
1250
+ content: {
1251
+ "application/json": {
1252
+ /** Format: uuid */
1253
+ id: string;
1254
+ /** Format: uuid */
1255
+ organizationId: string;
1256
+ /** Format: date-time */
1257
+ createdAt: string;
1258
+ /** Format: date-time */
1259
+ updatedAt: string;
1260
+ code: string;
1261
+ label: (string | number | boolean | ("null" | null)) | unknown[] | {
1262
+ [key: string]: unknown;
1263
+ };
1264
+ description: string | null;
1265
+ };
1266
+ };
1267
+ };
1268
+ /** @description Default Response */
1269
+ 404: {
1270
+ headers: {
1271
+ [name: string]: unknown;
1272
+ };
1273
+ content: {
1274
+ "application/json": {
1275
+ error: {
1276
+ code: string;
1277
+ message: string;
1278
+ details?: unknown;
1279
+ };
1280
+ };
1281
+ };
1282
+ };
1283
+ /** @description Default Response */
1284
+ 422: {
1285
+ headers: {
1286
+ [name: string]: unknown;
1287
+ };
1288
+ content: {
1289
+ "application/json": {
1290
+ error: {
1291
+ code: string;
1292
+ message: string;
1293
+ details?: unknown;
1294
+ };
1295
+ };
1296
+ };
1297
+ };
1298
+ };
1299
+ };
1049
1300
  trace?: never;
1050
1301
  };
1051
1302
  "/v1/attribute-families/{id}/attributes": {
@@ -1356,6 +1607,21 @@ interface paths {
1356
1607
  };
1357
1608
  };
1358
1609
  /** @description Default Response */
1610
+ 409: {
1611
+ headers: {
1612
+ [name: string]: unknown;
1613
+ };
1614
+ content: {
1615
+ "application/json": {
1616
+ error: {
1617
+ code: string;
1618
+ message: string;
1619
+ details?: unknown;
1620
+ };
1621
+ };
1622
+ };
1623
+ };
1624
+ /** @description Default Response */
1359
1625
  422: {
1360
1626
  headers: {
1361
1627
  [name: string]: unknown;
@@ -1526,6 +1792,13 @@ interface paths {
1526
1792
  * `(locale, null)` → `(null, channel)` → `(null, null)`. Missing
1527
1793
  * attributes are simply absent from the resolved map (no nulls).
1528
1794
  *
1795
+ * `modifierCount` and `hasRequiredModifiers` summarize the product's
1796
+ * order-line options (engraving, add-ons, print choices, …). A PDP with
1797
+ * `hasRequiredModifiers: true` must not let a customer check out without
1798
+ * resolving them — fetch the full list from
1799
+ * `GET /v1/products/{id}/modifiers`. Modifiers do NOT create SKUs; see
1800
+ * DEVELOPERS.md → "Sellable optionality" for how they relate to variants.
1801
+ *
1529
1802
  * **Example response (with ?locale=en_US&channel=headless-main)**
1530
1803
  * ```json
1531
1804
  * {
@@ -1556,6 +1829,8 @@ interface paths {
1556
1829
  * "role": "hero", "position": 0, "altText": { "en_US": "Front view" }
1557
1830
  * }
1558
1831
  * ],
1832
+ * "modifierCount": 2,
1833
+ * "hasRequiredModifiers": true,
1559
1834
  * "createdAt": "...",
1560
1835
  * "updatedAt": "..."
1561
1836
  * }
@@ -1625,6 +1900,8 @@ interface paths {
1625
1900
  [key: string]: string;
1626
1901
  } | null;
1627
1902
  }[];
1903
+ modifierCount: number;
1904
+ hasRequiredModifiers: boolean;
1628
1905
  resolvedAttributes?: {
1629
1906
  [key: string]: unknown;
1630
1907
  };
@@ -1865,7 +2142,7 @@ interface paths {
1865
2142
  patch?: never;
1866
2143
  trace?: never;
1867
2144
  };
1868
- "/v1/products/bulk": {
2145
+ "/v1/products/{id}/duplicate": {
1869
2146
  parameters: {
1870
2147
  query?: never;
1871
2148
  header?: never;
@@ -1875,7 +2152,108 @@ interface paths {
1875
2152
  get?: never;
1876
2153
  put?: never;
1877
2154
  /**
1878
- * Bulk create products (per-row results)
2155
+ * Duplicate a product
2156
+ * @description Deep-copies a product into a new `draft`: family, attributes, tags, categories, modifiers, media associations, outbound relationships and variants. Identifiers (UPC/GTIN/MPN) are NOT copied — they identify a specific physical product. Slug and variant SKUs are regenerated to stay unique. Emits `product.created`.
2157
+ */
2158
+ post: {
2159
+ parameters: {
2160
+ query?: never;
2161
+ header?: never;
2162
+ path: {
2163
+ id: string;
2164
+ };
2165
+ cookie?: never;
2166
+ };
2167
+ requestBody: {
2168
+ content: {
2169
+ "application/json": unknown | {
2170
+ name?: string;
2171
+ slug?: string;
2172
+ };
2173
+ };
2174
+ };
2175
+ responses: {
2176
+ /** @description Default Response */
2177
+ 201: {
2178
+ headers: {
2179
+ [name: string]: unknown;
2180
+ };
2181
+ content: {
2182
+ "application/json": {
2183
+ /** Format: uuid */
2184
+ id: string;
2185
+ /** Format: uuid */
2186
+ organizationId: string;
2187
+ /** Format: date-time */
2188
+ createdAt: string;
2189
+ /** Format: date-time */
2190
+ updatedAt: string;
2191
+ /** Format: uuid */
2192
+ familyId: string;
2193
+ name: string;
2194
+ slug: string;
2195
+ /** @enum {string} */
2196
+ status: "draft" | "active" | "archived";
2197
+ attributes: (string | number | boolean | ("null" | null)) | unknown[] | {
2198
+ [key: string]: unknown;
2199
+ };
2200
+ tags: string[];
2201
+ /** Format: uuid */
2202
+ createdBy: string | null;
2203
+ /** Format: uuid */
2204
+ updatedBy: string | null;
2205
+ };
2206
+ };
2207
+ };
2208
+ /** @description Default Response */
2209
+ 404: {
2210
+ headers: {
2211
+ [name: string]: unknown;
2212
+ };
2213
+ content: {
2214
+ "application/json": {
2215
+ error: {
2216
+ code: string;
2217
+ message: string;
2218
+ details?: unknown;
2219
+ };
2220
+ };
2221
+ };
2222
+ };
2223
+ /** @description Default Response */
2224
+ 409: {
2225
+ headers: {
2226
+ [name: string]: unknown;
2227
+ };
2228
+ content: {
2229
+ "application/json": {
2230
+ error: {
2231
+ code: string;
2232
+ message: string;
2233
+ details?: unknown;
2234
+ };
2235
+ };
2236
+ };
2237
+ };
2238
+ };
2239
+ };
2240
+ delete?: never;
2241
+ options?: never;
2242
+ head?: never;
2243
+ patch?: never;
2244
+ trace?: never;
2245
+ };
2246
+ "/v1/products/bulk": {
2247
+ parameters: {
2248
+ query?: never;
2249
+ header?: never;
2250
+ path?: never;
2251
+ cookie?: never;
2252
+ };
2253
+ get?: never;
2254
+ put?: never;
2255
+ /**
2256
+ * Bulk create products (per-row results)
1879
2257
  * @description A single failure does not sink the rest of the batch. Each row reports ok/error independently.
1880
2258
  */
1881
2259
  post: {
@@ -3181,7 +3559,47 @@ interface paths {
3181
3559
  get?: never;
3182
3560
  put?: never;
3183
3561
  post?: never;
3184
- delete?: never;
3562
+ /**
3563
+ * Delete a channel (surface)
3564
+ * @description Removes a channel and its per-product publish records (ON DELETE CASCADE). The channel stops appearing as a completeness/readiness surface. Channel-scoped attribute values are stored in the product JSONB (not FKs) and are left untouched — they simply no longer resolve to a live channel. Use this to clear a surface left behind after uninstalling the connector that seeded it (channels are decoupled from connectors by design).
3565
+ */
3566
+ delete: {
3567
+ parameters: {
3568
+ query?: never;
3569
+ header?: never;
3570
+ path: {
3571
+ id: string;
3572
+ };
3573
+ cookie?: never;
3574
+ };
3575
+ requestBody?: never;
3576
+ responses: {
3577
+ /** @description Default Response */
3578
+ 204: {
3579
+ headers: {
3580
+ [name: string]: unknown;
3581
+ };
3582
+ content: {
3583
+ "application/json": "null" | null;
3584
+ };
3585
+ };
3586
+ /** @description Default Response */
3587
+ 404: {
3588
+ headers: {
3589
+ [name: string]: unknown;
3590
+ };
3591
+ content: {
3592
+ "application/json": {
3593
+ error: {
3594
+ code: string;
3595
+ message: string;
3596
+ details?: unknown;
3597
+ };
3598
+ };
3599
+ };
3600
+ };
3601
+ };
3602
+ };
3185
3603
  options?: never;
3186
3604
  head?: never;
3187
3605
  /**
@@ -3377,110 +3795,255 @@ interface paths {
3377
3795
  patch?: never;
3378
3796
  trace?: never;
3379
3797
  };
3380
- "/v1/categories": {
3798
+ "/v1/locales/{id}": {
3381
3799
  parameters: {
3382
3800
  query?: never;
3383
3801
  header?: never;
3384
3802
  path?: never;
3385
3803
  cookie?: never;
3386
3804
  };
3805
+ get?: never;
3806
+ put?: never;
3807
+ post?: never;
3387
3808
  /**
3388
- * List categories
3389
- * @description Returns the full category tree, flat, ordered by
3390
- * `position`. Build the hierarchy client-side by joining on `parentId` —
3391
- * roots have `parentId: null`. `name` is a localized label map keyed by
3392
- * locale code.
3393
- *
3394
- * **Example response**
3395
- * ```json
3396
- * [
3397
- * {
3398
- * "id": "8d2a1f3c-...",
3399
- * "parentId": null,
3400
- * "name": { "en_US": "Banner Stands" },
3401
- * "slug": "banner-stands",
3402
- * "position": 0,
3403
- * "createdAt": "...",
3404
- * "updatedAt": "..."
3405
- * },
3406
- * {
3407
- * "id": "9e3b2c4d-...",
3408
- * "parentId": "8d2a1f3c-...",
3409
- * "name": { "en_US": "24\" - 36\" Banner Stand Displays" },
3410
- * "slug": "24-36-banner-stand-displays",
3411
- * "position": 0,
3412
- * "createdAt": "...",
3413
- * "updatedAt": "..."
3414
- * }
3415
- * ]
3416
- * ```
3417
- *
3418
- * To get a single category's full ancestor path, walk `parentId` upwards
3419
- * client-side, or hit `GET /v1/categories/{id}` which returns the same row
3420
- * shape with the resolved path included in `path`.
3421
- *
3422
- * Returns the full tree by default. `?limit=` / `?offset=` are supported
3423
- * for large taxonomies (ordered by `position`); omit them to get everything.
3809
+ * Delete a locale
3810
+ * @description Refuses to delete the default locale set another default first. Attribute values scoped to this locale are stored in product JSONB (not FKs) and are left untouched; they simply no longer resolve to a live locale.
3424
3811
  */
3425
- get: {
3812
+ delete: {
3426
3813
  parameters: {
3427
- query?: {
3428
- limit?: number;
3429
- offset?: number;
3430
- };
3814
+ query?: never;
3431
3815
  header?: never;
3432
- path?: never;
3816
+ path: {
3817
+ id: string;
3818
+ };
3433
3819
  cookie?: never;
3434
3820
  };
3435
3821
  requestBody?: never;
3436
3822
  responses: {
3437
3823
  /** @description Default Response */
3438
- 200: {
3824
+ 204: {
3825
+ headers: {
3826
+ [name: string]: unknown;
3827
+ };
3828
+ content: {
3829
+ "application/json": "null" | null;
3830
+ };
3831
+ };
3832
+ /** @description Default Response */
3833
+ 404: {
3439
3834
  headers: {
3440
3835
  [name: string]: unknown;
3441
3836
  };
3442
3837
  content: {
3443
3838
  "application/json": {
3444
- /** Format: uuid */
3445
- id: string;
3446
- /** Format: uuid */
3447
- organizationId: string;
3448
- /** Format: date-time */
3449
- createdAt: string;
3450
- /** Format: date-time */
3451
- updatedAt: string;
3452
- /** Format: uuid */
3453
- parentId: string | null;
3454
- name: (string | number | boolean | ("null" | null)) | unknown[] | {
3455
- [key: string]: unknown;
3839
+ error: {
3840
+ code: string;
3841
+ message: string;
3842
+ details?: unknown;
3456
3843
  };
3457
- slug: string;
3458
- position: number;
3459
- /** Format: uuid */
3460
- channelId: string | null;
3461
- }[];
3844
+ };
3845
+ };
3846
+ };
3847
+ /** @description Default Response */
3848
+ 422: {
3849
+ headers: {
3850
+ [name: string]: unknown;
3851
+ };
3852
+ content: {
3853
+ "application/json": {
3854
+ error: {
3855
+ code: string;
3856
+ message: string;
3857
+ details?: unknown;
3858
+ };
3859
+ };
3462
3860
  };
3463
3861
  };
3464
3862
  };
3465
3863
  };
3466
- put?: never;
3467
- /** Create a category */
3468
- post: {
3864
+ options?: never;
3865
+ head?: never;
3866
+ /**
3867
+ * Update a locale (label, default)
3868
+ * @description Setting `isDefault: true` makes this the org’s sole default — every other locale is un-defaulted in the same transaction.
3869
+ */
3870
+ patch: {
3469
3871
  parameters: {
3470
3872
  query?: never;
3471
3873
  header?: never;
3472
- path?: never;
3874
+ path: {
3875
+ id: string;
3876
+ };
3473
3877
  cookie?: never;
3474
3878
  };
3475
3879
  requestBody: {
3476
3880
  content: {
3477
3881
  "application/json": {
3478
- /** Format: uuid */
3479
- parentId?: string | null;
3480
- name: {
3481
- [key: string]: string;
3482
- };
3483
- slug: string;
3882
+ label?: string;
3883
+ isDefault?: boolean;
3884
+ };
3885
+ };
3886
+ };
3887
+ responses: {
3888
+ /** @description Default Response */
3889
+ 200: {
3890
+ headers: {
3891
+ [name: string]: unknown;
3892
+ };
3893
+ content: {
3894
+ "application/json": {
3895
+ /** Format: uuid */
3896
+ id: string;
3897
+ /** Format: uuid */
3898
+ organizationId: string;
3899
+ /** Format: date-time */
3900
+ createdAt: string;
3901
+ /** Format: date-time */
3902
+ updatedAt: string;
3903
+ code: string;
3904
+ label: string;
3905
+ isDefault: boolean;
3906
+ };
3907
+ };
3908
+ };
3909
+ /** @description Default Response */
3910
+ 404: {
3911
+ headers: {
3912
+ [name: string]: unknown;
3913
+ };
3914
+ content: {
3915
+ "application/json": {
3916
+ error: {
3917
+ code: string;
3918
+ message: string;
3919
+ details?: unknown;
3920
+ };
3921
+ };
3922
+ };
3923
+ };
3924
+ /** @description Default Response */
3925
+ 422: {
3926
+ headers: {
3927
+ [name: string]: unknown;
3928
+ };
3929
+ content: {
3930
+ "application/json": {
3931
+ error: {
3932
+ code: string;
3933
+ message: string;
3934
+ details?: unknown;
3935
+ };
3936
+ };
3937
+ };
3938
+ };
3939
+ };
3940
+ };
3941
+ trace?: never;
3942
+ };
3943
+ "/v1/categories": {
3944
+ parameters: {
3945
+ query?: never;
3946
+ header?: never;
3947
+ path?: never;
3948
+ cookie?: never;
3949
+ };
3950
+ /**
3951
+ * List categories
3952
+ * @description Returns the full category tree, flat, ordered by
3953
+ * `position`. Build the hierarchy client-side by joining on `parentId` —
3954
+ * roots have `parentId: null`. `name` is a localized label map keyed by
3955
+ * locale code.
3956
+ *
3957
+ * **Example response**
3958
+ * ```json
3959
+ * [
3960
+ * {
3961
+ * "id": "8d2a1f3c-...",
3962
+ * "parentId": null,
3963
+ * "name": { "en_US": "Banner Stands" },
3964
+ * "slug": "banner-stands",
3965
+ * "position": 0,
3966
+ * "createdAt": "...",
3967
+ * "updatedAt": "..."
3968
+ * },
3969
+ * {
3970
+ * "id": "9e3b2c4d-...",
3971
+ * "parentId": "8d2a1f3c-...",
3972
+ * "name": { "en_US": "24\" - 36\" Banner Stand Displays" },
3973
+ * "slug": "24-36-banner-stand-displays",
3974
+ * "position": 0,
3975
+ * "createdAt": "...",
3976
+ * "updatedAt": "..."
3977
+ * }
3978
+ * ]
3979
+ * ```
3980
+ *
3981
+ * To get a single category's full ancestor path, walk `parentId` upwards
3982
+ * client-side, or hit `GET /v1/categories/{id}` which returns the same row
3983
+ * shape with the resolved path included in `path`.
3984
+ *
3985
+ * Returns the full tree by default. `?limit=` / `?offset=` are supported
3986
+ * for large taxonomies (ordered by `position`); omit them to get everything.
3987
+ */
3988
+ get: {
3989
+ parameters: {
3990
+ query?: {
3991
+ limit?: number;
3992
+ offset?: number;
3993
+ };
3994
+ header?: never;
3995
+ path?: never;
3996
+ cookie?: never;
3997
+ };
3998
+ requestBody?: never;
3999
+ responses: {
4000
+ /** @description Default Response */
4001
+ 200: {
4002
+ headers: {
4003
+ [name: string]: unknown;
4004
+ };
4005
+ content: {
4006
+ "application/json": {
4007
+ /** Format: uuid */
4008
+ id: string;
4009
+ /** Format: uuid */
4010
+ organizationId: string;
4011
+ /** Format: date-time */
4012
+ createdAt: string;
4013
+ /** Format: date-time */
4014
+ updatedAt: string;
4015
+ /** Format: uuid */
4016
+ parentId: string | null;
4017
+ name: (string | number | boolean | ("null" | null)) | unknown[] | {
4018
+ [key: string]: unknown;
4019
+ };
4020
+ slug: string;
4021
+ position: number;
4022
+ /** Format: uuid */
4023
+ channelId: string | null;
4024
+ }[];
4025
+ };
4026
+ };
4027
+ };
4028
+ };
4029
+ put?: never;
4030
+ /** Create a category */
4031
+ post: {
4032
+ parameters: {
4033
+ query?: never;
4034
+ header?: never;
4035
+ path?: never;
4036
+ cookie?: never;
4037
+ };
4038
+ requestBody: {
4039
+ content: {
4040
+ "application/json": {
4041
+ /** Format: uuid */
4042
+ parentId?: string | null;
4043
+ name: {
4044
+ [key: string]: string;
4045
+ };
4046
+ slug: string;
3484
4047
  /** @default 0 */
3485
4048
  position?: number;
3486
4049
  /** Format: uuid */
@@ -4846,7 +5409,7 @@ interface paths {
4846
5409
  };
4847
5410
  trace?: never;
4848
5411
  };
4849
- "/v1/media/{id}": {
5412
+ "/v1/media/associations/reorder": {
4850
5413
  parameters: {
4851
5414
  query?: never;
4852
5415
  header?: never;
@@ -4854,31 +5417,65 @@ interface paths {
4854
5417
  cookie?: never;
4855
5418
  };
4856
5419
  get?: never;
4857
- put?: never;
4858
- post?: never;
4859
- /** Delete media (object + row) */
4860
- delete: {
5420
+ /**
5421
+ * Reorder an entity’s media
5422
+ * @description Sets `position` for every association of the given entity from the order of `orderedIds`. Any `hero` association is pinned to position 0. `orderedIds` must contain exactly the entity’s association ids.
5423
+ */
5424
+ put: {
4861
5425
  parameters: {
4862
5426
  query?: never;
4863
5427
  header?: never;
4864
- path: {
4865
- id: string;
4866
- };
5428
+ path?: never;
4867
5429
  cookie?: never;
4868
5430
  };
4869
- requestBody?: never;
5431
+ requestBody: {
5432
+ content: {
5433
+ "application/json": {
5434
+ /** @enum {string} */
5435
+ entityType: "product" | "variant";
5436
+ /** Format: uuid */
5437
+ entityId: string;
5438
+ orderedIds: string[];
5439
+ };
5440
+ };
5441
+ };
4870
5442
  responses: {
4871
5443
  /** @description Default Response */
4872
- 204: {
5444
+ 200: {
4873
5445
  headers: {
4874
5446
  [name: string]: unknown;
4875
5447
  };
4876
5448
  content: {
4877
- "application/json": "null" | null;
5449
+ "application/json": {
5450
+ data: {
5451
+ /** Format: uuid */
5452
+ id: string;
5453
+ /** Format: uuid */
5454
+ organizationId: string;
5455
+ /** Format: date-time */
5456
+ createdAt: string;
5457
+ /** Format: date-time */
5458
+ updatedAt: string;
5459
+ /** Format: uuid */
5460
+ mediaId: string;
5461
+ /** @enum {string} */
5462
+ entityType: "product" | "variant";
5463
+ /** Format: uuid */
5464
+ entityId: string;
5465
+ /** @enum {string} */
5466
+ role: "hero" | "gallery" | "thumbnail" | "technical" | "lifestyle" | "swatch";
5467
+ position: number;
5468
+ altText: ((string | number | boolean | ("null" | null)) | unknown[] | {
5469
+ [key: string]: unknown;
5470
+ }) | null;
5471
+ /** Format: uuid */
5472
+ channelId: string | null;
5473
+ }[];
5474
+ };
4878
5475
  };
4879
5476
  };
4880
5477
  /** @description Default Response */
4881
- 404: {
5478
+ 422: {
4882
5479
  headers: {
4883
5480
  [name: string]: unknown;
4884
5481
  };
@@ -4894,24 +5491,30 @@ interface paths {
4894
5491
  };
4895
5492
  };
4896
5493
  };
5494
+ post?: never;
5495
+ delete?: never;
4897
5496
  options?: never;
4898
5497
  head?: never;
4899
5498
  patch?: never;
4900
5499
  trace?: never;
4901
5500
  };
4902
- "/v1/me": {
5501
+ "/v1/media/associations/{id}/hero": {
4903
5502
  parameters: {
4904
5503
  query?: never;
4905
5504
  header?: never;
4906
5505
  path?: never;
4907
5506
  cookie?: never;
4908
5507
  };
4909
- /** Identity of the authenticated principal */
4910
- get: {
5508
+ get?: never;
5509
+ put?: never;
5510
+ /** Set an association as the hero (single hero, pinned first) */
5511
+ post: {
4911
5512
  parameters: {
4912
5513
  query?: never;
4913
5514
  header?: never;
4914
- path?: never;
5515
+ path: {
5516
+ id: string;
5517
+ };
4915
5518
  cookie?: never;
4916
5519
  };
4917
5520
  requestBody?: never;
@@ -4923,43 +5526,226 @@ interface paths {
4923
5526
  };
4924
5527
  content: {
4925
5528
  "application/json": {
4926
- user: {
5529
+ data: {
4927
5530
  /** Format: uuid */
4928
5531
  id: string;
4929
- externalProvider: string;
4930
- externalSubject: string;
4931
- email: string | null;
4932
- name: string | null;
4933
- avatarUrl: string | null;
5532
+ /** Format: uuid */
5533
+ organizationId: string;
4934
5534
  /** Format: date-time */
4935
5535
  createdAt: string;
4936
5536
  /** Format: date-time */
4937
5537
  updatedAt: string;
4938
- };
4939
- /** Format: uuid */
4940
- organizationId: string;
4941
- organizationName: string;
4942
- roles: string[];
4943
- source: string;
4944
- deployment: {
5538
+ /** Format: uuid */
5539
+ mediaId: string;
4945
5540
  /** @enum {string} */
4946
- tenantMode: "single" | "multi";
5541
+ entityType: "product" | "variant";
4947
5542
  /** Format: uuid */
4948
- bootstrapOrgId: string;
4949
- };
4950
- };
4951
- };
4952
- };
4953
- };
4954
- };
5543
+ entityId: string;
5544
+ /** @enum {string} */
5545
+ role: "hero" | "gallery" | "thumbnail" | "technical" | "lifestyle" | "swatch";
5546
+ position: number;
5547
+ altText: ((string | number | boolean | ("null" | null)) | unknown[] | {
5548
+ [key: string]: unknown;
5549
+ }) | null;
5550
+ /** Format: uuid */
5551
+ channelId: string | null;
5552
+ }[];
5553
+ };
5554
+ };
5555
+ };
5556
+ /** @description Default Response */
5557
+ 404: {
5558
+ headers: {
5559
+ [name: string]: unknown;
5560
+ };
5561
+ content: {
5562
+ "application/json": {
5563
+ error: {
5564
+ code: string;
5565
+ message: string;
5566
+ details?: unknown;
5567
+ };
5568
+ };
5569
+ };
5570
+ };
5571
+ };
5572
+ };
5573
+ delete?: never;
5574
+ options?: never;
5575
+ head?: never;
5576
+ patch?: never;
5577
+ trace?: never;
5578
+ };
5579
+ "/v1/media/{id}": {
5580
+ parameters: {
5581
+ query?: never;
5582
+ header?: never;
5583
+ path?: never;
5584
+ cookie?: never;
5585
+ };
5586
+ get?: never;
4955
5587
  put?: never;
4956
5588
  post?: never;
4957
- delete?: never;
5589
+ /** Delete media (object + row) */
5590
+ delete: {
5591
+ parameters: {
5592
+ query?: never;
5593
+ header?: never;
5594
+ path: {
5595
+ id: string;
5596
+ };
5597
+ cookie?: never;
5598
+ };
5599
+ requestBody?: never;
5600
+ responses: {
5601
+ /** @description Default Response */
5602
+ 204: {
5603
+ headers: {
5604
+ [name: string]: unknown;
5605
+ };
5606
+ content: {
5607
+ "application/json": "null" | null;
5608
+ };
5609
+ };
5610
+ /** @description Default Response */
5611
+ 404: {
5612
+ headers: {
5613
+ [name: string]: unknown;
5614
+ };
5615
+ content: {
5616
+ "application/json": {
5617
+ error: {
5618
+ code: string;
5619
+ message: string;
5620
+ details?: unknown;
5621
+ };
5622
+ };
5623
+ };
5624
+ };
5625
+ };
5626
+ };
4958
5627
  options?: never;
4959
5628
  head?: never;
4960
5629
  patch?: never;
4961
5630
  trace?: never;
4962
5631
  };
5632
+ "/v1/me": {
5633
+ parameters: {
5634
+ query?: never;
5635
+ header?: never;
5636
+ path?: never;
5637
+ cookie?: never;
5638
+ };
5639
+ /** Identity of the authenticated principal */
5640
+ get: {
5641
+ parameters: {
5642
+ query?: never;
5643
+ header?: never;
5644
+ path?: never;
5645
+ cookie?: never;
5646
+ };
5647
+ requestBody?: never;
5648
+ responses: {
5649
+ /** @description Default Response */
5650
+ 200: {
5651
+ headers: {
5652
+ [name: string]: unknown;
5653
+ };
5654
+ content: {
5655
+ "application/json": {
5656
+ user: {
5657
+ /** Format: uuid */
5658
+ id: string;
5659
+ externalProvider: string;
5660
+ externalSubject: string;
5661
+ email: string | null;
5662
+ name: string | null;
5663
+ avatarUrl: string | null;
5664
+ /** Format: date-time */
5665
+ createdAt: string;
5666
+ /** Format: date-time */
5667
+ updatedAt: string;
5668
+ };
5669
+ /** Format: uuid */
5670
+ organizationId: string | null;
5671
+ organizationName: string | null;
5672
+ roles: string[];
5673
+ source: string;
5674
+ deployment: {
5675
+ /** @enum {string} */
5676
+ tenantMode: "single" | "multi";
5677
+ /** Format: uuid */
5678
+ bootstrapOrgId: string;
5679
+ };
5680
+ };
5681
+ };
5682
+ };
5683
+ };
5684
+ };
5685
+ put?: never;
5686
+ post?: never;
5687
+ delete?: never;
5688
+ options?: never;
5689
+ head?: never;
5690
+ /**
5691
+ * Update the authenticated user's own profile
5692
+ * @description Sets the display name on the MiniPim user row. In hosted (Clerk) mode the IdP can overwrite this on a later sign-in if the session token carries a `name` claim; identity-provided fields win over locally-set ones by design.
5693
+ */
5694
+ patch: {
5695
+ parameters: {
5696
+ query?: never;
5697
+ header?: never;
5698
+ path?: never;
5699
+ cookie?: never;
5700
+ };
5701
+ requestBody: {
5702
+ content: {
5703
+ "application/json": {
5704
+ name: string;
5705
+ };
5706
+ };
5707
+ };
5708
+ responses: {
5709
+ /** @description Default Response */
5710
+ 200: {
5711
+ headers: {
5712
+ [name: string]: unknown;
5713
+ };
5714
+ content: {
5715
+ "application/json": {
5716
+ /** Format: uuid */
5717
+ id: string;
5718
+ externalProvider: string;
5719
+ externalSubject: string;
5720
+ email: string | null;
5721
+ name: string | null;
5722
+ avatarUrl: string | null;
5723
+ /** Format: date-time */
5724
+ createdAt: string;
5725
+ /** Format: date-time */
5726
+ updatedAt: string;
5727
+ };
5728
+ };
5729
+ };
5730
+ /** @description Default Response */
5731
+ 403: {
5732
+ headers: {
5733
+ [name: string]: unknown;
5734
+ };
5735
+ content: {
5736
+ "application/json": {
5737
+ error: {
5738
+ code: string;
5739
+ message: string;
5740
+ details?: unknown;
5741
+ };
5742
+ };
5743
+ };
5744
+ };
5745
+ };
5746
+ };
5747
+ trace?: never;
5748
+ };
4963
5749
  "/v1/me/orgs": {
4964
5750
  parameters: {
4965
5751
  query?: never;
@@ -5058,7 +5844,66 @@ interface paths {
5058
5844
  };
5059
5845
  };
5060
5846
  put?: never;
5061
- post?: never;
5847
+ /**
5848
+ * Add a member by email
5849
+ * @description If the email already has an account, the user is added to the org immediately. Otherwise a pending invitation is created and (in hosted mode) an account invite email is sent.
5850
+ */
5851
+ post: {
5852
+ parameters: {
5853
+ query?: never;
5854
+ header?: never;
5855
+ path?: never;
5856
+ cookie?: never;
5857
+ };
5858
+ requestBody: {
5859
+ content: {
5860
+ "application/json": {
5861
+ /** Format: email */
5862
+ email: string;
5863
+ /**
5864
+ * @default [
5865
+ * "member"
5866
+ * ]
5867
+ */
5868
+ roles?: string[];
5869
+ };
5870
+ };
5871
+ };
5872
+ responses: {
5873
+ /** @description Default Response */
5874
+ 201: {
5875
+ headers: {
5876
+ [name: string]: unknown;
5877
+ };
5878
+ content: {
5879
+ "application/json": {
5880
+ /** @enum {string} */
5881
+ status: "member" | "invited";
5882
+ /** Format: uuid */
5883
+ userId: string | null;
5884
+ /** Format: uuid */
5885
+ invitationId: string | null;
5886
+ link: string | null;
5887
+ };
5888
+ };
5889
+ };
5890
+ /** @description Default Response */
5891
+ 403: {
5892
+ headers: {
5893
+ [name: string]: unknown;
5894
+ };
5895
+ content: {
5896
+ "application/json": {
5897
+ error: {
5898
+ code: string;
5899
+ message: string;
5900
+ details?: unknown;
5901
+ };
5902
+ };
5903
+ };
5904
+ };
5905
+ };
5906
+ };
5062
5907
  delete?: never;
5063
5908
  options?: never;
5064
5909
  head?: never;
@@ -5075,7 +5920,77 @@ interface paths {
5075
5920
  get?: never;
5076
5921
  put?: never;
5077
5922
  post?: never;
5078
- delete?: never;
5923
+ /**
5924
+ * Remove a member from the current organization
5925
+ * @description The `:id` is the member's `user_id`. Deletes the membership row only — the user account and their memberships in other organizations are untouched. The last remaining admin cannot be removed (an org must never end up admin-less); demote/remove another admin first, or delete the organization instead.
5926
+ */
5927
+ delete: {
5928
+ parameters: {
5929
+ query?: never;
5930
+ header?: never;
5931
+ path: {
5932
+ id: string;
5933
+ };
5934
+ cookie?: never;
5935
+ };
5936
+ requestBody?: never;
5937
+ responses: {
5938
+ /** @description Default Response */
5939
+ 204: {
5940
+ headers: {
5941
+ [name: string]: unknown;
5942
+ };
5943
+ content: {
5944
+ "application/json": "null" | null;
5945
+ };
5946
+ };
5947
+ /** @description Default Response */
5948
+ 403: {
5949
+ headers: {
5950
+ [name: string]: unknown;
5951
+ };
5952
+ content: {
5953
+ "application/json": {
5954
+ error: {
5955
+ code: string;
5956
+ message: string;
5957
+ details?: unknown;
5958
+ };
5959
+ };
5960
+ };
5961
+ };
5962
+ /** @description Default Response */
5963
+ 404: {
5964
+ headers: {
5965
+ [name: string]: unknown;
5966
+ };
5967
+ content: {
5968
+ "application/json": {
5969
+ error: {
5970
+ code: string;
5971
+ message: string;
5972
+ details?: unknown;
5973
+ };
5974
+ };
5975
+ };
5976
+ };
5977
+ /** @description Default Response */
5978
+ 409: {
5979
+ headers: {
5980
+ [name: string]: unknown;
5981
+ };
5982
+ content: {
5983
+ "application/json": {
5984
+ error: {
5985
+ code: string;
5986
+ message: string;
5987
+ details?: unknown;
5988
+ };
5989
+ };
5990
+ };
5991
+ };
5992
+ };
5993
+ };
5079
5994
  options?: never;
5080
5995
  head?: never;
5081
5996
  /**
@@ -5146,6 +6061,21 @@ interface paths {
5146
6061
  };
5147
6062
  };
5148
6063
  };
6064
+ /** @description Default Response */
6065
+ 409: {
6066
+ headers: {
6067
+ [name: string]: unknown;
6068
+ };
6069
+ content: {
6070
+ "application/json": {
6071
+ error: {
6072
+ code: string;
6073
+ message: string;
6074
+ details?: unknown;
6075
+ };
6076
+ };
6077
+ };
6078
+ };
5149
6079
  };
5150
6080
  };
5151
6081
  trace?: never;
@@ -5349,7 +6279,7 @@ interface paths {
5349
6279
  put?: never;
5350
6280
  /**
5351
6281
  * Accept an invitation token
5352
- * @description Adds the authenticated user to the invite's organization with the invite's roles. Idempotent: re-accepting from the same user is a no-op.
6282
+ * @description Adds the authenticated user to the invite's organization with the invite's roles. An email-targeted invitation can only be accepted by a user whose verified email matches; an email-less (shareable-link) invitation can be accepted by anyone holding the link. Idempotent: re-accepting from the same user is a no-op.
5353
6283
  */
5354
6284
  post: {
5355
6285
  parameters: {
@@ -5376,6 +6306,21 @@ interface paths {
5376
6306
  };
5377
6307
  };
5378
6308
  /** @description Default Response */
6309
+ 403: {
6310
+ headers: {
6311
+ [name: string]: unknown;
6312
+ };
6313
+ content: {
6314
+ "application/json": {
6315
+ error: {
6316
+ code: string;
6317
+ message: string;
6318
+ details?: unknown;
6319
+ };
6320
+ };
6321
+ };
6322
+ };
6323
+ /** @description Default Response */
5379
6324
  404: {
5380
6325
  headers: {
5381
6326
  [name: string]: unknown;