partnermax 0.2.0 → 0.2.2

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.
Files changed (179) hide show
  1. package/CHANGELOG.md +75 -47
  2. package/LICENSE +201 -201
  3. package/README.md +394 -370
  4. package/api-promise.js +1 -1
  5. package/client.d.mts +9 -3
  6. package/client.d.mts.map +1 -1
  7. package/client.d.ts +9 -3
  8. package/client.d.ts.map +1 -1
  9. package/client.js +12 -2
  10. package/client.js.map +1 -1
  11. package/client.mjs +12 -2
  12. package/client.mjs.map +1 -1
  13. package/core/api-promise.js +1 -1
  14. package/core/api-promise.mjs +1 -1
  15. package/core/pagination.d.mts +57 -0
  16. package/core/pagination.d.mts.map +1 -0
  17. package/core/pagination.d.ts +57 -0
  18. package/core/pagination.d.ts.map +1 -0
  19. package/core/pagination.js +108 -0
  20. package/core/pagination.js.map +1 -0
  21. package/core/pagination.mjs +102 -0
  22. package/core/pagination.mjs.map +1 -0
  23. package/error.js +1 -1
  24. package/index.d.mts +1 -0
  25. package/index.d.mts.map +1 -1
  26. package/index.d.ts +1 -0
  27. package/index.d.ts.map +1 -1
  28. package/index.js +3 -1
  29. package/index.js.map +1 -1
  30. package/index.mjs +1 -0
  31. package/index.mjs.map +1 -1
  32. package/internal/tslib.js +17 -17
  33. package/package.json +19 -15
  34. package/pagination.d.mts +3 -0
  35. package/pagination.d.mts.map +1 -0
  36. package/pagination.d.ts +3 -0
  37. package/pagination.d.ts.map +1 -0
  38. package/pagination.js +6 -0
  39. package/pagination.js.map +1 -0
  40. package/pagination.mjs +3 -0
  41. package/pagination.mjs.map +1 -0
  42. package/resource.js +1 -1
  43. package/resources/dealers/dealers.d.mts +7 -71
  44. package/resources/dealers/dealers.d.mts.map +1 -1
  45. package/resources/dealers/dealers.d.ts +7 -71
  46. package/resources/dealers/dealers.d.ts.map +1 -1
  47. package/resources/dealers/dealers.js +3 -16
  48. package/resources/dealers/dealers.js.map +1 -1
  49. package/resources/dealers/dealers.mjs +2 -15
  50. package/resources/dealers/dealers.mjs.map +1 -1
  51. package/resources/dealers/index.d.mts +2 -2
  52. package/resources/dealers/index.d.mts.map +1 -1
  53. package/resources/dealers/index.d.ts +2 -2
  54. package/resources/dealers/index.d.ts.map +1 -1
  55. package/resources/dealers/index.js.map +1 -1
  56. package/resources/dealers/index.mjs.map +1 -1
  57. package/resources/dealers/nlt/index.d.mts +1 -1
  58. package/resources/dealers/nlt/index.d.mts.map +1 -1
  59. package/resources/dealers/nlt/index.d.ts +1 -1
  60. package/resources/dealers/nlt/index.d.ts.map +1 -1
  61. package/resources/dealers/nlt/nlt.d.mts +2 -2
  62. package/resources/dealers/nlt/nlt.d.mts.map +1 -1
  63. package/resources/dealers/nlt/nlt.d.ts +2 -2
  64. package/resources/dealers/nlt/nlt.d.ts.map +1 -1
  65. package/resources/dealers/nlt/nlt.js +1 -1
  66. package/resources/dealers/nlt/offers.d.mts +55 -78
  67. package/resources/dealers/nlt/offers.d.mts.map +1 -1
  68. package/resources/dealers/nlt/offers.d.ts +55 -78
  69. package/resources/dealers/nlt/offers.d.ts.map +1 -1
  70. package/resources/dealers/nlt/offers.js +9 -11
  71. package/resources/dealers/nlt/offers.js.map +1 -1
  72. package/resources/dealers/nlt/offers.mjs +9 -11
  73. package/resources/dealers/nlt/offers.mjs.map +1 -1
  74. package/resources/dealers/nlt-settings.d.mts +24 -64
  75. package/resources/dealers/nlt-settings.d.mts.map +1 -1
  76. package/resources/dealers/nlt-settings.d.ts +24 -64
  77. package/resources/dealers/nlt-settings.d.ts.map +1 -1
  78. package/resources/dealers/nlt-settings.js +4 -13
  79. package/resources/dealers/nlt-settings.js.map +1 -1
  80. package/resources/dealers/nlt-settings.mjs +4 -13
  81. package/resources/dealers/nlt-settings.mjs.map +1 -1
  82. package/resources/dealers/nlt.js +1 -1
  83. package/resources/dealers/vehicles/images.d.mts +3 -2
  84. package/resources/dealers/vehicles/images.d.mts.map +1 -1
  85. package/resources/dealers/vehicles/images.d.ts +3 -2
  86. package/resources/dealers/vehicles/images.d.ts.map +1 -1
  87. package/resources/dealers/vehicles/images.js +3 -2
  88. package/resources/dealers/vehicles/images.js.map +1 -1
  89. package/resources/dealers/vehicles/images.mjs +3 -2
  90. package/resources/dealers/vehicles/images.mjs.map +1 -1
  91. package/resources/dealers/vehicles/index.d.mts +1 -1
  92. package/resources/dealers/vehicles/index.d.mts.map +1 -1
  93. package/resources/dealers/vehicles/index.d.ts +1 -1
  94. package/resources/dealers/vehicles/index.d.ts.map +1 -1
  95. package/resources/dealers/vehicles/index.js.map +1 -1
  96. package/resources/dealers/vehicles/index.mjs.map +1 -1
  97. package/resources/dealers/vehicles/vehicles.d.mts +57 -70
  98. package/resources/dealers/vehicles/vehicles.d.mts.map +1 -1
  99. package/resources/dealers/vehicles/vehicles.d.ts +57 -70
  100. package/resources/dealers/vehicles/vehicles.d.ts.map +1 -1
  101. package/resources/dealers/vehicles/vehicles.js +19 -19
  102. package/resources/dealers/vehicles/vehicles.js.map +1 -1
  103. package/resources/dealers/vehicles/vehicles.mjs +18 -18
  104. package/resources/dealers/vehicles/vehicles.mjs.map +1 -1
  105. package/resources/dealers/vehicles.js +1 -1
  106. package/resources/dealers.js +1 -1
  107. package/resources/index.d.mts +1 -1
  108. package/resources/index.d.mts.map +1 -1
  109. package/resources/index.d.ts +1 -1
  110. package/resources/index.d.ts.map +1 -1
  111. package/resources/index.js.map +1 -1
  112. package/resources/index.mjs.map +1 -1
  113. package/resources/keys.d.mts +7 -6
  114. package/resources/keys.d.mts.map +1 -1
  115. package/resources/keys.d.ts +7 -6
  116. package/resources/keys.d.ts.map +1 -1
  117. package/resources/keys.js +7 -6
  118. package/resources/keys.js.map +1 -1
  119. package/resources/keys.mjs +7 -6
  120. package/resources/keys.mjs.map +1 -1
  121. package/resources.js +1 -1
  122. package/src/api-promise.ts +2 -2
  123. package/src/client.ts +868 -841
  124. package/src/core/README.md +3 -3
  125. package/src/core/api-promise.ts +92 -92
  126. package/src/core/error.ts +130 -130
  127. package/src/core/pagination.ts +170 -0
  128. package/src/core/resource.ts +11 -11
  129. package/src/core/uploads.ts +2 -2
  130. package/src/error.ts +2 -2
  131. package/src/index.ts +23 -22
  132. package/src/internal/README.md +3 -3
  133. package/src/internal/builtin-types.ts +93 -93
  134. package/src/internal/detect-platform.ts +196 -196
  135. package/src/internal/errors.ts +33 -33
  136. package/src/internal/headers.ts +97 -97
  137. package/src/internal/parse.ts +56 -56
  138. package/src/internal/request-options.ts +91 -91
  139. package/src/internal/shim-types.ts +26 -26
  140. package/src/internal/shims.ts +107 -107
  141. package/src/internal/to-file.ts +154 -154
  142. package/src/internal/types.ts +93 -93
  143. package/src/internal/uploads.ts +187 -187
  144. package/src/internal/utils/base64.ts +40 -40
  145. package/src/internal/utils/bytes.ts +32 -32
  146. package/src/internal/utils/env.ts +18 -18
  147. package/src/internal/utils/log.ts +128 -128
  148. package/src/internal/utils/path.ts +88 -88
  149. package/src/internal/utils/query.ts +23 -23
  150. package/src/internal/utils/sleep.ts +3 -3
  151. package/src/internal/utils/uuid.ts +17 -17
  152. package/src/internal/utils/values.ts +105 -105
  153. package/src/internal/utils.ts +9 -9
  154. package/src/lib/.keep +4 -4
  155. package/src/pagination.ts +2 -0
  156. package/src/resource.ts +2 -2
  157. package/src/resources/dealers/dealers.ts +260 -348
  158. package/src/resources/dealers/index.ts +28 -28
  159. package/src/resources/dealers/nlt/index.ts +11 -11
  160. package/src/resources/dealers/nlt/nlt.ts +29 -29
  161. package/src/resources/dealers/nlt/offers.ts +403 -427
  162. package/src/resources/dealers/nlt-settings.ts +229 -269
  163. package/src/resources/dealers/nlt.ts +3 -3
  164. package/src/resources/dealers/vehicles/images.ts +154 -153
  165. package/src/resources/dealers/vehicles/index.ts +26 -25
  166. package/src/resources/dealers/vehicles/vehicles.ts +786 -796
  167. package/src/resources/dealers/vehicles.ts +3 -3
  168. package/src/resources/dealers.ts +3 -3
  169. package/src/resources/index.ts +11 -12
  170. package/src/resources/keys.ts +129 -128
  171. package/src/resources.ts +1 -1
  172. package/src/tsconfig.json +11 -11
  173. package/src/uploads.ts +2 -2
  174. package/src/version.ts +1 -1
  175. package/uploads.js +1 -1
  176. package/version.d.mts +1 -1
  177. package/version.d.ts +1 -1
  178. package/version.js +1 -1
  179. package/version.mjs +1 -1
@@ -1,796 +1,786 @@
1
- // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
-
3
- import { APIResource } from '../../../core/resource';
4
- import * as ImagesAPI from './images';
5
- import {
6
- ImageCreateParams,
7
- ImageDeleteParams,
8
- ImageListParams,
9
- Images,
10
- VehicleImage,
11
- VehicleImageList,
12
- } from './images';
13
- import { APIPromise } from '../../../core/api-promise';
14
- import { buildHeaders } from '../../../internal/headers';
15
- import { RequestOptions } from '../../../internal/request-options';
16
- import { path } from '../../../internal/utils/path';
17
-
18
- /**
19
- * Used-vehicle stock management for partner-owned dealers. The partner uploads each used vehicle by its canonical Motornet UNI code; DealerMAX joins the partner-provided pricing and stock metadata with the catalog master so the resulting listing is immediately indexed by the AI surfaces (MCP server, ChatGPT Custom GPT, NLWeb /ask, and the SEO/JSON-LD layer).
20
- */
21
- export class Vehicles extends APIResource {
22
- images: ImagesAPI.Images = new ImagesAPI.Images(this._client);
23
-
24
- /**
25
- * Provision a new used vehicle in a dealer's stock.
26
- *
27
- * Writes are atomic across `azlease_usatoin` and `azlease_usatoauto` using a
28
- * `SAVEPOINT` so a UNIQUE plate violation rolls back cleanly. On success the
29
- * AI-content worker (:mod:`azurenet-engine.app.jobs.usato_ai_content_worker`)
30
- * picks up the new row within 60 seconds and generates the SEO body + pgvector
31
- * embedding at which point the vehicle becomes discoverable on the cross-network
32
- * MCP / Custom GPT / NLWeb surfaces. The response returns immediately (no
33
- * synchronous wait on the worker).
34
- */
35
- create(dealerID: string, params: VehicleCreateParams, options?: RequestOptions): APIPromise<VehicleDetail> {
36
- const { 'Idempotency-Key': idempotencyKey, ...body } = params;
37
- return this._client.post(path`/v1/dealers/${dealerID}/vehicles`, {
38
- body,
39
- ...options,
40
- headers: buildHeaders([
41
- { ...(idempotencyKey != null ? { 'Idempotency-Key': idempotencyKey } : undefined) },
42
- options?.headers,
43
- ]),
44
- });
45
- }
46
-
47
- /**
48
- * Get Vehicle
49
- */
50
- retrieve(
51
- vehicleID: string,
52
- params: VehicleRetrieveParams,
53
- options?: RequestOptions,
54
- ): APIPromise<VehicleDetail> {
55
- const { dealer_id, ...query } = params;
56
- return this._client.get(path`/v1/dealers/${dealer_id}/vehicles/${vehicleID}`, { query, ...options });
57
- }
58
-
59
- /**
60
- * Partial update of a vehicle.
61
- *
62
- * Splits the inbound body across the two physical tables (`azlease_usatoauto` and
63
- * `azlease_usatoin`) and emits at most one UPDATE per table inside a single
64
- * transaction. Fields not present in the body are not touched.
65
- */
66
- update(
67
- vehicleID: string,
68
- params: VehicleUpdateParams,
69
- options?: RequestOptions,
70
- ): APIPromise<VehicleDetail> {
71
- const { dealer_id, 'Idempotency-Key': idempotencyKey, ...body } = params;
72
- return this._client.patch(path`/v1/dealers/${dealer_id}/vehicles/${vehicleID}`, {
73
- body,
74
- ...options,
75
- headers: buildHeaders([
76
- { ...(idempotencyKey != null ? { 'Idempotency-Key': idempotencyKey } : undefined) },
77
- options?.headers,
78
- ]),
79
- });
80
- }
81
-
82
- /**
83
- * List vehicles in a dealer's stock owned by the calling partner.
84
- *
85
- * Cursor pagination is opaque base64url over the last vehicle UUID. Default sort
86
- * is `i.data_inserimento ASC` so freshly provisioned vehicles surface at the tail.
87
- * Soft-deleted rows are excluded unless `include_deleted=true` is set explicitly —
88
- * this preserves the soft-delete semantic across the API contract.
89
- */
90
- list(
91
- dealerID: string,
92
- query: VehicleListParams | null | undefined = {},
93
- options?: RequestOptions,
94
- ): APIPromise<VehicleList> {
95
- return this._client.get(path`/v1/dealers/${dealerID}/vehicles`, { query, ...options });
96
- }
97
-
98
- /**
99
- * Withdraw a vehicle from sale without deleting the row.
100
- *
101
- * Sets `azlease_usatoin.visibile = FALSE` and stamps `venduto_il = now()`. The
102
- * plate becomes reusable on the network the moment this returns (the
103
- * active-uniqueness check excludes rows where `visibile = FALSE` OR
104
- * `venduto_il IS NOT NULL`).
105
- *
106
- * Soft-delete is the canonical "remove this vehicle from sale" surface. The
107
- * AI-citation consumers (MCP `_tool_search_vehicles`, Custom GPT
108
- * `search_vehicles_network`, NLWeb `/ask`) each filter their own queries on
109
- * `i.visibile = TRUE AND i.venduto_il IS NULL` the shared `v_apimax_listing`
110
- * view itself does not impose that filter, every consumer adds it. The result on
111
- * the partner side is the same: a soft-deleted vehicle disappears from every AI
112
- * surface within the next index cycle.
113
- *
114
- * Returns `409 vehicle_already_deleted` if the row is already soft- deleted — same
115
- * idempotency pattern as the dealers DELETE endpoint.
116
- */
117
- delete(vehicleID: string, params: VehicleDeleteParams, options?: RequestOptions): APIPromise<void> {
118
- const { dealer_id } = params;
119
- return this._client.delete(path`/v1/dealers/${dealer_id}/vehicles/${vehicleID}`, {
120
- ...options,
121
- headers: buildHeaders([{ Accept: '*/*' }, options?.headers]),
122
- });
123
- }
124
-
125
- /**
126
- * Provision up to `BULK_MAX_ROWS` vehicles in a single synchronous call.
127
- *
128
- * Each row is processed inside its own `SAVEPOINT` so a failure on row N
129
- * (validation, plate conflict, motornet not in catalogue, race) is isolated — the
130
- * SAVEPOINT rolls back, the per-row outcome is collected with a structured error
131
- * code, and the loop continues with row N+1.
132
- *
133
- * Successful rows accumulate in the outer transaction and are committed together
134
- * at the end of the request. Failed rows leave no trace in the database.
135
- *
136
- * Returns `207 Multi-Status`. The response carries:
137
- *
138
- * - `total`, `succeeded`, `failed` — aggregate counters for quick branch logic on
139
- * the partner side.
140
- * - `results` — array of per-row outcomes, indexed by the position in the request
141
- * `vehicles[]` array. Successful rows include the full `VehicleDetail`; failed
142
- * rows include `error_code` + `error_message` keyed to the same codes as the
143
- * single-POST surface so the partner reuses one error handler for both paths.
144
- *
145
- * For imports larger than `BULK_MAX_ROWS` (currently 100), the partner is expected
146
- * to chunk the array client-side. A 5 000-vehicle initial migration is 50 calls;
147
- * the partner controls concurrency.
148
- */
149
- bulk(
150
- dealerID: string,
151
- params: VehicleBulkParams,
152
- options?: RequestOptions,
153
- ): APIPromise<BulkCreateVehiclesResponse> {
154
- const { 'Idempotency-Key': idempotencyKey, ...body } = params;
155
- return this._client.post(path`/v1/dealers/${dealerID}/vehicles/bulk`, {
156
- body,
157
- ...options,
158
- headers: buildHeaders([
159
- { ...(idempotencyKey != null ? { 'Idempotency-Key': idempotencyKey } : undefined) },
160
- options?.headers,
161
- ]),
162
- });
163
- }
164
- }
165
-
166
- /**
167
- * AI-generated editorial content for a single vehicle.
168
- *
169
- * Produced asynchronously by the `usato_ai_content_worker` in `azurenet-engine`
170
- * within ~60 seconds of vehicle creation. While the worker is still pending, every
171
- * field is `null`; once the worker completes the row this object carries the full
172
- * editorial set the cross-network AI consumers (MCP, ChatGPT Custom GPT, NLWeb)
173
- * display.
174
- *
175
- * Layered descriptions:
176
- *
177
- * - `tagline` — 8–12 word headline. Use on listing cards / push notifications.
178
- * - `short` — 1–2 sentence summary (≤ 220 chars). Use as the meta description
179
- * fallback.
180
- * - `medium` — paragraph (~400 chars). Use on vehicle-detail SEO blurbs.
181
- * - `long` — full marketing description (1500–3000 chars). Use on detail pages.
182
- * - `highlights` — array of 3–7 selling points. Render as a bullet list above the
183
- * description.
184
- * - `faq` — array of `{question, answer}` objects. Render as accordion / JSON-LD
185
- * `FAQPage`.
186
- * - `seo_title` — 60 chars, `<title>`-ready.
187
- * - `seo_description` — ≤ 160 chars, meta description-ready.
188
- * - `slug` — URL-safe slug used in the canonical URL on the dealer site.
189
- *
190
- * The Italian language is canonical (`lang='it'`). Multi-language is on the
191
- * roadmap; until then the partner gets exactly what the consumer AI surfaces get.
192
- */
193
- export interface AIContent {
194
- /**
195
- * Array of `{question, answer}` objects. Each entry has two string keys; render
196
- * with the partner's own FAQ UI or feed into a `FAQPage` JSON-LD block.
197
- */
198
- faq?: Array<{ [key: string]: string }> | null;
199
-
200
- /**
201
- * UTC timestamp of the most recent AI generation. `null` until the worker first
202
- * processes the vehicle (≤ 60 seconds after vehicle creation).
203
- */
204
- generated_at?: string | null;
205
-
206
- highlights?: Array<string> | null;
207
-
208
- long?: string | null;
209
-
210
- medium?: string | null;
211
-
212
- seo_description?: string | null;
213
-
214
- seo_title?: string | null;
215
-
216
- short?: string | null;
217
-
218
- slug?: string | null;
219
-
220
- tagline?: string | null;
221
- }
222
-
223
- /**
224
- * Response of `POST /v1/dealers/{dealer_id}/vehicles/bulk`.
225
- *
226
- * HTTP status is `207 Multi-Status` (rather than 201) to make partial success
227
- * explicit at the protocol level. The aggregate counters at the top let a partner
228
- * short-circuit when every row succeeded; the `results` array carries per-row
229
- * detail when not.
230
- */
231
- export interface BulkCreateVehiclesResponse {
232
- failed: number;
233
-
234
- results: Array<BulkRowOutcome>;
235
-
236
- succeeded: number;
237
-
238
- /**
239
- * Number of rows in the request body.
240
- */
241
- total: number;
242
- }
243
-
244
- /**
245
- * Per-row result inside `BulkCreateVehiclesResponse`.
246
- *
247
- * On success `vehicle` is populated (full `VehicleDetail`) and
248
- * `error_code`/`error_message` are null. On failure `vehicle` is null and
249
- * `error_code`/`error_message` carry the same code that the corresponding
250
- * single-create POST would have raised (e.g. `motornet_code_not_in_catalogue`,
251
- * `vehicle_plate_already_registered`, `validation_error`).
252
- */
253
- export interface BulkRowOutcome {
254
- /**
255
- * Zero-based index of the row in the request `vehicles[]` array. Stable across
256
- * retries — the partner can correlate failures back to its own batch by this
257
- * index.
258
- */
259
- row_index: number;
260
-
261
- status: 'succeeded' | 'failed';
262
-
263
- error_code?: string | null;
264
-
265
- error_message?: string | null;
266
-
267
- /**
268
- * Full vehicle resource. Returned by `GET /v1/dealers/{id}/vehicles/{id}`,
269
- * `POST /v1/dealers/{id}/vehicles`, and `PATCH /v1/dealers/{id}/vehicles/{id}`.
270
- *
271
- * Carries three layers of information:
272
- *
273
- * - **Partner-supplied** what the partner posted (`plate`, `description`,
274
- * `sale_price_eur`, etc.).
275
- * - **Catalogue-derived** — `technical_details` is the flat `mnet_dettagli_usato`
276
- * dict (Italian column keys: `cilindrata`, `kw`, `hp`, `lunghezza`,
277
- * `consumo_medio`, `emissioni_co2`, etc.). Same shape conventions as
278
- * `NltOfferDetail` per `feedback_partnermax_field_naming_us_english`.
279
- * - **AI-derived** `ai_content` carries the editorial output the cross-network
280
- * consumers display (descriptions, highlights, FAQ, SEO meta). `null` until the
281
- * worker has processed the vehicle.
282
- *
283
- * Fields the partner does NOT see through this surface (because they are
284
- * dealer-internal margin/operations data the partner does not own):
285
- * `cost_price_eur`, `inspection_expiry_date`, `road_tax_expiry_date`,
286
- * `previous_owner_count`, `previous_ownership_transfer_date`, `last_service_*`.
287
- * These exist in the underlying DB tables for the DealerMAX dashboard but are
288
- * intentionally not exposed via the SDK.
289
- */
290
- vehicle?: VehicleDetail | null;
291
- }
292
-
293
- /**
294
- * Full vehicle resource. Returned by `GET /v1/dealers/{id}/vehicles/{id}`,
295
- * `POST /v1/dealers/{id}/vehicles`, and `PATCH /v1/dealers/{id}/vehicles/{id}`.
296
- *
297
- * Carries three layers of information:
298
- *
299
- * - **Partner-supplied** — what the partner posted (`plate`, `description`,
300
- * `sale_price_eur`, etc.).
301
- * - **Catalogue-derived** `technical_details` is the flat `mnet_dettagli_usato`
302
- * dict (Italian column keys: `cilindrata`, `kw`, `hp`, `lunghezza`,
303
- * `consumo_medio`, `emissioni_co2`, etc.). Same shape conventions as
304
- * `NltOfferDetail` per `feedback_partnermax_field_naming_us_english`.
305
- * - **AI-derived** — `ai_content` carries the editorial output the cross-network
306
- * consumers display (descriptions, highlights, FAQ, SEO meta). `null` until the
307
- * worker has processed the vehicle.
308
- *
309
- * Fields the partner does NOT see through this surface (because they are
310
- * dealer-internal margin/operations data the partner does not own):
311
- * `cost_price_eur`, `inspection_expiry_date`, `road_tax_expiry_date`,
312
- * `previous_owner_count`, `previous_ownership_transfer_date`, `last_service_*`.
313
- * These exist in the underlying DB tables for the DealerMAX dashboard but are
314
- * intentionally not exposed via the SDK.
315
- */
316
- export interface VehicleDetail {
317
- certified_km: number;
318
-
319
- created_at: string;
320
-
321
- dealer_id: string;
322
-
323
- description: string;
324
-
325
- extended_warranty_enabled: boolean;
326
-
327
- is_for_sale: boolean;
328
-
329
- is_visible: boolean;
330
-
331
- last_modified_at: string;
332
-
333
- motornet_code: string;
334
-
335
- partner_id: string;
336
-
337
- plate: string;
338
-
339
- registration_year: number;
340
-
341
- sale_price_eur: number;
342
-
343
- vat_displayed: boolean;
344
-
345
- vehicle_damaged: boolean;
346
-
347
- vehicle_id: string;
348
-
349
- /**
350
- * Editorial content generated by the partnermax AI pipeline. `null` immediately
351
- * after `POST` until the worker has produced the row (≤ 60 seconds). Populated for
352
- * the same consumer-AI surfaces (MCP, Custom GPT, NLWeb).
353
- */
354
- ai_content?: AIContent | null;
355
-
356
- alloy_wheel_size?: number | null;
357
-
358
- brand?: string | null;
359
-
360
- color?: string | null;
361
-
362
- extended_warranty_months?: number | null;
363
-
364
- fuel_type?: string | null;
365
-
366
- /**
367
- * Vehicle photos in display order. The first entry is the cover photo
368
- * (`position=1` in the dedicated images endpoint).
369
- */
370
- image_urls?: Array<string>;
371
-
372
- model?: string | null;
373
-
374
- notes?: string | null;
375
-
376
- registration_month?: number | null;
377
-
378
- /**
379
- * Flat dict of every non-null `mnet_dettagli_usato` column for this
380
- * `motornet_code`. Keys stay in Italian because they are raw SQL column names;
381
- * native units preserved (mm, kg, kW, CV, g/km, etc.).
382
- */
383
- technical_details?: { [key: string]: unknown };
384
-
385
- trim?: string | null;
386
-
387
- vin?: string | null;
388
- }
389
-
390
- /**
391
- * Cursor-paginated list of vehicle summaries.
392
- */
393
- export interface VehicleList {
394
- data: Array<VehicleSummary>;
395
-
396
- has_more: boolean;
397
-
398
- next_cursor?: string | null;
399
- }
400
-
401
- /**
402
- * Compact vehicle payload for list endpoints.
403
- *
404
- * Catalogue fields (`brand`, `model`, `trim`, `fuel_type`) are derived from
405
- * `mnet_dettagli` at read time. Italian raw labels are surfaced verbatim — same
406
- * convention as NLT (`apimax`-aligned).
407
- */
408
- export interface VehicleSummary {
409
- certified_km: number;
410
-
411
- created_at: string;
412
-
413
- dealer_id: string;
414
-
415
- is_for_sale: boolean;
416
-
417
- is_visible: boolean;
418
-
419
- motornet_code: string;
420
-
421
- plate: string;
422
-
423
- registration_year: number;
424
-
425
- sale_price_eur: number;
426
-
427
- vehicle_id: string;
428
-
429
- brand?: string | null;
430
-
431
- color?: string | null;
432
-
433
- fuel_type?: string | null;
434
-
435
- model?: string | null;
436
-
437
- trim?: string | null;
438
- }
439
-
440
- export interface VehicleCreateParams {
441
- /**
442
- * Body param: Certified odometer reading at intake, in kilometres.
443
- */
444
- certified_km: number;
445
-
446
- /**
447
- * Body param: Motornet UNI code identifying the exact vehicle configuration. Must
448
- * exist in `mnet_dettagli_usato` at submission time; otherwise the call returns
449
- * 422 `motornet_code_not_in_catalogue`. The partner is expected to source this
450
- * from its own DMS; partnermax does not expose a plate→code lookup.
451
- */
452
- motornet_code: string;
453
-
454
- /**
455
- * Body param: Italian licence plate. Uppercased server-side. UNIQUE across the
456
- * network for active vehicles (`visibile=true AND venduto_il IS NULL`); reusable
457
- * once the previous holder sells/hides the row.
458
- */
459
- plate: string;
460
-
461
- /**
462
- * Body param: Year of first registration. Upper bound is current year + 1.
463
- */
464
- registration_year: number;
465
-
466
- /**
467
- * Body param: Public sale price in EUR. Surfaced on MCP / Custom GPT / NLWeb and
468
- * on the dealer's site JSON-LD `Offer.price`.
469
- */
470
- sale_price_eur: number;
471
-
472
- /**
473
- * Body param
474
- */
475
- alloy_wheel_size?: number | null;
476
-
477
- /**
478
- * Body param
479
- */
480
- color?: string | null;
481
-
482
- /**
483
- * Body param: Partner-supplied long description. Surfaced on the dealer site
484
- * detail page.
485
- */
486
- description?: string;
487
-
488
- /**
489
- * Body param
490
- */
491
- extended_warranty_enabled?: boolean;
492
-
493
- /**
494
- * Body param
495
- */
496
- extended_warranty_months?: number | null;
497
-
498
- /**
499
- * Body param: Maps to `azlease_usatoauto.is_vendita_enabled`. When false the row
500
- * is in stock but not offered for sale.
501
- */
502
- is_for_sale?: boolean;
503
-
504
- /**
505
- * Body param: Soft-publish flag. When false the row exists in stock but is
506
- * excluded from consumer-facing AI surfaces. Maps to `azlease_usatoin.visibile`.
507
- */
508
- is_visible?: boolean;
509
-
510
- /**
511
- * Body param: Free-form short notes; surfaced as
512
- * `mnet_dettagli.precisazioni`-style.
513
- */
514
- notes?: string | null;
515
-
516
- /**
517
- * Body param: Month of registration (1–12).
518
- */
519
- registration_month?: number | null;
520
-
521
- /**
522
- * Body param: If true the public price is displayed VAT-exposed (B2B); otherwise
523
- * VAT-inclusive (B2C).
524
- */
525
- vat_displayed?: boolean;
526
-
527
- /**
528
- * Body param
529
- */
530
- vehicle_damaged?: boolean;
531
-
532
- /**
533
- * Body param: ISO 3779 vehicle identification number. Optional but strongly
534
- * recommended.
535
- */
536
- vin?: string | null;
537
-
538
- /**
539
- * Header param
540
- */
541
- 'Idempotency-Key'?: string;
542
- }
543
-
544
- export interface VehicleRetrieveParams {
545
- /**
546
- * Path param
547
- */
548
- dealer_id: string;
549
-
550
- /**
551
- * Query param: If true, the detail of a soft-deleted vehicle is returned. Default
552
- * false soft-deleted rows return 404 to keep behaviour consistent with the list
553
- * endpoint.
554
- */
555
- include_deleted?: boolean;
556
- }
557
-
558
- export interface VehicleUpdateParams {
559
- /**
560
- * Path param
561
- */
562
- dealer_id: string;
563
-
564
- /**
565
- * Body param
566
- */
567
- alloy_wheel_size?: number | null;
568
-
569
- /**
570
- * Body param
571
- */
572
- certified_km?: number | null;
573
-
574
- /**
575
- * Body param
576
- */
577
- color?: string | null;
578
-
579
- /**
580
- * Body param
581
- */
582
- description?: string | null;
583
-
584
- /**
585
- * Body param
586
- */
587
- extended_warranty_enabled?: boolean | null;
588
-
589
- /**
590
- * Body param
591
- */
592
- extended_warranty_months?: number | null;
593
-
594
- /**
595
- * Body param
596
- */
597
- is_for_sale?: boolean | null;
598
-
599
- /**
600
- * Body param
601
- */
602
- is_visible?: boolean | null;
603
-
604
- /**
605
- * Body param
606
- */
607
- notes?: string | null;
608
-
609
- /**
610
- * Body param
611
- */
612
- registration_month?: number | null;
613
-
614
- /**
615
- * Body param
616
- */
617
- sale_price_eur?: number | null;
618
-
619
- /**
620
- * Body param
621
- */
622
- vat_displayed?: boolean | null;
623
-
624
- /**
625
- * Body param
626
- */
627
- vehicle_damaged?: boolean | null;
628
-
629
- /**
630
- * Header param
631
- */
632
- 'Idempotency-Key'?: string;
633
- }
634
-
635
- export interface VehicleListParams {
636
- cursor?: string | null;
637
-
638
- /**
639
- * If true, soft-deleted rows (`venduto_il` populated) are also returned. Default
640
- * false — listings hide soft-deleted vehicles.
641
- */
642
- include_deleted?: boolean;
643
-
644
- /**
645
- * Filter on the sale flag.
646
- */
647
- is_for_sale?: boolean | null;
648
-
649
- /**
650
- * Filter on the visibility flag.
651
- */
652
- is_visible?: boolean | null;
653
-
654
- limit?: number;
655
- }
656
-
657
- export interface VehicleDeleteParams {
658
- dealer_id: string;
659
- }
660
-
661
- export interface VehicleBulkParams {
662
- /**
663
- * Body param: Array of vehicles to create. Between 1 and 100 rows per call. For
664
- * larger imports, the partner is expected to chunk client-side (e.g. 50 calls of
665
- * 100 rows each for a 5 000-vehicle migration).
666
- */
667
- vehicles: Array<VehicleBulkParams.Vehicle>;
668
-
669
- /**
670
- * Header param
671
- */
672
- 'Idempotency-Key'?: string;
673
- }
674
-
675
- export namespace VehicleBulkParams {
676
- /**
677
- * Request body for vehicle provisioning.
678
- *
679
- * The partner sends a small, vehicle-specific payload. All technical specs (brand,
680
- * model, trim, fuel type, displacement, dimensions, CO2, etc.) are derived
681
- * server-side from `mnet_dettagli` via the `motornet_code` join — the partner
682
- * never types them. This is the same canonical pattern used by NLT offers and
683
- * matches the platform rule `feedback_motornet_authoritative`.
684
- *
685
- * Fields immutable after creation: `motornet_code`, `plate`, `vin`. Other fields
686
- * may be updated via PATCH.
687
- */
688
- export interface Vehicle {
689
- /**
690
- * Certified odometer reading at intake, in kilometres.
691
- */
692
- certified_km: number;
693
-
694
- /**
695
- * Motornet UNI code identifying the exact vehicle configuration. Must exist in
696
- * `mnet_dettagli_usato` at submission time; otherwise the call returns 422
697
- * `motornet_code_not_in_catalogue`. The partner is expected to source this from
698
- * its own DMS; partnermax does not expose a plate→code lookup.
699
- */
700
- motornet_code: string;
701
-
702
- /**
703
- * Italian licence plate. Uppercased server-side. UNIQUE across the network for
704
- * active vehicles (`visibile=true AND venduto_il IS NULL`); reusable once the
705
- * previous holder sells/hides the row.
706
- */
707
- plate: string;
708
-
709
- /**
710
- * Year of first registration. Upper bound is current year + 1.
711
- */
712
- registration_year: number;
713
-
714
- /**
715
- * Public sale price in EUR. Surfaced on MCP / Custom GPT / NLWeb and on the
716
- * dealer's site JSON-LD `Offer.price`.
717
- */
718
- sale_price_eur: number;
719
-
720
- alloy_wheel_size?: number | null;
721
-
722
- color?: string | null;
723
-
724
- /**
725
- * Partner-supplied long description. Surfaced on the dealer site detail page.
726
- */
727
- description?: string;
728
-
729
- extended_warranty_enabled?: boolean;
730
-
731
- extended_warranty_months?: number | null;
732
-
733
- /**
734
- * Maps to `azlease_usatoauto.is_vendita_enabled`. When false the row is in stock
735
- * but not offered for sale.
736
- */
737
- is_for_sale?: boolean;
738
-
739
- /**
740
- * Soft-publish flag. When false the row exists in stock but is excluded from
741
- * consumer-facing AI surfaces. Maps to `azlease_usatoin.visibile`.
742
- */
743
- is_visible?: boolean;
744
-
745
- /**
746
- * Free-form short notes; surfaced as `mnet_dettagli.precisazioni`-style.
747
- */
748
- notes?: string | null;
749
-
750
- /**
751
- * Month of registration (1–12).
752
- */
753
- registration_month?: number | null;
754
-
755
- /**
756
- * If true the public price is displayed VAT-exposed (B2B); otherwise VAT-inclusive
757
- * (B2C).
758
- */
759
- vat_displayed?: boolean;
760
-
761
- vehicle_damaged?: boolean;
762
-
763
- /**
764
- * ISO 3779 vehicle identification number. Optional but strongly recommended.
765
- */
766
- vin?: string | null;
767
- }
768
- }
769
-
770
- Vehicles.Images = Images;
771
-
772
- export declare namespace Vehicles {
773
- export {
774
- type AIContent as AIContent,
775
- type BulkCreateVehiclesResponse as BulkCreateVehiclesResponse,
776
- type BulkRowOutcome as BulkRowOutcome,
777
- type VehicleDetail as VehicleDetail,
778
- type VehicleList as VehicleList,
779
- type VehicleSummary as VehicleSummary,
780
- type VehicleCreateParams as VehicleCreateParams,
781
- type VehicleRetrieveParams as VehicleRetrieveParams,
782
- type VehicleUpdateParams as VehicleUpdateParams,
783
- type VehicleListParams as VehicleListParams,
784
- type VehicleDeleteParams as VehicleDeleteParams,
785
- type VehicleBulkParams as VehicleBulkParams,
786
- };
787
-
788
- export {
789
- Images as Images,
790
- type VehicleImage as VehicleImage,
791
- type VehicleImageList as VehicleImageList,
792
- type ImageCreateParams as ImageCreateParams,
793
- type ImageListParams as ImageListParams,
794
- type ImageDeleteParams as ImageDeleteParams,
795
- };
796
- }
1
+ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ import { APIResource } from '../../../core/resource';
4
+ import * as ImagesAPI from './images';
5
+ import {
6
+ ImageCreateParams,
7
+ ImageDeleteParams,
8
+ ImageListParams,
9
+ Images,
10
+ VehicleImage,
11
+ VehicleImageList,
12
+ } from './images';
13
+ import { APIPromise } from '../../../core/api-promise';
14
+ import { CursorPage, type CursorPageParams, PagePromise } from '../../../core/pagination';
15
+ import { buildHeaders } from '../../../internal/headers';
16
+ import { RequestOptions } from '../../../internal/request-options';
17
+ import { path } from '../../../internal/utils/path';
18
+
19
+ /**
20
+ * Used-vehicle stock management for partner-owned dealers. The partner uploads each used vehicle by its canonical Motornet UNI code; DealerMAX joins the partner-provided pricing and stock metadata with the catalog master so the resulting listing is immediately indexed by the AI surfaces (MCP server, ChatGPT Custom GPT, NLWeb /ask, and the SEO/JSON-LD layer).
21
+ */
22
+ export class Vehicles extends APIResource {
23
+ images: ImagesAPI.Images = new ImagesAPI.Images(this._client);
24
+
25
+ /**
26
+ * Provision a new used vehicle in a dealer's stock.
27
+ *
28
+ * The write is atomic: a plate conflict or catalogue-code error leaves no partial
29
+ * stock record behind. On success the asynchronous AI-content worker picks up the
30
+ * new vehicle within 60 seconds and generates the SEO body plus semantic
31
+ * embedding; at that point the vehicle becomes discoverable on the cross-network
32
+ * MCP / Custom GPT / NLWeb surfaces. The response returns immediately (no
33
+ * synchronous wait on the worker).
34
+ */
35
+ create(dealerID: string, params: VehicleCreateParams, options?: RequestOptions): APIPromise<VehicleDetail> {
36
+ const { 'Idempotency-Key': idempotencyKey, ...body } = params;
37
+ return this._client.post(path`/v1/dealers/${dealerID}/vehicles`, {
38
+ body,
39
+ ...options,
40
+ headers: buildHeaders([
41
+ { ...(idempotencyKey != null ? { 'Idempotency-Key': idempotencyKey } : undefined) },
42
+ options?.headers,
43
+ ]),
44
+ });
45
+ }
46
+
47
+ /**
48
+ * Get Vehicle
49
+ */
50
+ retrieve(
51
+ vehicleID: string,
52
+ params: VehicleRetrieveParams,
53
+ options?: RequestOptions,
54
+ ): APIPromise<VehicleDetail> {
55
+ const { dealer_id, ...query } = params;
56
+ return this._client.get(path`/v1/dealers/${dealer_id}/vehicles/${vehicleID}`, { query, ...options });
57
+ }
58
+
59
+ /**
60
+ * Partial update of a vehicle.
61
+ *
62
+ * Applies the transmitted fields inside a single transaction. Fields not present
63
+ * in the body are not touched; explicit `null` clears only fields that are
64
+ * nullable in the public contract.
65
+ */
66
+ update(
67
+ vehicleID: string,
68
+ params: VehicleUpdateParams,
69
+ options?: RequestOptions,
70
+ ): APIPromise<VehicleDetail> {
71
+ const { dealer_id, 'Idempotency-Key': idempotencyKey, ...body } = params;
72
+ return this._client.patch(path`/v1/dealers/${dealer_id}/vehicles/${vehicleID}`, {
73
+ body,
74
+ ...options,
75
+ headers: buildHeaders([
76
+ { ...(idempotencyKey != null ? { 'Idempotency-Key': idempotencyKey } : undefined) },
77
+ options?.headers,
78
+ ]),
79
+ });
80
+ }
81
+
82
+ /**
83
+ * List vehicles in a dealer's stock owned by the calling partner.
84
+ *
85
+ * Cursor pagination is opaque base64url over the last vehicle UUID. Default sort
86
+ * is `i.data_inserimento ASC` so freshly provisioned vehicles surface at the tail.
87
+ * Soft-deleted rows are excluded unless `include_deleted=true` is set explicitly —
88
+ * this preserves the soft-delete semantic across the API contract.
89
+ */
90
+ list(
91
+ dealerID: string,
92
+ query: VehicleListParams | null | undefined = {},
93
+ options?: RequestOptions,
94
+ ): PagePromise<VehicleSummariesCursorPage, VehicleSummary> {
95
+ return this._client.getAPIList(path`/v1/dealers/${dealerID}/vehicles`, CursorPage<VehicleSummary>, {
96
+ query,
97
+ ...options,
98
+ });
99
+ }
100
+
101
+ /**
102
+ * Withdraw a vehicle from sale without deleting the row.
103
+ *
104
+ * Marks the vehicle as no longer for sale. The plate becomes reusable on the
105
+ * network the moment this returns.
106
+ *
107
+ * Soft-delete is the canonical "remove this vehicle from sale" surface. The
108
+ * AI-citation consumers (MCP `_tool_search_vehicles`, Custom GPT
109
+ * `search_vehicles_network`, NLWeb `/ask`) each filter their own
110
+ * public-availability state. The result on the partner side is the same: a
111
+ * soft-deleted vehicle disappears from every AI surface within the next index
112
+ * cycle.
113
+ *
114
+ * Returns `409 vehicle_already_deleted` if the row is already soft- deleted — same
115
+ * idempotency pattern as the dealers DELETE endpoint.
116
+ */
117
+ delete(vehicleID: string, params: VehicleDeleteParams, options?: RequestOptions): APIPromise<void> {
118
+ const { dealer_id } = params;
119
+ return this._client.delete(path`/v1/dealers/${dealer_id}/vehicles/${vehicleID}`, {
120
+ ...options,
121
+ headers: buildHeaders([{ Accept: '*/*' }, options?.headers]),
122
+ });
123
+ }
124
+
125
+ /**
126
+ * Provision up to `BULK_MAX_ROWS` vehicles in a single synchronous call.
127
+ *
128
+ * Each row is processed inside its own `SAVEPOINT` so a failure on row N
129
+ * (validation, plate conflict, motornet not in catalogue, race) is isolated — the
130
+ * SAVEPOINT rolls back, the per-row outcome is collected with a structured error
131
+ * code, and the loop continues with row N+1.
132
+ *
133
+ * Successful rows accumulate in the outer transaction and are committed together
134
+ * at the end of the request. Failed rows leave no trace in the database.
135
+ *
136
+ * Returns `207 Multi-Status`. The response carries:
137
+ *
138
+ * - `total`, `succeeded`, `failed` — aggregate counters for quick branch logic on
139
+ * the partner side.
140
+ * - `results` — array of per-row outcomes, indexed by the position in the request
141
+ * `vehicles[]` array. Successful rows include the full `VehicleDetail`; failed
142
+ * rows include `error_code` + `error_message` keyed to the same codes as the
143
+ * single-POST surface so the partner reuses one error handler for both paths.
144
+ *
145
+ * For imports larger than `BULK_MAX_ROWS` (currently 100), the partner is expected
146
+ * to chunk the array client-side. A 5 000-vehicle initial migration is 50 calls;
147
+ * the partner controls concurrency.
148
+ */
149
+ bulk(
150
+ dealerID: string,
151
+ params: VehicleBulkParams,
152
+ options?: RequestOptions,
153
+ ): APIPromise<BulkCreateVehiclesResponse> {
154
+ const { 'Idempotency-Key': idempotencyKey, ...body } = params;
155
+ return this._client.post(path`/v1/dealers/${dealerID}/vehicles/bulk`, {
156
+ body,
157
+ ...options,
158
+ headers: buildHeaders([
159
+ { ...(idempotencyKey != null ? { 'Idempotency-Key': idempotencyKey } : undefined) },
160
+ options?.headers,
161
+ ]),
162
+ });
163
+ }
164
+ }
165
+
166
+ export type VehicleSummariesCursorPage = CursorPage<VehicleSummary>;
167
+
168
+ /**
169
+ * AI-generated editorial content for a single vehicle.
170
+ *
171
+ * Produced asynchronously by the `usato_ai_content_worker` in `azurenet-engine`
172
+ * within ~60 seconds of vehicle creation. While the worker is still pending, every
173
+ * field is `null`; once the worker completes the row this object carries the full
174
+ * editorial set the cross-network AI consumers (MCP, ChatGPT Custom GPT, NLWeb)
175
+ * display.
176
+ *
177
+ * Layered descriptions:
178
+ *
179
+ * - `tagline` — 8–12 word headline. Use on listing cards / push notifications.
180
+ * - `short` — 1–2 sentence summary ( 220 chars). Use as the meta description
181
+ * fallback.
182
+ * - `medium` — paragraph (~400 chars). Use on vehicle-detail SEO blurbs.
183
+ * - `long` — full marketing description (1500–3000 chars). Use on detail pages.
184
+ * - `highlights` — array of 3–7 selling points. Render as a bullet list above the
185
+ * description.
186
+ * - `faq` — array of `{question, answer}` objects. Render as accordion / JSON-LD
187
+ * `FAQPage`.
188
+ * - `seo_title` — 60 chars, `<title>`-ready.
189
+ * - `seo_description` — ≤ 160 chars, meta description-ready.
190
+ * - `slug` URL-safe slug used in the canonical URL on the dealer site.
191
+ *
192
+ * The Italian language is canonical (`lang='it'`). Multi-language is on the
193
+ * roadmap; until then the partner gets exactly what the consumer AI surfaces get.
194
+ */
195
+ export interface AIContent {
196
+ /**
197
+ * Array of `{question, answer}` objects. Each entry has two string keys; render
198
+ * with the partner's own FAQ UI or feed into a `FAQPage` JSON-LD block.
199
+ */
200
+ faq?: Array<{ [key: string]: string }> | null;
201
+
202
+ /**
203
+ * UTC timestamp of the most recent AI generation. `null` until the worker first
204
+ * processes the vehicle (≤ 60 seconds after vehicle creation).
205
+ */
206
+ generated_at?: string | null;
207
+
208
+ highlights?: Array<string> | null;
209
+
210
+ long?: string | null;
211
+
212
+ medium?: string | null;
213
+
214
+ seo_description?: string | null;
215
+
216
+ seo_title?: string | null;
217
+
218
+ short?: string | null;
219
+
220
+ slug?: string | null;
221
+
222
+ tagline?: string | null;
223
+ }
224
+
225
+ /**
226
+ * Response of `POST /v1/dealers/{dealer_id}/vehicles/bulk`.
227
+ *
228
+ * HTTP status is `207 Multi-Status` (rather than 201) to make partial success
229
+ * explicit at the protocol level. The aggregate counters at the top let a partner
230
+ * short-circuit when every row succeeded; the `results` array carries per-row
231
+ * detail when not.
232
+ */
233
+ export interface BulkCreateVehiclesResponse {
234
+ failed: number;
235
+
236
+ results: Array<BulkRowOutcome>;
237
+
238
+ succeeded: number;
239
+
240
+ /**
241
+ * Number of rows in the request body.
242
+ */
243
+ total: number;
244
+ }
245
+
246
+ /**
247
+ * Per-row result inside `BulkCreateVehiclesResponse`.
248
+ *
249
+ * On success `vehicle` is populated (full `VehicleDetail`) and
250
+ * `error_code`/`error_message` are null. On failure `vehicle` is null and
251
+ * `error_code`/`error_message` carry the same code that the corresponding
252
+ * single-create POST would have raised (e.g. `motornet_code_not_in_catalogue`,
253
+ * `vehicle_plate_already_registered`, `validation_error`).
254
+ */
255
+ export interface BulkRowOutcome {
256
+ /**
257
+ * Zero-based index of the row in the request `vehicles[]` array. Stable across
258
+ * retries — the partner can correlate failures back to its own batch by this
259
+ * index.
260
+ */
261
+ row_index: number;
262
+
263
+ status: 'succeeded' | 'failed';
264
+
265
+ error_code?: string | null;
266
+
267
+ error_message?: string | null;
268
+
269
+ /**
270
+ * Full vehicle resource. Returned by `GET /v1/dealers/{id}/vehicles/{id}`,
271
+ * `POST /v1/dealers/{id}/vehicles`, and `PATCH /v1/dealers/{id}/vehicles/{id}`.
272
+ *
273
+ * Carries three layers of information:
274
+ *
275
+ * - **Partner-supplied** — what the partner posted (`plate`, `description`,
276
+ * `sale_price_eur`, etc.).
277
+ * - **Catalogue-derived** — `technical_details` is a flat dictionary of
278
+ * Motornet-backed technical attributes using Italian domain labels such as
279
+ * `cilindrata`, `kw`, `hp`, `lunghezza`, `consumo_medio`, and `emissioni_co2`.
280
+ * - **AI-derived** `ai_content` carries the editorial output the cross-network
281
+ * consumers display (descriptions, highlights, FAQ, SEO meta). `null` until the
282
+ * worker has processed the vehicle.
283
+ *
284
+ * Dealer-internal margin and operations data remains outside this SDK surface;
285
+ * partners receive only the inventory, commercial, catalogue, media, and
286
+ * AI-derived fields needed to publish the vehicle.
287
+ */
288
+ vehicle?: VehicleDetail | null;
289
+ }
290
+
291
+ /**
292
+ * Full vehicle resource. Returned by `GET /v1/dealers/{id}/vehicles/{id}`,
293
+ * `POST /v1/dealers/{id}/vehicles`, and `PATCH /v1/dealers/{id}/vehicles/{id}`.
294
+ *
295
+ * Carries three layers of information:
296
+ *
297
+ * - **Partner-supplied** what the partner posted (`plate`, `description`,
298
+ * `sale_price_eur`, etc.).
299
+ * - **Catalogue-derived** — `technical_details` is a flat dictionary of
300
+ * Motornet-backed technical attributes using Italian domain labels such as
301
+ * `cilindrata`, `kw`, `hp`, `lunghezza`, `consumo_medio`, and `emissioni_co2`.
302
+ * - **AI-derived** `ai_content` carries the editorial output the cross-network
303
+ * consumers display (descriptions, highlights, FAQ, SEO meta). `null` until the
304
+ * worker has processed the vehicle.
305
+ *
306
+ * Dealer-internal margin and operations data remains outside this SDK surface;
307
+ * partners receive only the inventory, commercial, catalogue, media, and
308
+ * AI-derived fields needed to publish the vehicle.
309
+ */
310
+ export interface VehicleDetail {
311
+ certified_km: number;
312
+
313
+ created_at: string;
314
+
315
+ dealer_id: string;
316
+
317
+ description: string;
318
+
319
+ extended_warranty_enabled: boolean;
320
+
321
+ is_for_sale: boolean;
322
+
323
+ is_visible: boolean;
324
+
325
+ last_modified_at: string;
326
+
327
+ motornet_code: string;
328
+
329
+ partner_id: string;
330
+
331
+ plate: string;
332
+
333
+ registration_year: number;
334
+
335
+ sale_price_eur: number;
336
+
337
+ vat_displayed: boolean;
338
+
339
+ vehicle_damaged: boolean;
340
+
341
+ vehicle_id: string;
342
+
343
+ /**
344
+ * Editorial content generated by the partnermax AI pipeline. `null` immediately
345
+ * after `POST` until the worker has produced the row (≤ 60 seconds). Populated for
346
+ * the same consumer-AI surfaces (MCP, Custom GPT, NLWeb).
347
+ */
348
+ ai_content?: AIContent | null;
349
+
350
+ alloy_wheel_size?: number | null;
351
+
352
+ brand?: string | null;
353
+
354
+ color?: string | null;
355
+
356
+ extended_warranty_months?: number | null;
357
+
358
+ fuel_type?: string | null;
359
+
360
+ /**
361
+ * Vehicle photos in display order. The first entry is the cover photo
362
+ * (`position=1` in the dedicated images endpoint).
363
+ */
364
+ image_urls?: Array<string>;
365
+
366
+ model?: string | null;
367
+
368
+ notes?: string | null;
369
+
370
+ registration_month?: number | null;
371
+
372
+ /**
373
+ * Flat dictionary of Motornet-backed technical attributes for this
374
+ * `motornet_code`. Keys stay in Italian domain vocabulary; native units are
375
+ * preserved (mm, kg, kW, CV, g/km, etc.).
376
+ */
377
+ technical_details?: { [key: string]: unknown };
378
+
379
+ trim?: string | null;
380
+
381
+ vin?: string | null;
382
+ }
383
+
384
+ /**
385
+ * Cursor-paginated list of vehicle summaries.
386
+ */
387
+ export interface VehicleList {
388
+ data: Array<VehicleSummary>;
389
+
390
+ has_more: boolean;
391
+
392
+ next_cursor?: string | null;
393
+ }
394
+
395
+ /**
396
+ * Compact vehicle payload for list endpoints.
397
+ *
398
+ * Catalogue fields (`brand`, `model`, `trim`, `fuel_type`) are derived from
399
+ * DealerMAX's licensed Motornet-backed catalogue at read time. Italian raw labels
400
+ * are surfaced verbatim so partner clients see the same vocabulary as
401
+ * consumer-facing DealerMAX surfaces.
402
+ */
403
+ export interface VehicleSummary {
404
+ certified_km: number;
405
+
406
+ created_at: string;
407
+
408
+ dealer_id: string;
409
+
410
+ is_for_sale: boolean;
411
+
412
+ is_visible: boolean;
413
+
414
+ motornet_code: string;
415
+
416
+ plate: string;
417
+
418
+ registration_year: number;
419
+
420
+ sale_price_eur: number;
421
+
422
+ vehicle_id: string;
423
+
424
+ brand?: string | null;
425
+
426
+ color?: string | null;
427
+
428
+ fuel_type?: string | null;
429
+
430
+ model?: string | null;
431
+
432
+ trim?: string | null;
433
+ }
434
+
435
+ export interface VehicleCreateParams {
436
+ /**
437
+ * Body param: Certified odometer reading at intake, in kilometres.
438
+ */
439
+ certified_km: number;
440
+
441
+ /**
442
+ * Body param: Motornet UNI code identifying the exact vehicle configuration. Must
443
+ * exist in the used-vehicle catalogue at submission time; otherwise the call
444
+ * returns 422 `motornet_code_not_in_catalogue`. Partners may send a code from
445
+ * their own Motornet agreement or use the paid control-plane targa/VIN resolver
446
+ * before creating the vehicle.
447
+ */
448
+ motornet_code: string;
449
+
450
+ /**
451
+ * Body param: Italian licence plate. Uppercased server-side. UNIQUE across the
452
+ * network for active vehicles; reusable once the previous holder withdraws the
453
+ * vehicle from sale.
454
+ */
455
+ plate: string;
456
+
457
+ /**
458
+ * Body param: Year of first registration. Upper bound is current year + 1.
459
+ */
460
+ registration_year: number;
461
+
462
+ /**
463
+ * Body param: Public sale price in EUR. Surfaced on MCP / Custom GPT / NLWeb and
464
+ * on the dealer's site JSON-LD `Offer.price`.
465
+ */
466
+ sale_price_eur: number;
467
+
468
+ /**
469
+ * Body param
470
+ */
471
+ alloy_wheel_size?: number | null;
472
+
473
+ /**
474
+ * Body param
475
+ */
476
+ color?: string | null;
477
+
478
+ /**
479
+ * Body param: Partner-supplied long description. Surfaced on the dealer site
480
+ * detail page.
481
+ */
482
+ description?: string;
483
+
484
+ /**
485
+ * Body param
486
+ */
487
+ extended_warranty_enabled?: boolean;
488
+
489
+ /**
490
+ * Body param
491
+ */
492
+ extended_warranty_months?: number | null;
493
+
494
+ /**
495
+ * Body param: When false the vehicle remains in stock but is not offered for sale.
496
+ */
497
+ is_for_sale?: boolean;
498
+
499
+ /**
500
+ * Body param: Soft-publish flag. When false the row exists in stock but is
501
+ * excluded from consumer-facing AI surfaces.
502
+ */
503
+ is_visible?: boolean;
504
+
505
+ /**
506
+ * Body param: Free-form short notes for partner-facing vehicle detail views.
507
+ */
508
+ notes?: string | null;
509
+
510
+ /**
511
+ * Body param: Month of registration (1–12).
512
+ */
513
+ registration_month?: number | null;
514
+
515
+ /**
516
+ * Body param: If true the public price is displayed VAT-exposed (B2B); otherwise
517
+ * VAT-inclusive (B2C).
518
+ */
519
+ vat_displayed?: boolean;
520
+
521
+ /**
522
+ * Body param
523
+ */
524
+ vehicle_damaged?: boolean;
525
+
526
+ /**
527
+ * Body param: ISO 3779 vehicle identification number. Optional but strongly
528
+ * recommended.
529
+ */
530
+ vin?: string | null;
531
+
532
+ /**
533
+ * Header param
534
+ */
535
+ 'Idempotency-Key'?: string;
536
+ }
537
+
538
+ export interface VehicleRetrieveParams {
539
+ /**
540
+ * Path param
541
+ */
542
+ dealer_id: string;
543
+
544
+ /**
545
+ * Query param: If true, the detail of a soft-deleted vehicle is returned. Default
546
+ * false — soft-deleted rows return 404 to keep behaviour consistent with the list
547
+ * endpoint.
548
+ */
549
+ include_deleted?: boolean;
550
+ }
551
+
552
+ export interface VehicleUpdateParams {
553
+ /**
554
+ * Path param
555
+ */
556
+ dealer_id: string;
557
+
558
+ /**
559
+ * Body param
560
+ */
561
+ alloy_wheel_size?: number | null;
562
+
563
+ /**
564
+ * Body param
565
+ */
566
+ certified_km?: number | null;
567
+
568
+ /**
569
+ * Body param
570
+ */
571
+ color?: string | null;
572
+
573
+ /**
574
+ * Body param
575
+ */
576
+ description?: string | null;
577
+
578
+ /**
579
+ * Body param
580
+ */
581
+ extended_warranty_enabled?: boolean | null;
582
+
583
+ /**
584
+ * Body param
585
+ */
586
+ extended_warranty_months?: number | null;
587
+
588
+ /**
589
+ * Body param
590
+ */
591
+ is_for_sale?: boolean | null;
592
+
593
+ /**
594
+ * Body param
595
+ */
596
+ is_visible?: boolean | null;
597
+
598
+ /**
599
+ * Body param
600
+ */
601
+ notes?: string | null;
602
+
603
+ /**
604
+ * Body param
605
+ */
606
+ registration_month?: number | null;
607
+
608
+ /**
609
+ * Body param
610
+ */
611
+ sale_price_eur?: number | null;
612
+
613
+ /**
614
+ * Body param
615
+ */
616
+ vat_displayed?: boolean | null;
617
+
618
+ /**
619
+ * Body param
620
+ */
621
+ vehicle_damaged?: boolean | null;
622
+
623
+ /**
624
+ * Header param
625
+ */
626
+ 'Idempotency-Key'?: string;
627
+ }
628
+
629
+ export interface VehicleListParams extends CursorPageParams {
630
+ /**
631
+ * If true, soft-deleted rows (`venduto_il` populated) are also returned. Default
632
+ * false — listings hide soft-deleted vehicles.
633
+ */
634
+ include_deleted?: boolean;
635
+
636
+ /**
637
+ * Filter on the sale flag.
638
+ */
639
+ is_for_sale?: boolean | null;
640
+
641
+ /**
642
+ * Filter on the visibility flag.
643
+ */
644
+ is_visible?: boolean | null;
645
+ }
646
+
647
+ export interface VehicleDeleteParams {
648
+ dealer_id: string;
649
+ }
650
+
651
+ export interface VehicleBulkParams {
652
+ /**
653
+ * Body param: Array of vehicles to create. Between 1 and 100 rows per call. For
654
+ * larger imports, the partner is expected to chunk client-side (e.g. 50 calls of
655
+ * 100 rows each for a 5 000-vehicle migration).
656
+ */
657
+ vehicles: Array<VehicleBulkParams.Vehicle>;
658
+
659
+ /**
660
+ * Header param
661
+ */
662
+ 'Idempotency-Key'?: string;
663
+ }
664
+
665
+ export namespace VehicleBulkParams {
666
+ /**
667
+ * Request body for vehicle provisioning.
668
+ *
669
+ * The partner sends a small, vehicle-specific payload. All technical specs (brand,
670
+ * model, trim, fuel type, displacement, dimensions, CO2, etc.) are derived
671
+ * server-side from DealerMAX's licensed Motornet-backed catalogue — the partner
672
+ * never types them.
673
+ *
674
+ * Fields immutable after creation: `motornet_code`, `plate`, `vin`. Other fields
675
+ * may be updated via PATCH.
676
+ */
677
+ export interface Vehicle {
678
+ /**
679
+ * Certified odometer reading at intake, in kilometres.
680
+ */
681
+ certified_km: number;
682
+
683
+ /**
684
+ * Motornet UNI code identifying the exact vehicle configuration. Must exist in the
685
+ * used-vehicle catalogue at submission time; otherwise the call returns 422
686
+ * `motornet_code_not_in_catalogue`. Partners may send a code from their own
687
+ * Motornet agreement or use the paid control-plane targa/VIN resolver before
688
+ * creating the vehicle.
689
+ */
690
+ motornet_code: string;
691
+
692
+ /**
693
+ * Italian licence plate. Uppercased server-side. UNIQUE across the network for
694
+ * active vehicles; reusable once the previous holder withdraws the vehicle from
695
+ * sale.
696
+ */
697
+ plate: string;
698
+
699
+ /**
700
+ * Year of first registration. Upper bound is current year + 1.
701
+ */
702
+ registration_year: number;
703
+
704
+ /**
705
+ * Public sale price in EUR. Surfaced on MCP / Custom GPT / NLWeb and on the
706
+ * dealer's site JSON-LD `Offer.price`.
707
+ */
708
+ sale_price_eur: number;
709
+
710
+ alloy_wheel_size?: number | null;
711
+
712
+ color?: string | null;
713
+
714
+ /**
715
+ * Partner-supplied long description. Surfaced on the dealer site detail page.
716
+ */
717
+ description?: string;
718
+
719
+ extended_warranty_enabled?: boolean;
720
+
721
+ extended_warranty_months?: number | null;
722
+
723
+ /**
724
+ * When false the vehicle remains in stock but is not offered for sale.
725
+ */
726
+ is_for_sale?: boolean;
727
+
728
+ /**
729
+ * Soft-publish flag. When false the row exists in stock but is excluded from
730
+ * consumer-facing AI surfaces.
731
+ */
732
+ is_visible?: boolean;
733
+
734
+ /**
735
+ * Free-form short notes for partner-facing vehicle detail views.
736
+ */
737
+ notes?: string | null;
738
+
739
+ /**
740
+ * Month of registration (1–12).
741
+ */
742
+ registration_month?: number | null;
743
+
744
+ /**
745
+ * If true the public price is displayed VAT-exposed (B2B); otherwise VAT-inclusive
746
+ * (B2C).
747
+ */
748
+ vat_displayed?: boolean;
749
+
750
+ vehicle_damaged?: boolean;
751
+
752
+ /**
753
+ * ISO 3779 vehicle identification number. Optional but strongly recommended.
754
+ */
755
+ vin?: string | null;
756
+ }
757
+ }
758
+
759
+ Vehicles.Images = Images;
760
+
761
+ export declare namespace Vehicles {
762
+ export {
763
+ type AIContent as AIContent,
764
+ type BulkCreateVehiclesResponse as BulkCreateVehiclesResponse,
765
+ type BulkRowOutcome as BulkRowOutcome,
766
+ type VehicleDetail as VehicleDetail,
767
+ type VehicleList as VehicleList,
768
+ type VehicleSummary as VehicleSummary,
769
+ type VehicleSummariesCursorPage as VehicleSummariesCursorPage,
770
+ type VehicleCreateParams as VehicleCreateParams,
771
+ type VehicleRetrieveParams as VehicleRetrieveParams,
772
+ type VehicleUpdateParams as VehicleUpdateParams,
773
+ type VehicleListParams as VehicleListParams,
774
+ type VehicleDeleteParams as VehicleDeleteParams,
775
+ type VehicleBulkParams as VehicleBulkParams,
776
+ };
777
+
778
+ export {
779
+ Images as Images,
780
+ type VehicleImage as VehicleImage,
781
+ type VehicleImageList as VehicleImageList,
782
+ type ImageCreateParams as ImageCreateParams,
783
+ type ImageListParams as ImageListParams,
784
+ type ImageDeleteParams as ImageDeleteParams,
785
+ };
786
+ }