This commit is contained in:
seb
2026-10-15 20:14:54 +02:00
parent e462a3d250
commit 508e1b6d7a
18 changed files with 859 additions and 333 deletions

View File

@@ -235,8 +235,10 @@ Generated from `@openapi` annotations in [`src/api/routes/`](../../src/api/route
| [`routes/quote/_id/pdf.md`](routes/quote/_id/pdf.md) | `POST /quote/{id}/pdf` |
| [`routes/serper/image.md`](routes/serper/image.md) | `POST /serper/image` |
| [`routes/serper/images.md`](routes/serper/images.md) | `POST /serper/images` |
| [`routes/shipment.md`](routes/shipment.md) | `GET /shipment` |
| [`routes/shipment/_id.delete.md`](routes/shipment/_id.delete.md) | `DELETE /shipment/{id}` |
| [`routes/shipment/_id.get.md`](routes/shipment/_id.get.md) | `GET /shipment/{id}` |
| [`routes/shipment/_id.patch.md`](routes/shipment/_id.patch.md) | `PATCH /shipment/{id}` |
| [`routes/shipment/_id/file/_fileId.delete.md`](routes/shipment/_id/file/_fileId.delete.md) | `DELETE /shipment/{id}/file/{fileId}` |
| [`routes/shipment/_id/file/_fileId.get.md`](routes/shipment/_id/file/_fileId.get.md) | `GET /shipment/{id}/file/{fileId}` |
| [`routes/shipment/_id/pdf.md`](routes/shipment/_id/pdf.md) | `POST /shipment/{id}/pdf` |
@@ -298,11 +300,11 @@ Clients subscribe via [`GET /events`](routes/events.md) (`text/event-stream`). A
| `ledger` | `POST /stock/adjust` |
| `modelconversation` | `POST /modelconversation`, `DELETE /modelconversation/{id}` |
| `modelconversation-<id>` | `POST /modelconversation/{id}/message` |
| `order` | `DELETE /order/{id}/file/{fileId}`, `POST /order/{id}/pdf`, `DELETE /shipment/{id}/file/{fileId}` |
| `order` | `DELETE /order/{id}/file/{fileId}`, `POST /order/{id}/pdf`, `PATCH /shipment/{id}`, `DELETE /shipment/{id}/file/{fileId}` |
| `printer` | `POST /printer`, `PUT /printer/order`, `DELETE /printer/{id}`, `PATCH /printer/{id}`, `PUT /printer/{id}` |
| `propertyname` | `POST /propertyname`, `PUT /propertyname/order`, `DELETE /propertyname/{id}`, `PATCH /propertyname/{id}` |
| `quote` | `DELETE /quote/{id}/file/{fileId}`, `POST /quote/{id}/pdf` |
| `shipment` | `DELETE /shipment/{id}/file/{fileId}`, `POST /shipment/{id}/pdf` |
| `shipment` | `PATCH /shipment/{id}`, `DELETE /shipment/{id}/file/{fileId}`, `POST /shipment/{id}/pdf` |
| `stock` | `POST /stock/adjust` |
| `vfs` | `POST /vfs/mkdir`, `POST /vfs/rename`, `POST /vfs/upload`, `DELETE /vfs/{*path}`, `POST /vfs/{*path}`, `PUT /vfs/{*path}` |
| `warehouse` | `POST /warehouse`, `PUT /warehouse/order`, `DELETE /warehouse/{id}`, `PUT /warehouse/{id}` |

View File

@@ -1,6 +1,6 @@
# Dash API Routes Overview (All)
Overview of all 247 API endpoints across all modules.
Overview of all 249 API endpoints across all modules.
### Notation
@@ -10,61 +10,62 @@ Params: path values first, then `query:` and `body:` (`body?` = optional body).
### Reusable types
- `T1` = `{ order: T2 }`
- `T2` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T29[], externalNumber?: str|null, createdAt?: str, shipping?: T37|null, shippings?: T37[], payment?: T43|null, payments?: T43[], paid?: bool, shipped?: bool, delivered?: bool, orderTotal?: num, paidTotal?: num, orderedQuantity?: num, shippedQuantity?: num, shipments?: T5[], files?: T15[] }`
- `T2` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T30[], externalNumber?: str|null, createdAt?: str, shipping?: T38|null, shippings?: T38[], payment?: T44|null, payments?: T44[], paid?: bool, shipped?: bool, delivered?: bool, orderTotal?: num, paidTotal?: num, orderedQuantity?: num, shippedQuantity?: num, shipments?: T6[], files?: T16[] }`
- `T3` = `{ article: T4 }`
- `T4` = `{ id: int, sku: str, name: str, slug: str, desc: str|null, seo: str|null, track_stock: bool, unitamount: num|null, weight: num|null, unit: T40, brand: T38|null, categoryIds: int[], photos: T35[], eans: str[], prices: T47[], suppliers: T17[] }`
- `T5` = `{ id: int, number: str, type: str, date: str, lines: T29[], shippings: T37[], entityId?: int|null, externalNumber?: str|null, createdAt?: str|null, lineCount?: int, packageCount?: int, files?: T15[] }`
- `T6` = `{ quote: T7 }`
- `T7` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T29[], externalNumber?: str|null, createdAt?: str, positions?: int, grossTotal?: num, totalQuantity?: num, customerName?: str|null, files?: T15[] }`
- `T8` = `{ delivery: T9 }`
- `T9` = `{ id: int, number: str, type: str, supplierId: int|null, date: str, lines: T29[], files: T15[], externalNumber?: str|null, createdAt?: str, ledger?: T51 }`
- `T10` = `{ name: str, path: str, totalSizeBytes: int, timestamp: str|null, manifest?: T11|null }`
- `T11` = `{ id: str, timestamp: str, dateKey: str, monthKey: str, dbProvider: str, files: T18, totalSizeBytes: int, durationMs: int }`
- `T12` = `{ labeltemplate: T14 }`
- `T13` = `{ attachment: T15, fileUrl: str }`
- `T14` = `{ id: int, name: str, width: num, height: num, dpi: int, type: str, content: T25, thumb?: str|null }`
- `T15` = `{ id: int, manifestId: int, fileId: int, sort: int, hash: str, mimetype: str, name: str, size: int, created?: str, modified?: str, skeledash?: str|null, thumbx?: int|null, thumby?: int|null, meta?: { [k]: str }|null }`
- `T16` = `{ id: int, name: str, pairingpin?: str|null, token?: str|null, pairedAt?: str|null, clientserial?: str|null, rootCategoryId?: int|null, syncRootArticles?: bool, lastseenAt?: str|null, updatedAt?: str|null, categoryIds?: int[] }`
- `T17` = `{ id: int, articleId: int, entityId: int, pu: num, sort: int, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T54|null }`
- `T18` = `{ vfs: T52, storage: T52, database: T45 }`
- `T19` = `{ id: int, entityId: int, addressType: str, firstName?: str|null, name?: str|null, street?: str|null, streetNumber?: str|null, zip?: str|null, city?: str|null, county?: str|null }`
- `T20` = `{ ledger: T21[] }`
- `T21` = `{ id: int, manifestarticle_id: int, transaction_type: str, amount: num, transaction_text: str, hash_version: int, prev_hash?: str, sku?: str|null, created_at?: str }`
- `T22` = `{ id: int, name: str, sort: int, exclusive: bool, values: T41[], articleCount?: int }`
- `T23` = `{ id: int, companyuser_id: int, provider: str, model: str, created_at: str, updated_at: str, state: str, started_by?: integer,null, first_message?: string,null }`
- `T24` = `{ id: int, name: str, rootCategoryId: int|null, languageId: int|null, iso639: str|null, taxrate: num, reducedtaxrate: num, taxfreerate: num }`
- `T25` = `{ objects: T30[] }`
- `T4` = `{ id: int, sku: str, name: str, slug: str, desc: str|null, seo: str|null, track_stock: bool, unitamount: num|null, weight: num|null, unit: T41, brand: T39|null, categoryIds: int[], photos: T36[], eans: str[], prices: T48[], suppliers: T18[] }`
- `T5` = `{ shipment: T6 }`
- `T6` = `{ id: int, number: str, type: str, date: str, lines: T30[], shippings: T38[], entityId?: int|null, externalNumber?: str|null, createdAt?: str|null, lineCount?: int, packageCount?: int, files?: T16[], state?: str }`
- `T7` = `{ quote: T8 }`
- `T8` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T30[], externalNumber?: str|null, createdAt?: str, positions?: int, grossTotal?: num, totalQuantity?: num, customerName?: str|null, files?: T16[] }`
- `T9` = `{ delivery: T10 }`
- `T10` = `{ id: int, number: str, type: str, supplierId: int|null, date: str, lines: T30[], files: T16[], externalNumber?: str|null, createdAt?: str, ledger?: T52 }`
- `T11` = `{ name: str, path: str, totalSizeBytes: int, timestamp: str|null, manifest?: T12|null }`
- `T12` = `{ id: str, timestamp: str, dateKey: str, monthKey: str, dbProvider: str, files: T19, totalSizeBytes: int, durationMs: int }`
- `T13` = `{ labeltemplate: T15 }`
- `T14` = `{ attachment: T16, fileUrl: str }`
- `T15` = `{ id: int, name: str, width: num, height: num, dpi: int, type: str, content: T26, thumb?: str|null }`
- `T16` = `{ id: int, manifestId: int, fileId: int, sort: int, hash: str, mimetype: str, name: str, size: int, created?: str, modified?: str, skeledash?: str|null, thumbx?: int|null, thumby?: int|null, meta?: { [k]: str }|null }`
- `T17` = `{ id: int, name: str, pairingpin?: str|null, token?: str|null, pairedAt?: str|null, clientserial?: str|null, rootCategoryId?: int|null, syncRootArticles?: bool, lastseenAt?: str|null, updatedAt?: str|null, categoryIds?: int[] }`
- `T18` = `{ id: int, articleId: int, entityId: int, pu: num, sort: int, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T55|null }`
- `T19` = `{ vfs: T53, storage: T53, database: T46 }`
- `T20` = `{ id: int, entityId: int, addressType: str, firstName?: str|null, name?: str|null, street?: str|null, streetNumber?: str|null, zip?: str|null, city?: str|null, county?: str|null }`
- `T21` = `{ ledger: T22[] }`
- `T22` = `{ id: int, manifestarticle_id: int, transaction_type: str, amount: num, transaction_text: str, hash_version: int, prev_hash?: str, sku?: str|null, created_at?: str }`
- `T23` = `{ id: int, name: str, sort: int, exclusive: bool, values: T42[], articleCount?: int }`
- `T24` = `{ id: int, companyuser_id: int, provider: str, model: str, created_at: str, updated_at: str, state: str, started_by?: integer,null, first_message?: string,null }`
- `T25` = `{ id: int, name: str, rootCategoryId: int|null, languageId: int|null, iso639: str|null, taxrate: num, reducedtaxrate: num, taxfreerate: num }`
- `T26` = `{ objects: T31[] }`
- `T27` = `{ printer: T33 }`
- `T28` = `{ entity: T36 }`
- `T29` = `{ id: int, sku: str|null, name: str|null, pu: num, amount: num, net: num, rebate: num, taxrate: num, comment: str|null }`
- `T30` = `{ id: str, type: str, x: num, y: num, w?: num, h?: num, text?: str, font?: str, fontSize?: num, barcodeFormat?: str }`
- `T27` = `{ objects: T32[] }`
- `T28` = `{ printer: T34 }`
- `T29` = `{ entity: T37 }`
- `T30` = `{ id: int, sku: str|null, name: str|null, pu: num, amount: num, net: num, rebate: num, taxrate: num, comment: str|null }`
- `T31` = `{ id: str, type: str, x: num, y: num, w?: num, h?: num, text?: str, font?: str, fontSize?: num, barcodeFormat?: str }`
- `T32` = `{ shipping: T37 }`
- `T33` = `{ id: int, company_id: int, address: str, type: str, sort: int, model?: str|null, serial?: str|null, desc?: str|null }`
- `T34` = `{ amount: num, net: num, taxrate: num, sku?: str|null, name?: str|null, pu?: num, rebate?: num, comment?: str|null }`
- `T35` = `{ sort: int, fullHash: str, fullW: int, fullH: int, fullSize: int, thumbW: int, thumbH: int, thumbHash: str }`
- `T36` = `{ id: int, customergroupId: int, firstName: str|null, name: str, number: str|null, createdAt: str, updatedAt: str }`
- `T37` = `{ id: int, manifestId: int, number: str, type: str, state: str, trackingCode?: str|null, carrier?: str|null }`
- `T38` = `{ name: str, id?: int|null, fullHash?: str|null, thumbW?: int|null, thumbH?: int|null, thumbHash?: str|null }`
- `T39` = `{ article: T44 }`
- `T40` = `{ si: str, basesi: str, basesifactor: num, symbol?: str|null, name?: str|null }`
- `T41` = `{ id: int, attributeId: int, value: str, sort: int, articleCount?: int }`
- `T42` = `{ id: int, name: str, sort: int, exclusive: bool, articleCount?: int }`
- `T43` = `{ id: int, accountId: int, manifestId: int, type: str, amount: num }`
- `T44` = `{ id: int, categoryId: int, name: str, sku: str, track_stock: bool }`
- `T45` = `{ name: str|null, sizeBytes: int, backedUp: bool, reason?: str|null }`
- `T46` = `{ id: int, email: str, selectedCompanyId: int|null, picture?: str }`
- `T47` = `{ minmultiplier: num, net: num, taxRate: num, customergroupId: int }`
- `T48` = `{ fullHash: str, thumbW: int, thumbH: int, thumbHash: str }`
- `T49` = `{ id: int, entityId: int, contactType: str, contact: str }`
- `T50` = `{ id: int, name: str, createdAt: str, updatedAt: str }`
- `T51` = `{ totalPositions: int, completelyOnLedgerPositions: int }`
- `T52` = `{ name: str, sizeBytes: int, sourceExists: bool }`
- `T53` = `{ warehouse: T55 }`
- `T54` = `{ net: num, taxId: int, taxRate?: num|null }`
- `T55` = `{ id: int, name: str, sort: int }`
- `T56` = `{ id: int, categoryIds: int[] }`
- `T32` = `{ id: str, type: str, x: num, y: num, w?: num, h?: num, text?: str, font?: str, fontSize?: num, barcodeFormat?: str }`
- `T33` = `{ shipping: T38 }`
- `T34` = `{ id: int, company_id: int, address: str, type: str, sort: int, model?: str|null, serial?: str|null, desc?: str|null }`
- `T35` = `{ amount: num, net: num, taxrate: num, sku?: str|null, name?: str|null, pu?: num, rebate?: num, comment?: str|null }`
- `T36` = `{ sort: int, fullHash: str, fullW: int, fullH: int, fullSize: int, thumbW: int, thumbH: int, thumbHash: str }`
- `T37` = `{ id: int, customergroupId: int, firstName: str|null, name: str, number: str|null, createdAt: str, updatedAt: str }`
- `T38` = `{ id: int, manifestId: int, number: str, type: str, state: str, trackingCode?: str|null, carrier?: str|null }`
- `T39` = `{ name: str, id?: int|null, fullHash?: str|null, thumbW?: int|null, thumbH?: int|null, thumbHash?: str|null }`
- `T40` = `{ article: T45 }`
- `T41` = `{ si: str, basesi: str, basesifactor: num, symbol?: str|null, name?: str|null }`
- `T42` = `{ id: int, attributeId: int, value: str, sort: int, articleCount?: int }`
- `T43` = `{ id: int, name: str, sort: int, exclusive: bool, articleCount?: int }`
- `T44` = `{ id: int, accountId: int, manifestId: int, type: str, amount: num }`
- `T45` = `{ id: int, categoryId: int, name: str, sku: str, track_stock: bool }`
- `T46` = `{ name: str|null, sizeBytes: int, backedUp: bool, reason?: str|null }`
- `T47` = `{ id: int, email: str, selectedCompanyId: int|null, picture?: str }`
- `T48` = `{ minmultiplier: num, net: num, taxRate: num, customergroupId: int }`
- `T49` = `{ fullHash: str, thumbW: int, thumbH: int, thumbHash: str }`
- `T50` = `{ id: int, entityId: int, contactType: str, contact: str }`
- `T51` = `{ id: int, name: str, createdAt: str, updatedAt: str }`
- `T52` = `{ totalPositions: int, completelyOnLedgerPositions: int }`
- `T53` = `{ name: str, sizeBytes: int, sourceExists: bool }`
- `T54` = `{ warehouse: T56 }`
- `T55` = `{ net: num, taxId: int, taxRate?: num|null }`
- `T56` = `{ id: int, name: str, sort: int }`
- `T57` = `{ id: int, categoryIds: int[] }`
### Routes
@@ -94,7 +95,7 @@ _none_
#### Create article in category — `POST /article`
- Params: `body: { categoryId: int, name: str, desc?: str, seo?: str, track_stock?: bool }`
- Returns: `201 T39`
- Returns: `201 T40`
#### Export articles as ZIP — `GET /article/export.zip`
- Params: `query: categoryId?: int`
- Returns: `200 zip`
@@ -130,10 +131,10 @@ _none_
- Returns: `200 { children: { id: int, sku: str, name: str, parentsort: int, attributeValueId: int, attributeValue: str }[] }`
#### Create and attach a new child article to a parent article — `POST /article/{sku}/children`
- Params: `sku: str, body: { attributeValueId?: int, value?: str, name?: str }`
- Returns: `201 T39`
- Returns: `201 T40`
#### Attach an existing article as a child to a parent article — `PUT /article/{sku}/children`
- Params: `sku: str, body: { sku: str, attributeValueId?: int, value?: str, reparent?: bool }`
- Returns: `200 { article: T44, children: { id: int, sku: str, name: str, parentsort: int, attributeValueId: int, attributeValue: str }[] }`
- Returns: `200 { article: T45, children: { id: int, sku: str, name: str, parentsort: int, attributeValueId: int, attributeValue: str }[] }`
#### Remove a child article from a parent article — `DELETE /article/{sku}/children/{childSku}`
- Params: `sku: str, childSku: str, query: deleteArticle?: bool`
- Returns: `200 { success: bool, deleted: bool }`
@@ -160,7 +161,7 @@ _none_
- Returns: `200 { options: { id: int, articleId: int, sku: str, name: str, count: int, sort: int, mandated: bool }[] }`
#### Toggle parent mode for an article — `POST /article/{sku}/parent`
- Params: `sku: str, body: { isParent: bool, attributeNameId?: int }`
- Returns: `200 T39`
- Returns: `200 T40`
#### Replace POS prices by SKU (net > gross; price=net, tax=taxRate %) — `PUT /article/{sku}/prices`
- Params: `sku: str, body: { prices: { net?: num, gross?: num, price?: num, taxRate?: num, tax?: num, minmultiplier?: num }[] }`
- Returns: `200 T3`
@@ -178,10 +179,10 @@ _none_
- Returns: `200 { ok: bool }`
#### List article suppliers — `GET /article/{sku}/supplier`
- Params: `sku: str`
- Returns: `200 { suppliers: T17[] }`
- Returns: `200 { suppliers: T18[] }`
#### Assign supplier to article — `POST /article/{sku}/supplier`
- Params: `sku: str, body: { entityId: int, sku?: str|null, pu?: num, stock?: num|null, sort?: int|null, netPrice?: num|null, taxId?: int|null, taxRate?: num|null }`
- Returns: `201 { supplier: T17 }`
- Returns: `201 { supplier: T18 }`
#### Reorder article suppliers — `PUT /article/{sku}/supplier/order`
- Params: `sku: str, body: { ids: int[] }`
- Returns: `200 { ids: int[] }`
@@ -190,7 +191,7 @@ _none_
- Returns: `204 void`
#### Update article supplier assignment — `PATCH /article/{sku}/supplier/{id}`
- Params: `sku: str, id: int, body: { sku?: str|null, pu?: num, stock?: num|null, sort?: int, netPrice?: num|null, taxId?: int|null, taxRate?: num|null }`
- Returns: `200 { supplier: T17 }`
- Returns: `200 { supplier: T18 }`
#### Set article track_stock flag by SKU — `PUT /article/{sku}/track_stock`
- Params: `sku: str, body: { track_stock: bool }`
- Returns: `200 T3`
@@ -202,19 +203,19 @@ _none_
#### List attribute names — `GET /attributename`
_none_
- Returns: `200 { attributenames: T22[] }`
- Returns: `200 { attributenames: T23[] }`
#### Create attribute name — `POST /attributename`
- Params: `body: { name: str, sort?: int, exclusive?: bool }`
- Returns: `201 { attributename: T22 }`
- Returns: `201 { attributename: T23 }`
#### Reorder attribute names — `PUT /attributename/order`
- Params: `body: { attributenameIds: int[] }`
- Returns: `200 { ok: bool }`
#### List values for an attribute — `GET /attributename/{attributeId}/value`
- Params: `attributeId: int`
- Returns: `200 { values: T41[] }`
- Returns: `200 { values: T42[] }`
#### Create value for an attribute — `POST /attributename/{attributeId}/value`
- Params: `attributeId: int, body: { value: str, sort?: int }`
- Returns: `201 { attributevalue: T41 }`
- Returns: `201 { attributevalue: T42 }`
#### Reorder values of an attribute — `PUT /attributename/{attributeId}/value/order`
- Params: `attributeId: int, body: { attributevalueIds: int[] }`
- Returns: `200 { ok: bool }`
@@ -223,7 +224,7 @@ _none_
- Returns: `200 { ok: bool }`
#### Update attribute name — `PATCH /attributename/{id}`
- Params: `id: int, body: { name?: str, sort?: int, exclusive?: bool }`
- Returns: `200 { attributename: T22 }`
- Returns: `200 { attributename: T23 }`
### Section: /attributevalue
@@ -232,34 +233,34 @@ _none_
- Returns: `200 { ok: bool }`
#### Update attribute value — `PATCH /attributevalue/{id}`
- Params: `id: int, body: { value?: str, sort?: int }`
- Returns: `200 { attributevalue: T41 }`
- Returns: `200 { attributevalue: T42 }`
#### Delete attribute value image — `DELETE /attributevalue/{id}/image`
- Params: `id: int`
- Returns: `200 { attributevalue: { id: int, thumbW: int|null, thumbH: int|null, thumbHash: str|null, pics: T48[] } }`
- Returns: `200 { attributevalue: { id: int, thumbW: int|null, thumbH: int|null, thumbHash: str|null, pics: T49[] } }`
#### Add or replace attribute value image — `POST /attributevalue/{id}/image`
- Params: `id: int, image/avif`
- Returns: `201 { attributevalue: { id: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str, pics: T48[] } }`
- Returns: `201 { attributevalue: { id: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str, pics: T49[] } }`
### Section: /auth
#### Login with Google ID token — `POST /auth/login`
- Params: `body: { idToken: str }`
- Returns: `200 { message: str, user: T46 }`
- Returns: `200 { message: str, user: T47 }`
#### Logout — `POST /auth/logout`
_none_
- Returns: `200 { message: str }`
#### Current user — `GET /auth/me`
_none_
- Returns: `200 { user: T46, googleClientId: str }`
- Returns: `200 { user: T47, googleClientId: str }`
#### Set selected company — `PUT /auth/selected-company`
- Params: `body: { companyId: int }`
- Returns: `200 { user: T46 }`
- Returns: `200 { user: T47 }`
### Section: /backup
#### List backups and service status — `GET /backup`
_none_
- Returns: `200 { status: { enabled: bool, isRunning: bool, dbProvider: str, mssqlWarning: bool, backupDir: str, retention: { hourlyMax: int, dailyMax: int, monthly: str }, counts: { hourly: int, daily: int, monthly: int }, latestHourly?: T10|null, latestDaily?: T10|null, latestMonthly?: T10|null }, backups: { counts: { hourly: int, daily: int, monthly: int }, hourly: T10[], daily: T10[], monthly: T10[] } }`
- Returns: `200 { status: { enabled: bool, isRunning: bool, dbProvider: str, mssqlWarning: bool, backupDir: str, retention: { hourlyMax: int, dailyMax: int, monthly: str }, counts: { hourly: int, daily: int, monthly: int }, latestHourly?: T11|null, latestDaily?: T11|null, latestMonthly?: T11|null }, backups: { counts: { hourly: int, daily: int, monthly: int }, hourly: T11[], daily: T11[], monthly: T11[] } }`
#### List VFS files in a backup — `GET /backup/{id}/vfs`
- Params: `id: str, query: companyId?: int`
- Returns: `200 { backupId: str, companyId: int, files: { name: str, size: int, mime: str, mtime: str }[] }`
@@ -274,7 +275,7 @@ _none_
- Returns: `200 { brands: { id: int, name: str, articleCount: int, pics: { fullHash: str, thumbW: int, thumbH: int, thumbHash: str, smallThumbW?: int|null, smallThumbH?: int|null, smallThumbBinary?: str|null }[], gsprpinfo?: str|null }[], total: int, offset: int, limit: int }`
#### Create brand — `POST /brand`
- Params: `body: { name: str, gsprpinfo?: str }`
- Returns: `201 { brand: { id: int, name: str, pics: T48[], gsprpinfo?: str|null } }`
- Returns: `201 { brand: { id: int, name: str, pics: T49[], gsprpinfo?: str|null } }`
#### Delete brand — `DELETE /brand/{id}`
- Params: `id: int`
- Returns: `204 void`
@@ -283,10 +284,10 @@ _none_
- Returns: `200 { brand: { id: int, name: str, touchedArticleCount: int, gsprpinfo?: str|null } }`
#### Delete brand image — `DELETE /brand/{id}/image`
- Params: `id: int`
- Returns: `200 { brand: { id: int, thumbW: int|null, thumbH: int|null, thumbHash: str|null, pics: T48[] } }`
- Returns: `200 { brand: { id: int, thumbW: int|null, thumbH: int|null, thumbHash: str|null, pics: T49[] } }`
#### Add or replace brand image — `POST /brand/{id}/image`
- Params: `id: int, image/avif`
- Returns: `201 { brand: { id: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str, pics: T48[] } }`
- Returns: `201 { brand: { id: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str, pics: T49[] } }`
### Section: /category
@@ -310,7 +311,7 @@ _none_
- Returns: `200 { category: { id: int, name: str, slug: str, parentId: int, sort: int } }`
#### Articles in category — `GET /category/{id}/articles`
- Params: `id: int`
- Returns: `200 { articles: { id: int, sku: str, name: str, slug: str, track_stock: bool, optionsCount: int, articleListCount: int, childCount: int, net?: num|null, taxRate?: num|null, parentArticleId?: int|null, parentSku?: str|null, fullHash?: str|null, thumbW?: int|null, thumbH?: int|null, thumbHash?: str|null, brand?: T38|null }[] }`
- Returns: `200 { articles: { id: int, sku: str, name: str, slug: str, track_stock: bool, optionsCount: int, articleListCount: int, childCount: int, net?: num|null, taxRate?: num|null, parentArticleId?: int|null, parentSku?: str|null, fullHash?: str|null, thumbW?: int|null, thumbH?: int|null, thumbHash?: str|null, brand?: T39|null }[] }`
#### List category attribute values — `GET /category/{id}/attributevalue`
- Params: `id: int`
- Returns: `200 { attributevalues: { id: int, attributeId: int, attributeName: str, attributeValueId: int, value: str, sort: int, categoryId?: int, exclusive?: bool }[] }`
@@ -337,10 +338,10 @@ _none_
#### List companies — `GET /company`
_none_
- Returns: `200 { companies: T24[] }`
- Returns: `200 { companies: T25[] }`
#### Create company — `POST /company`
- Params: `body: { iso639: str, name: str, taxrate: num, reducedtaxrate: num }`
- Returns: `201 { company: T24, user: T46 }`
- Returns: `201 { company: T25, user: T47 }`
#### Export company catalog as zip archive (SSE) — `GET /company/export`
- Params: `query: stream?: str`
- Returns: `200 SSE`
@@ -370,7 +371,7 @@ _none_
- Returns: `204 void`
#### Update company — `PUT /company/{id}`
- Params: `id: int, body: { iso639: str, name: str, taxrate: num, reducedtaxrate: num }`
- Returns: `200 { company: T24 }`
- Returns: `200 { company: T25 }`
### Section: /customergroup
@@ -379,7 +380,7 @@ _none_
- Returns: `200 { customergroups: { id: int, name: str, sort: int, editable: bool }[] }`
#### Create customer group — `POST /customergroup`
- Params: `body: { name: str }`
- Returns: `201 { customergroup: T55 }`
- Returns: `201 { customergroup: T56 }`
#### Reorder customer groups — `PUT /customergroup/order`
- Params: `body: { customergroupIds: int[] }`
- Returns: `200 { customergroupIds: int[] }`
@@ -388,16 +389,16 @@ _none_
- Returns: `204 void`
#### Update customer group — `PATCH /customergroup/{id}`
- Params: `id: int, body: { name: str }`
- Returns: `200 { customergroup: T55 }`
- Returns: `200 { customergroup: T56 }`
### Section: /delivery
#### List deliveries — `GET /delivery`
_none_
- Returns: `200 { deliveries: { id: int, number: str, type: str, supplierId: int|null, date: str, externalNumber?: str|null, createdAt?: str, ledger?: T51 }[] }`
- Returns: `200 { deliveries: { id: int, number: str, type: str, supplierId: int|null, date: str, externalNumber?: str|null, createdAt?: str, ledger?: T52 }[] }`
#### Create delivery — `POST /delivery`
- Params: `body: { externalNumber: str, date: str, lines: T34[], supplierId?: int|null, files?: { mimetype: str, name: str, content: str, sort?: int, size?: int, hash?: str, created?: str, modified?: str, meta?: { [k]: str } }[] }`
- Returns: `201 T8`
- Params: `body: { externalNumber: str, date: str, lines: T35[], supplierId?: int|null, files?: { mimetype: str, name: str, content: str, sort?: int, size?: int, hash?: str, created?: str, modified?: str, meta?: { [k]: str } }[] }`
- Returns: `201 T9`
#### Parse document (SSE) — `POST /delivery/parse`
- Params: `form: { file: str }`
- Returns: `200 SSE`
@@ -415,10 +416,10 @@ _none_
- Returns: `204 void`
#### Get delivery — `GET /delivery/{id}`
- Params: `id: int`
- Returns: `200 T8`
- Returns: `200 T9`
#### Update delivery — `PATCH /delivery/{id}`
- Params: `id: int, body: { externalNumber?: str|null, date?: str, supplierId?: int|null, lines?: T34[], files?: { mimetype: str, name: str, content: str, sort?: int, size?: int, hash?: str, created?: str, modified?: str, meta?: { [k]: str } }[] }`
- Returns: `200 T8`
- Params: `id: int, body: { externalNumber?: str|null, date?: str, supplierId?: int|null, lines?: T35[], files?: { mimetype: str, name: str, content: str, sort?: int, size?: int, hash?: str, created?: str, modified?: str, meta?: { [k]: str } }[] }`
- Returns: `200 T9`
#### Delete delivery file attachment — `DELETE /delivery/{id}/file/{fileId}`
- Params: `id: int, fileId: int`
- Returns: `204 void`
@@ -427,52 +428,52 @@ _none_
- Returns: `200 str`
#### Generate and attach delivery note PDF (goods receipt) — `POST /delivery/{id}/pdf`
- Params: `id: int`
- Returns: `201 T13`
- Returns: `201 T14`
### Section: /entity
#### List entities — `GET /entity`
- Params: `query: customergroupId?: int, role?: str`
- Returns: `200 { entities: T36[] }`
- Returns: `200 { entities: T37[] }`
#### Create entity — `POST /entity`
- Params: `body: { customergroupId: int, name: str, firstName?: str|null, number?: str }`
- Returns: `201 T28`
- Returns: `201 T29`
#### Peek next customer number — `GET /entity/next-number`
_none_
- Returns: `200 { number: str }`
#### List entity addresses — `GET /entity/{entityId}/address`
- Params: `entityId: int`
- Returns: `200 { addresses: T19[] }`
- Returns: `200 { addresses: T20[] }`
#### Create entity address — `POST /entity/{entityId}/address`
- Params: `entityId: int, body: { addressType: str, firstName?: str|null, name?: str|null, street?: str|null, streetNumber?: str|null, zip?: str|null, city?: str|null, county?: str|null }`
- Returns: `201 { address: T19 }`
- Returns: `201 { address: T20 }`
#### Delete entity address — `DELETE /entity/{entityId}/address/{id}`
- Params: `entityId: int, id: int`
- Returns: `204 void`
#### Update entity address — `PATCH /entity/{entityId}/address/{id}`
- Params: `entityId: int, id: int, body: { addressType?: str, firstName?: str|null, name?: str|null, street?: str|null, streetNumber?: str|null, zip?: str|null, city?: str|null, county?: str|null }`
- Returns: `200 { address: T19 }`
- Returns: `200 { address: T20 }`
#### List entity contacts — `GET /entity/{entityId}/contact`
- Params: `entityId: int`
- Returns: `200 { contacts: T49[] }`
- Returns: `200 { contacts: T50[] }`
#### Create entity contact — `POST /entity/{entityId}/contact`
- Params: `entityId: int, body: { contactType: str, contact: str }`
- Returns: `201 { contact: T49 }`
- Returns: `201 { contact: T50 }`
#### Delete entity contact — `DELETE /entity/{entityId}/contact/{id}`
- Params: `entityId: int, id: int`
- Returns: `204 void`
#### Update entity contact — `PATCH /entity/{entityId}/contact/{id}`
- Params: `entityId: int, id: int, body: { contactType?: str, contact?: str }`
- Returns: `200 { contact: T49 }`
- Returns: `200 { contact: T50 }`
#### Delete entity — `DELETE /entity/{id}`
- Params: `id: int`
- Returns: `204 void`
#### Get entity — `GET /entity/{id}`
- Params: `id: int`
- Returns: `200 T28`
- Returns: `200 T29`
#### Update entity — `PATCH /entity/{id}`
- Params: `id: int, body: { name?: str, firstName?: str|null, number?: str|null }`
- Returns: `200 T28`
- Returns: `200 T29`
### Section: /events
@@ -516,35 +517,35 @@ _none_
_none_
- Returns: `200 { labeltemplates: { id: int, name: str, width: num, height: num, dpi: int, type: str, thumb?: str|null }[] }`
#### Create label template — `POST /labeltemplate`
- Params: `body: { name: str, width: num, height: num, dpi: int, type: str, content: T26 }`
- Returns: `201 T12`
- Params: `body: { name: str, width: num, height: num, dpi: int, type: str, content: T27 }`
- Returns: `201 T13`
#### Delete label template — `DELETE /labeltemplate/{id}`
- Params: `id: int`
- Returns: `204 void`
#### Get label template by ID — `GET /labeltemplate/{id}`
- Params: `id: int`
- Returns: `200 T12`
- Returns: `200 T13`
#### Update label template (partial) — `PATCH /labeltemplate/{id}`
- Params: `id: int, body: { name?: str, width?: num, height?: num, dpi?: int, type?: str, content?: T26 }`
- Returns: `200 T12`
- Params: `id: int, body: { name?: str, width?: num, height?: num, dpi?: int, type?: str, content?: T27 }`
- Returns: `200 T13`
#### Update label template — `PUT /labeltemplate/{id}`
- Params: `id: int, body: { name?: str, width?: num, height?: num, dpi?: int, type?: str, content?: T26 }`
- Returns: `200 T12`
- Params: `id: int, body: { name?: str, width?: num, height?: num, dpi?: int, type?: str, content?: T27 }`
- Returns: `200 T13`
### Section: /ledger
#### Query ledger by manifest article ID or SKU — `GET /ledger`
- Params: `query: manifestarticle_id?: int, sku?: str, transaction_type?: str`
- Returns: `200 T20`
- Returns: `200 T21`
#### Add ledger entry — `POST /ledger`
- Params: `body: { manifestarticle_id: int, transaction_type: str, amount: num, transaction_text: str }`
- Returns: `201 { ledger: T21 }`
- Returns: `201 { ledger: T22 }`
#### Query ledger by manifest article ID — `GET /ledger/manifestarticle/{manifestarticleId}`
- Params: `manifestarticleId: int, query: transaction_type?: str`
- Returns: `200 T20`
- Returns: `200 T21`
#### Query ledger by article SKU — `GET /ledger/sku/{sku}`
- Params: `sku: str, query: transaction_type?: str`
- Returns: `200 T20`
- Returns: `200 T21`
### Section: /mcp
@@ -574,16 +575,16 @@ _none_
#### List conversations — `GET /modelconversation`
_none_
- Returns: `200 { conversations: T23[] }`
- Returns: `200 { conversations: T24[] }`
#### Create conversation — `POST /modelconversation`
- Params: `body: { provider: str, model: str }`
- Returns: `201 { conversation: T23 }`
- Returns: `201 { conversation: T24 }`
#### Delete conversation — `DELETE /modelconversation/{id}`
- Params: `id: int`
- Returns: `204 void`
#### Get conversation — `GET /modelconversation/{id}`
- Params: `id: int`
- Returns: `200 { conversation: T23 }`
- Returns: `200 { conversation: T24 }`
#### List conversation messages — `GET /modelconversation/{id}/message`
- Params: `id: int`
- Returns: `200 { messages: { id: int, conversation_id: int, created_at: str, role: str, message: str }[] }`
@@ -624,7 +625,7 @@ _none_
- Params: `query: offset?: int, limit?: int, search?: str, onlyUnpaid?: bool, onlyUndelivered?: bool, seekMonths?: int`
- Returns: `200 { orders: T2[], total: int, unfilteredTotal: int, offset: int, limit: int }`
#### Create order — `POST /order`
- Params: `body: { number: str, date: str, lines: T34[], entityId?: int|null, externalNumber?: str|null }`
- Params: `body: { number: str, date: str, lines: T35[], entityId?: int|null, externalNumber?: str|null }`
- Returns: `201 T1`
#### Delete order — `DELETE /order/{id}`
- Params: `id: int`
@@ -633,7 +634,7 @@ _none_
- Params: `id: int`
- Returns: `200 T1`
#### Update order — `PATCH /order/{id}`
- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, externalNumber?: str|null, lines?: T34[] }`
- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, externalNumber?: str|null, lines?: T35[] }`
- Returns: `200 T1`
#### Delete order file attachment — `DELETE /order/{id}/file/{fileId}`
- Params: `id: int, fileId: int`
@@ -643,25 +644,25 @@ _none_
- Returns: `200 str`
#### List payments of an order — `GET /order/{id}/payment`
- Params: `id: int`
- Returns: `200 { payments: T43[] }`
- Returns: `200 { payments: T44[] }`
#### Add payment to an order — `POST /order/{id}/payment`
- Params: `id: int, body: { accountId: int, type: str, amount: num }`
- Returns: `201 { payment: T43 }`
- Returns: `201 { payment: T44 }`
#### Generate and attach order PDF — `POST /order/{id}/pdf`
- Params: `id: int`
- Returns: `201 T13`
- Returns: `201 T14`
#### List shipments of an order — `GET /order/{id}/shipment`
- Params: `id: int`
- Returns: `200 { shipments: T5[] }`
- Returns: `200 { shipments: T6[] }`
#### Create shipment for an order — `POST /order/{id}/shipment`
- Params: `id: int, body: { lines: { sku: str, amount: num, name?: str, pu?: num, net?: num, rebate?: num, taxrate?: num, comment?: str }[], date?: str, externalNumber?: str }`
- Returns: `201 { shipment: T5 }`
- Params: `id: int, body?: { date?: str, externalNumber?: str, lines?: { sku: str, amount?: num, name?: str, pu?: num, net?: num, rebate?: num, taxrate?: num, comment?: str }[] }`
- Returns: `201 T5`
#### List shippings of an order — `GET /order/{id}/shipping`
- Params: `id: int`
- Returns: `200 { shippings: T37[] }`
- Returns: `200 { shippings: T38[] }`
#### Create shipping for an order — `POST /order/{id}/shipping`
- Params: `id: int, body: { type: str, state: str, warehouseId?: int }`
- Returns: `201 T32`
- Returns: `201 T33`
### Section: /package
@@ -679,37 +680,37 @@ _none_
#### List POS terminals — `GET /posterminal`
_none_
- Returns: `200 { posterminals: T16[] }`
- Returns: `200 { posterminals: T17[] }`
#### Create POS terminal — `PUT /posterminal`
- Params: `body: { name: str, rootCategoryId?: int|null, syncRootArticles?: bool }`
- Returns: `200 { posterminal: T16 }`
- Returns: `200 { posterminal: T17 }`
#### Delete POS terminal — `DELETE /posterminal/{id}`
- Params: `id: int`
- Returns: `204 void`
#### Update POS terminal — `PATCH /posterminal/{id}`
- Params: `id: int, body: { name?: str, rootCategoryId?: int|null, syncRootArticles?: bool, pairingpin?: str|null }`
- Returns: `200 { posterminal: T16 }`
- Returns: `200 { posterminal: T17 }`
#### Disable all categories on terminal — `DELETE /posterminal/{id}/all`
- Params: `id: int`
- Returns: `200 T56`
- Returns: `200 T57`
#### Enable all categories on terminal — `PUT /posterminal/{id}/all`
- Params: `id: int`
- Returns: `200 T56`
- Returns: `200 T57`
#### Disable category on terminal — `DELETE /posterminal/{id}/category/{categoryId}`
- Params: `id: int, categoryId: int`
- Returns: `200 T56`
- Returns: `200 T57`
#### Enable category on terminal — `PUT /posterminal/{id}/category/{categoryId}`
- Params: `id: int, categoryId: int`
- Returns: `200 T56`
- Returns: `200 T57`
### Section: /printer
#### List printers — `GET /printer`
_none_
- Returns: `200 { printers: T33[] }`
- Returns: `200 { printers: T34[] }`
#### Create printer — `POST /printer`
- Params: `body: { address: str, type: str, model?: str|null, serial?: str|null, sort?: int, desc?: str|null }`
- Returns: `201 T27`
- Returns: `201 T28`
#### Reorder printers — `PUT /printer/order`
- Params: `body: { printerIds: int[] }`
- Returns: `200 { printerIds: int[] }`
@@ -718,22 +719,22 @@ _none_
- Returns: `204 void`
#### Get printer by ID — `GET /printer/{id}`
- Params: `id: int`
- Returns: `200 T27`
- Returns: `200 T28`
#### Update printer (partial) — `PATCH /printer/{id}`
- Params: `id: int, body: { address?: str, type?: str, model?: str|null, serial?: str|null, sort?: int, desc?: str|null }`
- Returns: `200 T27`
- Returns: `200 T28`
#### Update printer — `PUT /printer/{id}`
- Params: `id: int, body: { address?: str, type?: str, model?: str|null, serial?: str|null, sort?: int, desc?: str|null }`
- Returns: `200 T27`
- Returns: `200 T28`
### Section: /propertyname
#### List property names — `GET /propertyname`
_none_
- Returns: `200 { propertynames: T42[] }`
- Returns: `200 { propertynames: T43[] }`
#### Create property name — `POST /propertyname`
- Params: `body: { name: str, sort?: int, exclusive?: bool }`
- Returns: `201 { propertyname: T42 }`
- Returns: `201 { propertyname: T43 }`
#### Reorder property names — `PUT /propertyname/order`
- Params: `body: { propertynameIds: int[] }`
- Returns: `200 { ok: bool }`
@@ -742,7 +743,7 @@ _none_
- Returns: `200 { ok: bool }`
#### Update property name — `PATCH /propertyname/{id}`
- Params: `id: int, body: { name?: str, sort?: int, exclusive?: bool }`
- Returns: `200 { propertyname: T42 }`
- Returns: `200 { propertyname: T43 }`
### Section: /public
@@ -763,19 +764,19 @@ _none_
#### List quotes — `GET /quote`
- Params: `query: offset?: int, limit?: int, search?: str, seekMonths?: int`
- Returns: `200 { quotes: T7[], total: int, unfilteredTotal: int, offset: int, limit: int }`
- Returns: `200 { quotes: T8[], total: int, unfilteredTotal: int, offset: int, limit: int }`
#### Create quote — `POST /quote`
- Params: `body: { number: str, date: str, lines: T34[], entityId?: int|null, externalNumber?: str|null }`
- Returns: `201 T6`
- Params: `body: { number: str, date: str, lines: T35[], entityId?: int|null, externalNumber?: str|null }`
- Returns: `201 T7`
#### Delete quote — `DELETE /quote/{id}`
- Params: `id: int`
- Returns: `204 void`
#### Get quote — `GET /quote/{id}`
- Params: `id: int`
- Returns: `200 T6`
- Returns: `200 T7`
#### Update quote — `PATCH /quote/{id}`
- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, externalNumber?: str|null, lines?: T34[] }`
- Returns: `200 T6`
- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, externalNumber?: str|null, lines?: T35[] }`
- Returns: `200 T7`
#### Delete quote file attachment — `DELETE /quote/{id}/file/{fileId}`
- Params: `id: int, fileId: int`
- Returns: `204 void`
@@ -783,11 +784,11 @@ _none_
- Params: `id: int, fileId: int, query: download?: bool`
- Returns: `200 str`
#### Create order from quote — `POST /quote/{id}/order`
- Params: `id: int, body?: { number?: str, date?: str, createdAt?: str, entityId?: int|null, externalNumber?: str|null, lines?: T34[] }`
- Params: `id: int, body?: { number?: str, date?: str, createdAt?: str, entityId?: int|null, externalNumber?: str|null, lines?: T35[] }`
- Returns: `201 T1`
#### Generate and attach quote PDF — `POST /quote/{id}/pdf`
- Params: `id: int`
- Returns: `201 T13`
- Returns: `201 T14`
### Section: /serper
@@ -806,12 +807,18 @@ _none_
### Section: /shipment
#### List shipments — `GET /shipment`
- Params: `query: offset?: int, limit?: int, search?: str, state?: str, seekMonths?: int`
- Returns: `200 { shipments: { id: int, number: str, type: str, date: str, positions: int, totalQuantity: num, packageCount: int, state: str, entityId?: int|null, externalNumber?: str|null, createdAt?: str|null, orderId?: int|null, orderNumber?: str|null, customerName?: str|null, carrier?: str|null, trackingCode?: str|null }[], total: int, unfilteredTotal: int, offset: int, limit: int }`
#### Delete shipment — `DELETE /shipment/{id}`
- Params: `id: int`
- Returns: `204 void`
#### Get shipment by ID — `GET /shipment/{id}`
- Params: `id: int`
- Returns: `200 { shipment: T5 }`
- Returns: `200 T5`
#### Update shipment state or metadata — `PATCH /shipment/{id}`
- Params: `id: int, body: { state?: str }`
- Returns: `200 T5`
#### Delete shipment file attachment — `DELETE /shipment/{id}/file/{fileId}`
- Params: `id: int, fileId: int`
- Returns: `204 void`
@@ -820,13 +827,13 @@ _none_
- Returns: `200 str`
#### Generate and attach shipment PDF (delivery note) — `POST /shipment/{id}/pdf`
- Params: `id: int`
- Returns: `201 T13`
- Returns: `201 T14`
#### List packages of a shipment — `GET /shipment/{id}/shipping`
- Params: `id: int`
- Returns: `200 { shippings: T37[] }`
- Returns: `200 { shippings: T38[] }`
#### Create package for a shipment — `POST /shipment/{id}/shipping`
- Params: `id: int, body: { type: str, state: str, trackingCode?: str, carrier?: str, warehouseId?: int }`
- Returns: `201 T32`
- Returns: `201 T33`
### Section: /shipping
@@ -835,7 +842,7 @@ _none_
- Returns: `204 void`
#### Update shipping — `PATCH /shipping/{id}`
- Params: `id: int, body: { type?: str, state?: str, trackingCode?: str, carrier?: str, warehouseId?: int }`
- Returns: `200 T32`
- Returns: `200 T33`
#### List packages of a shipping — `GET /shipping/{id}/package`
- Params: `id: int`
- Returns: `200 { packages: { id: int, shippingId: int, entityaddressId: int, number: str, type: str, state: str, details?: str|null }[] }`
@@ -853,28 +860,28 @@ _none_
#### Adjust stock manually — `POST /stock/adjust`
- Params: `body: { sku?: str, warehouseId?: int, amount?: num, text?: str|null, lines?: { sku: str, amount: num, warehouseId?: int, text?: str }[] }`
- Returns: `201 { manifest: { id: int, number: str, type: str, date: str, createdAt: str }, lines: { manifestarticle_id: int, sku: str, name: str, warehouse_id: int, amount: num, text: str }[], ledger: T21[] }`
- Returns: `201 { manifest: { id: int, number: str, type: str, date: str, createdAt: str }, lines: { manifestarticle_id: int, sku: str, name: str, warehouse_id: int, amount: num, text: str }[], ledger: T22[] }`
### Section: /supplier
#### List suppliers — `GET /supplier`
_none_
- Returns: `200 { suppliers: T50[] }`
- Returns: `200 { suppliers: T51[] }`
#### Create supplier — `POST /supplier`
- Params: `body: { name: str }`
- Returns: `201 { supplier: T50 }`
- Returns: `201 { supplier: T51 }`
#### Delete supplier — `DELETE /supplier/{id}`
- Params: `id: int`
- Returns: `204 void`
#### Update supplier — `PATCH /supplier/{id}`
- Params: `id: int, body: { name: str }`
- Returns: `200 { supplier: T50 }`
- Returns: `200 { supplier: T51 }`
#### List supplier articles by SKUs — `GET /supplier/{id}/articles`
- Params: `id: int, query: skus?: string`
- Returns: `200 { articles: { id: int, articleId: int, entityId: int, pu: num, sort: int, article: { id: int, sku: str, name?: str|null, slug?: str|null, photos?: { sort: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str }[], eans?: str[] }, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T54|null }[] }`
- Returns: `200 { articles: { id: int, articleId: int, entityId: int, pu: num, sort: int, article: { id: int, sku: str, name?: str|null, slug?: str|null, photos?: { sort: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str }[], eans?: str[] }, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T55|null }[] }`
#### Query supplier articles by SKUs (bulk) — `POST /supplier/{id}/articles`
- Params: `id: int, body?: { skus?: str[] }`
- Returns: `200 { articles: { id: int, articleId: int, entityId: int, pu: num, sort: int, article: { id: int, sku: str, name?: str|null, slug?: str|null, photos?: { sort: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str }[], eans?: str[] }, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T54|null }[] }`
- Returns: `200 { articles: { id: int, articleId: int, entityId: int, pu: num, sort: int, article: { id: int, sku: str, name?: str|null, slug?: str|null, photos?: { sort: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str }[], eans?: str[] }, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T55|null }[] }`
### Section: /thumb
@@ -889,10 +896,10 @@ _none_
- Returns: `204 void`
#### List units — `GET /unit`
_none_
- Returns: `200 { units: T40[] }`
- Returns: `200 { units: T41[] }`
#### Upsert unit — `PUT /unit`
- Params: `body: { si: str, basesi: str, basesifactor: num, symbol: str, name: str }`
- Returns: `200 { unit: T40 }`
- Returns: `200 { unit: T41 }`
### Section: /v1
@@ -946,10 +953,10 @@ _none_
#### List warehouses — `GET /warehouse`
_none_
- Returns: `200 { warehouses: T55[] }`
- Returns: `200 { warehouses: T56[] }`
#### Create warehouse — `POST /warehouse`
- Params: `body: { name: str, sort?: int }`
- Returns: `201 T53`
- Returns: `201 T54`
#### Reorder warehouses — `PUT /warehouse/order`
- Params: `body: { warehouseIds: int[] }`
- Returns: `200 { warehouseIds: int[] }`
@@ -958,10 +965,10 @@ _none_
- Returns: `204 void`
#### Get warehouse by ID — `GET /warehouse/{id}`
- Params: `id: int`
- Returns: `200 T53`
- Returns: `200 T54`
#### Update warehouse (partial) — `PATCH /warehouse/{id}`
- Params: `id: int, body: { name?: str, sort?: int }`
- Returns: `200 T53`
- Returns: `200 T54`
#### Update warehouse — `PUT /warehouse/{id}`
- Params: `id: int, body: { name?: str, sort?: int }`
- Returns: `200 T53`
- Returns: `200 T54`

View File

@@ -1,6 +1,6 @@
# Dash API Routes Overview
Overview of all 172 API endpoints across all modules.
Overview of all 174 API endpoints across all modules.
### Notation
@@ -10,51 +10,52 @@ Params: path values first, then `query:` and `body:` (`body?` = optional body).
### Reusable types
- `T1` = `{ order: T2 }`
- `T2` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T23[], externalNumber?: str|null, createdAt?: str, shipping?: T31|null, shippings?: T31[], payment?: T37|null, payments?: T37[], paid?: bool, shipped?: bool, delivered?: bool, orderTotal?: num, paidTotal?: num, orderedQuantity?: num, shippedQuantity?: num, shipments?: T5[], files?: T13[] }`
- `T2` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T24[], externalNumber?: str|null, createdAt?: str, shipping?: T32|null, shippings?: T32[], payment?: T38|null, payments?: T38[], paid?: bool, shipped?: bool, delivered?: bool, orderTotal?: num, paidTotal?: num, orderedQuantity?: num, shippedQuantity?: num, shipments?: T6[], files?: T14[] }`
- `T3` = `{ article: T4 }`
- `T4` = `{ id: int, sku: str, name: str, slug: str, desc: str|null, seo: str|null, track_stock: bool, unitamount: num|null, weight: num|null, unit: T34, brand: T32|null, categoryIds: int[], photos: T29[], eans: str[], prices: T39[], suppliers: T14[] }`
- `T5` = `{ id: int, number: str, type: str, date: str, lines: T23[], shippings: T31[], entityId?: int|null, externalNumber?: str|null, createdAt?: str|null, lineCount?: int, packageCount?: int, files?: T13[] }`
- `T6` = `{ quote: T7 }`
- `T7` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T23[], externalNumber?: str|null, createdAt?: str, positions?: int, grossTotal?: num, totalQuantity?: num, customerName?: str|null, files?: T13[] }`
- `T8` = `{ delivery: T9 }`
- `T9` = `{ id: int, number: str, type: str, supplierId: int|null, date: str, lines: T23[], files: T13[], externalNumber?: str|null, createdAt?: str, ledger?: T43 }`
- `T10` = `{ labeltemplate: T12 }`
- `T11` = `{ attachment: T13, fileUrl: str }`
- `T12` = `{ id: int, name: str, width: num, height: num, dpi: int, type: str, content: T19, thumb?: str|null }`
- `T13` = `{ id: int, manifestId: int, fileId: int, sort: int, hash: str, mimetype: str, name: str, size: int, created?: str, modified?: str, skeledash?: str|null, thumbx?: int|null, thumby?: int|null, meta?: { [k]: str }|null }`
- `T14` = `{ id: int, articleId: int, entityId: int, pu: num, sort: int, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T45|null }`
- `T15` = `{ id: int, entityId: int, addressType: str, firstName?: str|null, name?: str|null, street?: str|null, streetNumber?: str|null, zip?: str|null, city?: str|null, county?: str|null }`
- `T16` = `{ ledger: T17[] }`
- `T17` = `{ id: int, manifestarticle_id: int, transaction_type: str, amount: num, transaction_text: str, hash_version: int, prev_hash?: str, sku?: str|null, created_at?: str }`
- `T18` = `{ id: int, name: str, sort: int, exclusive: bool, values: T35[], articleCount?: int }`
- `T19` = `{ objects: T24[] }`
- `T4` = `{ id: int, sku: str, name: str, slug: str, desc: str|null, seo: str|null, track_stock: bool, unitamount: num|null, weight: num|null, unit: T35, brand: T33|null, categoryIds: int[], photos: T30[], eans: str[], prices: T40[], suppliers: T15[] }`
- `T5` = `{ shipment: T6 }`
- `T6` = `{ id: int, number: str, type: str, date: str, lines: T24[], shippings: T32[], entityId?: int|null, externalNumber?: str|null, createdAt?: str|null, lineCount?: int, packageCount?: int, files?: T14[], state?: str }`
- `T7` = `{ quote: T8 }`
- `T8` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T24[], externalNumber?: str|null, createdAt?: str, positions?: int, grossTotal?: num, totalQuantity?: num, customerName?: str|null, files?: T14[] }`
- `T9` = `{ delivery: T10 }`
- `T10` = `{ id: int, number: str, type: str, supplierId: int|null, date: str, lines: T24[], files: T14[], externalNumber?: str|null, createdAt?: str, ledger?: T44 }`
- `T11` = `{ labeltemplate: T13 }`
- `T12` = `{ attachment: T14, fileUrl: str }`
- `T13` = `{ id: int, name: str, width: num, height: num, dpi: int, type: str, content: T20, thumb?: str|null }`
- `T14` = `{ id: int, manifestId: int, fileId: int, sort: int, hash: str, mimetype: str, name: str, size: int, created?: str, modified?: str, skeledash?: str|null, thumbx?: int|null, thumby?: int|null, meta?: { [k]: str }|null }`
- `T15` = `{ id: int, articleId: int, entityId: int, pu: num, sort: int, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T46|null }`
- `T16` = `{ id: int, entityId: int, addressType: str, firstName?: str|null, name?: str|null, street?: str|null, streetNumber?: str|null, zip?: str|null, city?: str|null, county?: str|null }`
- `T17` = `{ ledger: T18[] }`
- `T18` = `{ id: int, manifestarticle_id: int, transaction_type: str, amount: num, transaction_text: str, hash_version: int, prev_hash?: str, sku?: str|null, created_at?: str }`
- `T19` = `{ id: int, name: str, sort: int, exclusive: bool, values: T36[], articleCount?: int }`
- `T20` = `{ objects: T25[] }`
- `T21` = `{ printer: T27 }`
- `T22` = `{ entity: T30 }`
- `T23` = `{ id: int, sku: str|null, name: str|null, pu: num, amount: num, net: num, rebate: num, taxrate: num, comment: str|null }`
- `T24` = `{ id: str, type: str, x: num, y: num, w?: num, h?: num, text?: str, font?: str, fontSize?: num, barcodeFormat?: str }`
- `T21` = `{ objects: T26[] }`
- `T22` = `{ printer: T28 }`
- `T23` = `{ entity: T31 }`
- `T24` = `{ id: int, sku: str|null, name: str|null, pu: num, amount: num, net: num, rebate: num, taxrate: num, comment: str|null }`
- `T25` = `{ id: str, type: str, x: num, y: num, w?: num, h?: num, text?: str, font?: str, fontSize?: num, barcodeFormat?: str }`
- `T26` = `{ shipping: T31 }`
- `T27` = `{ id: int, company_id: int, address: str, type: str, sort: int, model?: str|null, serial?: str|null, desc?: str|null }`
- `T28` = `{ amount: num, net: num, taxrate: num, sku?: str|null, name?: str|null, pu?: num, rebate?: num, comment?: str|null }`
- `T29` = `{ sort: int, fullHash: str, fullW: int, fullH: int, fullSize: int, thumbW: int, thumbH: int, thumbHash: str }`
- `T30` = `{ id: int, customergroupId: int, firstName: str|null, name: str, number: str|null, createdAt: str, updatedAt: str }`
- `T31` = `{ id: int, manifestId: int, number: str, type: str, state: str, trackingCode?: str|null, carrier?: str|null }`
- `T32` = `{ name: str, id?: int|null, fullHash?: str|null, thumbW?: int|null, thumbH?: int|null, thumbHash?: str|null }`
- `T33` = `{ article: T38 }`
- `T34` = `{ si: str, basesi: str, basesifactor: num, symbol?: str|null, name?: str|null }`
- `T35` = `{ id: int, attributeId: int, value: str, sort: int, articleCount?: int }`
- `T36` = `{ id: int, name: str, sort: int, exclusive: bool, articleCount?: int }`
- `T37` = `{ id: int, accountId: int, manifestId: int, type: str, amount: num }`
- `T38` = `{ id: int, categoryId: int, name: str, sku: str, track_stock: bool }`
- `T39` = `{ minmultiplier: num, net: num, taxRate: num, customergroupId: int }`
- `T40` = `{ fullHash: str, thumbW: int, thumbH: int, thumbHash: str }`
- `T41` = `{ id: int, entityId: int, contactType: str, contact: str }`
- `T42` = `{ id: int, name: str, createdAt: str, updatedAt: str }`
- `T43` = `{ totalPositions: int, completelyOnLedgerPositions: int }`
- `T44` = `{ warehouse: T46 }`
- `T45` = `{ net: num, taxId: int, taxRate?: num|null }`
- `T46` = `{ id: int, name: str, sort: int }`
- `T26` = `{ id: str, type: str, x: num, y: num, w?: num, h?: num, text?: str, font?: str, fontSize?: num, barcodeFormat?: str }`
- `T27` = `{ shipping: T32 }`
- `T28` = `{ id: int, company_id: int, address: str, type: str, sort: int, model?: str|null, serial?: str|null, desc?: str|null }`
- `T29` = `{ amount: num, net: num, taxrate: num, sku?: str|null, name?: str|null, pu?: num, rebate?: num, comment?: str|null }`
- `T30` = `{ sort: int, fullHash: str, fullW: int, fullH: int, fullSize: int, thumbW: int, thumbH: int, thumbHash: str }`
- `T31` = `{ id: int, customergroupId: int, firstName: str|null, name: str, number: str|null, createdAt: str, updatedAt: str }`
- `T32` = `{ id: int, manifestId: int, number: str, type: str, state: str, trackingCode?: str|null, carrier?: str|null }`
- `T33` = `{ name: str, id?: int|null, fullHash?: str|null, thumbW?: int|null, thumbH?: int|null, thumbHash?: str|null }`
- `T34` = `{ article: T39 }`
- `T35` = `{ si: str, basesi: str, basesifactor: num, symbol?: str|null, name?: str|null }`
- `T36` = `{ id: int, attributeId: int, value: str, sort: int, articleCount?: int }`
- `T37` = `{ id: int, name: str, sort: int, exclusive: bool, articleCount?: int }`
- `T38` = `{ id: int, accountId: int, manifestId: int, type: str, amount: num }`
- `T39` = `{ id: int, categoryId: int, name: str, sku: str, track_stock: bool }`
- `T40` = `{ minmultiplier: num, net: num, taxRate: num, customergroupId: int }`
- `T41` = `{ fullHash: str, thumbW: int, thumbH: int, thumbHash: str }`
- `T42` = `{ id: int, entityId: int, contactType: str, contact: str }`
- `T43` = `{ id: int, name: str, createdAt: str, updatedAt: str }`
- `T44` = `{ totalPositions: int, completelyOnLedgerPositions: int }`
- `T45` = `{ warehouse: T47 }`
- `T46` = `{ net: num, taxId: int, taxRate?: num|null }`
- `T47` = `{ id: int, name: str, sort: int }`
### Routes
@@ -63,7 +64,7 @@ Params: path values first, then `query:` and `body:` (`body?` = optional body).
#### Create article in category — `POST /article`
- Params: `body: { categoryId: int, name: str, desc?: str, seo?: str, track_stock?: bool }`
- Returns: `201 T33`
- Returns: `201 T34`
#### Delete article by SKU — `DELETE /article/{sku}`
- Params: `sku: str, query: cascade?: bool`
- Returns: `204 void`
@@ -96,10 +97,10 @@ Params: path values first, then `query:` and `body:` (`body?` = optional body).
- Returns: `200 { children: { id: int, sku: str, name: str, parentsort: int, attributeValueId: int, attributeValue: str }[] }`
#### Create and attach a new child article to a parent article — `POST /article/{sku}/children`
- Params: `sku: str, body: { attributeValueId?: int, value?: str, name?: str }`
- Returns: `201 T33`
- Returns: `201 T34`
#### Attach an existing article as a child to a parent article — `PUT /article/{sku}/children`
- Params: `sku: str, body: { sku: str, attributeValueId?: int, value?: str, reparent?: bool }`
- Returns: `200 { article: T38, children: { id: int, sku: str, name: str, parentsort: int, attributeValueId: int, attributeValue: str }[] }`
- Returns: `200 { article: T39, children: { id: int, sku: str, name: str, parentsort: int, attributeValueId: int, attributeValue: str }[] }`
#### Remove a child article from a parent article — `DELETE /article/{sku}/children/{childSku}`
- Params: `sku: str, childSku: str, query: deleteArticle?: bool`
- Returns: `200 { success: bool, deleted: bool }`
@@ -123,7 +124,7 @@ Params: path values first, then `query:` and `body:` (`body?` = optional body).
- Returns: `200 { options: { id: int, articleId: int, sku: str, name: str, count: int, sort: int, mandated: bool }[] }`
#### Toggle parent mode for an article — `POST /article/{sku}/parent`
- Params: `sku: str, body: { isParent: bool, attributeNameId?: int }`
- Returns: `200 T33`
- Returns: `200 T34`
#### Replace POS prices by SKU (net > gross; price=net, tax=taxRate %) — `PUT /article/{sku}/prices`
- Params: `sku: str, body: { prices: { net?: num, gross?: num, price?: num, taxRate?: num, tax?: num, minmultiplier?: num }[] }`
- Returns: `200 T3`
@@ -141,10 +142,10 @@ Params: path values first, then `query:` and `body:` (`body?` = optional body).
- Returns: `200 { ok: bool }`
#### List article suppliers — `GET /article/{sku}/supplier`
- Params: `sku: str`
- Returns: `200 { suppliers: T14[] }`
- Returns: `200 { suppliers: T15[] }`
#### Assign supplier to article — `POST /article/{sku}/supplier`
- Params: `sku: str, body: { entityId: int, sku?: str|null, pu?: num, stock?: num|null, sort?: int|null, netPrice?: num|null, taxId?: int|null, taxRate?: num|null }`
- Returns: `201 { supplier: T14 }`
- Returns: `201 { supplier: T15 }`
#### Reorder article suppliers — `PUT /article/{sku}/supplier/order`
- Params: `sku: str, body: { ids: int[] }`
- Returns: `200 { ids: int[] }`
@@ -153,7 +154,7 @@ Params: path values first, then `query:` and `body:` (`body?` = optional body).
- Returns: `204 void`
#### Update article supplier assignment — `PATCH /article/{sku}/supplier/{id}`
- Params: `sku: str, id: int, body: { sku?: str|null, pu?: num, stock?: num|null, sort?: int, netPrice?: num|null, taxId?: int|null, taxRate?: num|null }`
- Returns: `200 { supplier: T14 }`
- Returns: `200 { supplier: T15 }`
#### Set article track_stock flag by SKU — `PUT /article/{sku}/track_stock`
- Params: `sku: str, body: { track_stock: bool }`
- Returns: `200 T3`
@@ -165,19 +166,19 @@ Params: path values first, then `query:` and `body:` (`body?` = optional body).
#### List attribute names — `GET /attributename`
_none_
- Returns: `200 { attributenames: T18[] }`
- Returns: `200 { attributenames: T19[] }`
#### Create attribute name — `POST /attributename`
- Params: `body: { name: str, sort?: int, exclusive?: bool }`
- Returns: `201 { attributename: T18 }`
- Returns: `201 { attributename: T19 }`
#### Reorder attribute names — `PUT /attributename/order`
- Params: `body: { attributenameIds: int[] }`
- Returns: `200 { ok: bool }`
#### List values for an attribute — `GET /attributename/{attributeId}/value`
- Params: `attributeId: int`
- Returns: `200 { values: T35[] }`
- Returns: `200 { values: T36[] }`
#### Create value for an attribute — `POST /attributename/{attributeId}/value`
- Params: `attributeId: int, body: { value: str, sort?: int }`
- Returns: `201 { attributevalue: T35 }`
- Returns: `201 { attributevalue: T36 }`
#### Reorder values of an attribute — `PUT /attributename/{attributeId}/value/order`
- Params: `attributeId: int, body: { attributevalueIds: int[] }`
- Returns: `200 { ok: bool }`
@@ -186,7 +187,7 @@ _none_
- Returns: `200 { ok: bool }`
#### Update attribute name — `PATCH /attributename/{id}`
- Params: `id: int, body: { name?: str, sort?: int, exclusive?: bool }`
- Returns: `200 { attributename: T18 }`
- Returns: `200 { attributename: T19 }`
### Section: /attributevalue
@@ -195,13 +196,13 @@ _none_
- Returns: `200 { ok: bool }`
#### Update attribute value — `PATCH /attributevalue/{id}`
- Params: `id: int, body: { value?: str, sort?: int }`
- Returns: `200 { attributevalue: T35 }`
- Returns: `200 { attributevalue: T36 }`
#### Delete attribute value image — `DELETE /attributevalue/{id}/image`
- Params: `id: int`
- Returns: `200 { attributevalue: { id: int, thumbW: int|null, thumbH: int|null, thumbHash: str|null, pics: T40[] } }`
- Returns: `200 { attributevalue: { id: int, thumbW: int|null, thumbH: int|null, thumbHash: str|null, pics: T41[] } }`
#### Add or replace attribute value image — `POST /attributevalue/{id}/image`
- Params: `id: int, image/avif`
- Returns: `201 { attributevalue: { id: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str, pics: T40[] } }`
- Returns: `201 { attributevalue: { id: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str, pics: T41[] } }`
### Section: /brand
@@ -210,7 +211,7 @@ _none_
- Returns: `200 { brands: { id: int, name: str, articleCount: int, pics: { fullHash: str, thumbW: int, thumbH: int, thumbHash: str, smallThumbW?: int|null, smallThumbH?: int|null, smallThumbBinary?: str|null }[], gsprpinfo?: str|null }[], total: int, offset: int, limit: int }`
#### Create brand — `POST /brand`
- Params: `body: { name: str, gsprpinfo?: str }`
- Returns: `201 { brand: { id: int, name: str, pics: T40[], gsprpinfo?: str|null } }`
- Returns: `201 { brand: { id: int, name: str, pics: T41[], gsprpinfo?: str|null } }`
#### Delete brand — `DELETE /brand/{id}`
- Params: `id: int`
- Returns: `204 void`
@@ -219,10 +220,10 @@ _none_
- Returns: `200 { brand: { id: int, name: str, touchedArticleCount: int, gsprpinfo?: str|null } }`
#### Delete brand image — `DELETE /brand/{id}/image`
- Params: `id: int`
- Returns: `200 { brand: { id: int, thumbW: int|null, thumbH: int|null, thumbHash: str|null, pics: T40[] } }`
- Returns: `200 { brand: { id: int, thumbW: int|null, thumbH: int|null, thumbHash: str|null, pics: T41[] } }`
#### Add or replace brand image — `POST /brand/{id}/image`
- Params: `id: int, image/avif`
- Returns: `201 { brand: { id: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str, pics: T40[] } }`
- Returns: `201 { brand: { id: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str, pics: T41[] } }`
### Section: /category
@@ -243,7 +244,7 @@ _none_
- Returns: `200 { category: { id: int, name: str, slug: str, parentId: int, sort: int } }`
#### Articles in category — `GET /category/{id}/articles`
- Params: `id: int`
- Returns: `200 { articles: { id: int, sku: str, name: str, slug: str, track_stock: bool, optionsCount: int, articleListCount: int, childCount: int, net?: num|null, taxRate?: num|null, parentArticleId?: int|null, parentSku?: str|null, fullHash?: str|null, thumbW?: int|null, thumbH?: int|null, thumbHash?: str|null, brand?: T32|null }[] }`
- Returns: `200 { articles: { id: int, sku: str, name: str, slug: str, track_stock: bool, optionsCount: int, articleListCount: int, childCount: int, net?: num|null, taxRate?: num|null, parentArticleId?: int|null, parentSku?: str|null, fullHash?: str|null, thumbW?: int|null, thumbH?: int|null, thumbHash?: str|null, brand?: T33|null }[] }`
#### List category attribute values — `GET /category/{id}/attributevalue`
- Params: `id: int`
- Returns: `200 { attributevalues: { id: int, attributeId: int, attributeName: str, attributeValueId: int, value: str, sort: int, categoryId?: int, exclusive?: bool }[] }`
@@ -297,7 +298,7 @@ _none_
- Returns: `200 { customergroups: { id: int, name: str, sort: int, editable: bool }[] }`
#### Create customer group — `POST /customergroup`
- Params: `body: { name: str }`
- Returns: `201 { customergroup: T46 }`
- Returns: `201 { customergroup: T47 }`
#### Reorder customer groups — `PUT /customergroup/order`
- Params: `body: { customergroupIds: int[] }`
- Returns: `200 { customergroupIds: int[] }`
@@ -306,76 +307,76 @@ _none_
- Returns: `204 void`
#### Update customer group — `PATCH /customergroup/{id}`
- Params: `id: int, body: { name: str }`
- Returns: `200 { customergroup: T46 }`
- Returns: `200 { customergroup: T47 }`
### Section: /delivery
#### List deliveries — `GET /delivery`
_none_
- Returns: `200 { deliveries: { id: int, number: str, type: str, supplierId: int|null, date: str, externalNumber?: str|null, createdAt?: str, ledger?: T43 }[] }`
- Returns: `200 { deliveries: { id: int, number: str, type: str, supplierId: int|null, date: str, externalNumber?: str|null, createdAt?: str, ledger?: T44 }[] }`
#### Create delivery — `POST /delivery`
- Params: `body: { externalNumber: str, date: str, lines: T28[], supplierId?: int|null, files?: { mimetype: str, name: str, content: str, sort?: int, size?: int, hash?: str, created?: str, modified?: str, meta?: { [k]: str } }[] }`
- Returns: `201 T8`
- Params: `body: { externalNumber: str, date: str, lines: T29[], supplierId?: int|null, files?: { mimetype: str, name: str, content: str, sort?: int, size?: int, hash?: str, created?: str, modified?: str, meta?: { [k]: str } }[] }`
- Returns: `201 T9`
#### Delete delivery — `DELETE /delivery/{id}`
- Params: `id: int`
- Returns: `204 void`
#### Get delivery — `GET /delivery/{id}`
- Params: `id: int`
- Returns: `200 T8`
- Returns: `200 T9`
#### Update delivery — `PATCH /delivery/{id}`
- Params: `id: int, body: { externalNumber?: str|null, date?: str, supplierId?: int|null, lines?: T28[], files?: { mimetype: str, name: str, content: str, sort?: int, size?: int, hash?: str, created?: str, modified?: str, meta?: { [k]: str } }[] }`
- Returns: `200 T8`
- Params: `id: int, body: { externalNumber?: str|null, date?: str, supplierId?: int|null, lines?: T29[], files?: { mimetype: str, name: str, content: str, sort?: int, size?: int, hash?: str, created?: str, modified?: str, meta?: { [k]: str } }[] }`
- Returns: `200 T9`
#### Delete delivery file attachment — `DELETE /delivery/{id}/file/{fileId}`
- Params: `id: int, fileId: int`
- Returns: `204 void`
#### Generate and attach delivery note PDF (goods receipt) — `POST /delivery/{id}/pdf`
- Params: `id: int`
- Returns: `201 T11`
- Returns: `201 T12`
### Section: /entity
#### List entities — `GET /entity`
- Params: `query: customergroupId?: int, role?: str`
- Returns: `200 { entities: T30[] }`
- Returns: `200 { entities: T31[] }`
#### Create entity — `POST /entity`
- Params: `body: { customergroupId: int, name: str, firstName?: str|null, number?: str }`
- Returns: `201 T22`
- Returns: `201 T23`
#### Peek next customer number — `GET /entity/next-number`
_none_
- Returns: `200 { number: str }`
#### List entity addresses — `GET /entity/{entityId}/address`
- Params: `entityId: int`
- Returns: `200 { addresses: T15[] }`
- Returns: `200 { addresses: T16[] }`
#### Create entity address — `POST /entity/{entityId}/address`
- Params: `entityId: int, body: { addressType: str, firstName?: str|null, name?: str|null, street?: str|null, streetNumber?: str|null, zip?: str|null, city?: str|null, county?: str|null }`
- Returns: `201 { address: T15 }`
- Returns: `201 { address: T16 }`
#### Delete entity address — `DELETE /entity/{entityId}/address/{id}`
- Params: `entityId: int, id: int`
- Returns: `204 void`
#### Update entity address — `PATCH /entity/{entityId}/address/{id}`
- Params: `entityId: int, id: int, body: { addressType?: str, firstName?: str|null, name?: str|null, street?: str|null, streetNumber?: str|null, zip?: str|null, city?: str|null, county?: str|null }`
- Returns: `200 { address: T15 }`
- Returns: `200 { address: T16 }`
#### List entity contacts — `GET /entity/{entityId}/contact`
- Params: `entityId: int`
- Returns: `200 { contacts: T41[] }`
- Returns: `200 { contacts: T42[] }`
#### Create entity contact — `POST /entity/{entityId}/contact`
- Params: `entityId: int, body: { contactType: str, contact: str }`
- Returns: `201 { contact: T41 }`
- Returns: `201 { contact: T42 }`
#### Delete entity contact — `DELETE /entity/{entityId}/contact/{id}`
- Params: `entityId: int, id: int`
- Returns: `204 void`
#### Update entity contact — `PATCH /entity/{entityId}/contact/{id}`
- Params: `entityId: int, id: int, body: { contactType?: str, contact?: str }`
- Returns: `200 { contact: T41 }`
- Returns: `200 { contact: T42 }`
#### Delete entity — `DELETE /entity/{id}`
- Params: `id: int`
- Returns: `204 void`
#### Get entity — `GET /entity/{id}`
- Params: `id: int`
- Returns: `200 T22`
- Returns: `200 T23`
#### Update entity — `PATCH /entity/{id}`
- Params: `id: int, body: { name?: str, firstName?: str|null, number?: str|null }`
- Returns: `200 T22`
- Returns: `200 T23`
### Section: /labeltemplate
@@ -383,35 +384,35 @@ _none_
_none_
- Returns: `200 { labeltemplates: { id: int, name: str, width: num, height: num, dpi: int, type: str, thumb?: str|null }[] }`
#### Create label template — `POST /labeltemplate`
- Params: `body: { name: str, width: num, height: num, dpi: int, type: str, content: T20 }`
- Returns: `201 T10`
- Params: `body: { name: str, width: num, height: num, dpi: int, type: str, content: T21 }`
- Returns: `201 T11`
#### Delete label template — `DELETE /labeltemplate/{id}`
- Params: `id: int`
- Returns: `204 void`
#### Get label template by ID — `GET /labeltemplate/{id}`
- Params: `id: int`
- Returns: `200 T10`
- Returns: `200 T11`
#### Update label template (partial) — `PATCH /labeltemplate/{id}`
- Params: `id: int, body: { name?: str, width?: num, height?: num, dpi?: int, type?: str, content?: T20 }`
- Returns: `200 T10`
- Params: `id: int, body: { name?: str, width?: num, height?: num, dpi?: int, type?: str, content?: T21 }`
- Returns: `200 T11`
#### Update label template — `PUT /labeltemplate/{id}`
- Params: `id: int, body: { name?: str, width?: num, height?: num, dpi?: int, type?: str, content?: T20 }`
- Returns: `200 T10`
- Params: `id: int, body: { name?: str, width?: num, height?: num, dpi?: int, type?: str, content?: T21 }`
- Returns: `200 T11`
### Section: /ledger
#### Query ledger by manifest article ID or SKU — `GET /ledger`
- Params: `query: manifestarticle_id?: int, sku?: str, transaction_type?: str`
- Returns: `200 T16`
- Returns: `200 T17`
#### Add ledger entry — `POST /ledger`
- Params: `body: { manifestarticle_id: int, transaction_type: str, amount: num, transaction_text: str }`
- Returns: `201 { ledger: T17 }`
- Returns: `201 { ledger: T18 }`
#### Query ledger by manifest article ID — `GET /ledger/manifestarticle/{manifestarticleId}`
- Params: `manifestarticleId: int, query: transaction_type?: str`
- Returns: `200 T16`
- Returns: `200 T17`
#### Query ledger by article SKU — `GET /ledger/sku/{sku}`
- Params: `sku: str, query: transaction_type?: str`
- Returns: `200 T16`
- Returns: `200 T17`
### Section: /number
@@ -428,7 +429,7 @@ _none_
- Params: `query: offset?: int, limit?: int, search?: str, onlyUnpaid?: bool, onlyUndelivered?: bool, seekMonths?: int`
- Returns: `200 { orders: T2[], total: int, unfilteredTotal: int, offset: int, limit: int }`
#### Create order — `POST /order`
- Params: `body: { number: str, date: str, lines: T28[], entityId?: int|null, externalNumber?: str|null }`
- Params: `body: { number: str, date: str, lines: T29[], entityId?: int|null, externalNumber?: str|null }`
- Returns: `201 T1`
#### Delete order — `DELETE /order/{id}`
- Params: `id: int`
@@ -437,32 +438,32 @@ _none_
- Params: `id: int`
- Returns: `200 T1`
#### Update order — `PATCH /order/{id}`
- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, externalNumber?: str|null, lines?: T28[] }`
- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, externalNumber?: str|null, lines?: T29[] }`
- Returns: `200 T1`
#### Delete order file attachment — `DELETE /order/{id}/file/{fileId}`
- Params: `id: int, fileId: int`
- Returns: `204 void`
#### List payments of an order — `GET /order/{id}/payment`
- Params: `id: int`
- Returns: `200 { payments: T37[] }`
- Returns: `200 { payments: T38[] }`
#### Add payment to an order — `POST /order/{id}/payment`
- Params: `id: int, body: { accountId: int, type: str, amount: num }`
- Returns: `201 { payment: T37 }`
- Returns: `201 { payment: T38 }`
#### Generate and attach order PDF — `POST /order/{id}/pdf`
- Params: `id: int`
- Returns: `201 T11`
- Returns: `201 T12`
#### List shipments of an order — `GET /order/{id}/shipment`
- Params: `id: int`
- Returns: `200 { shipments: T5[] }`
- Returns: `200 { shipments: T6[] }`
#### Create shipment for an order — `POST /order/{id}/shipment`
- Params: `id: int, body: { lines: { sku: str, amount: num, name?: str, pu?: num, net?: num, rebate?: num, taxrate?: num, comment?: str }[], date?: str, externalNumber?: str }`
- Returns: `201 { shipment: T5 }`
- Params: `id: int, body?: { date?: str, externalNumber?: str, lines?: { sku: str, amount?: num, name?: str, pu?: num, net?: num, rebate?: num, taxrate?: num, comment?: str }[] }`
- Returns: `201 T5`
#### List shippings of an order — `GET /order/{id}/shipping`
- Params: `id: int`
- Returns: `200 { shippings: T31[] }`
- Returns: `200 { shippings: T32[] }`
#### Create shipping for an order — `POST /order/{id}/shipping`
- Params: `id: int, body: { type: str, state: str, warehouseId?: int }`
- Returns: `201 T26`
- Returns: `201 T27`
### Section: /package
@@ -480,10 +481,10 @@ _none_
#### List printers — `GET /printer`
_none_
- Returns: `200 { printers: T27[] }`
- Returns: `200 { printers: T28[] }`
#### Create printer — `POST /printer`
- Params: `body: { address: str, type: str, model?: str|null, serial?: str|null, sort?: int, desc?: str|null }`
- Returns: `201 T21`
- Returns: `201 T22`
#### Reorder printers — `PUT /printer/order`
- Params: `body: { printerIds: int[] }`
- Returns: `200 { printerIds: int[] }`
@@ -492,22 +493,22 @@ _none_
- Returns: `204 void`
#### Get printer by ID — `GET /printer/{id}`
- Params: `id: int`
- Returns: `200 T21`
- Returns: `200 T22`
#### Update printer (partial) — `PATCH /printer/{id}`
- Params: `id: int, body: { address?: str, type?: str, model?: str|null, serial?: str|null, sort?: int, desc?: str|null }`
- Returns: `200 T21`
- Returns: `200 T22`
#### Update printer — `PUT /printer/{id}`
- Params: `id: int, body: { address?: str, type?: str, model?: str|null, serial?: str|null, sort?: int, desc?: str|null }`
- Returns: `200 T21`
- Returns: `200 T22`
### Section: /propertyname
#### List property names — `GET /propertyname`
_none_
- Returns: `200 { propertynames: T36[] }`
- Returns: `200 { propertynames: T37[] }`
#### Create property name — `POST /propertyname`
- Params: `body: { name: str, sort?: int, exclusive?: bool }`
- Returns: `201 { propertyname: T36 }`
- Returns: `201 { propertyname: T37 }`
#### Reorder property names — `PUT /propertyname/order`
- Params: `body: { propertynameIds: int[] }`
- Returns: `200 { ok: bool }`
@@ -516,55 +517,61 @@ _none_
- Returns: `200 { ok: bool }`
#### Update property name — `PATCH /propertyname/{id}`
- Params: `id: int, body: { name?: str, sort?: int, exclusive?: bool }`
- Returns: `200 { propertyname: T36 }`
- Returns: `200 { propertyname: T37 }`
### Section: /quote
#### List quotes — `GET /quote`
- Params: `query: offset?: int, limit?: int, search?: str, seekMonths?: int`
- Returns: `200 { quotes: T7[], total: int, unfilteredTotal: int, offset: int, limit: int }`
- Returns: `200 { quotes: T8[], total: int, unfilteredTotal: int, offset: int, limit: int }`
#### Create quote — `POST /quote`
- Params: `body: { number: str, date: str, lines: T28[], entityId?: int|null, externalNumber?: str|null }`
- Returns: `201 T6`
- Params: `body: { number: str, date: str, lines: T29[], entityId?: int|null, externalNumber?: str|null }`
- Returns: `201 T7`
#### Delete quote — `DELETE /quote/{id}`
- Params: `id: int`
- Returns: `204 void`
#### Get quote — `GET /quote/{id}`
- Params: `id: int`
- Returns: `200 T6`
- Returns: `200 T7`
#### Update quote — `PATCH /quote/{id}`
- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, externalNumber?: str|null, lines?: T28[] }`
- Returns: `200 T6`
- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, externalNumber?: str|null, lines?: T29[] }`
- Returns: `200 T7`
#### Delete quote file attachment — `DELETE /quote/{id}/file/{fileId}`
- Params: `id: int, fileId: int`
- Returns: `204 void`
#### Create order from quote — `POST /quote/{id}/order`
- Params: `id: int, body?: { number?: str, date?: str, createdAt?: str, entityId?: int|null, externalNumber?: str|null, lines?: T28[] }`
- Params: `id: int, body?: { number?: str, date?: str, createdAt?: str, entityId?: int|null, externalNumber?: str|null, lines?: T29[] }`
- Returns: `201 T1`
#### Generate and attach quote PDF — `POST /quote/{id}/pdf`
- Params: `id: int`
- Returns: `201 T11`
- Returns: `201 T12`
### Section: /shipment
#### List shipments — `GET /shipment`
- Params: `query: offset?: int, limit?: int, search?: str, state?: str, seekMonths?: int`
- Returns: `200 { shipments: { id: int, number: str, type: str, date: str, positions: int, totalQuantity: num, packageCount: int, state: str, entityId?: int|null, externalNumber?: str|null, createdAt?: str|null, orderId?: int|null, orderNumber?: str|null, customerName?: str|null, carrier?: str|null, trackingCode?: str|null }[], total: int, unfilteredTotal: int, offset: int, limit: int }`
#### Delete shipment — `DELETE /shipment/{id}`
- Params: `id: int`
- Returns: `204 void`
#### Get shipment by ID — `GET /shipment/{id}`
- Params: `id: int`
- Returns: `200 { shipment: T5 }`
- Returns: `200 T5`
#### Update shipment state or metadata — `PATCH /shipment/{id}`
- Params: `id: int, body: { state?: str }`
- Returns: `200 T5`
#### Delete shipment file attachment — `DELETE /shipment/{id}/file/{fileId}`
- Params: `id: int, fileId: int`
- Returns: `204 void`
#### Generate and attach shipment PDF (delivery note) — `POST /shipment/{id}/pdf`
- Params: `id: int`
- Returns: `201 T11`
- Returns: `201 T12`
#### List packages of a shipment — `GET /shipment/{id}/shipping`
- Params: `id: int`
- Returns: `200 { shippings: T31[] }`
- Returns: `200 { shippings: T32[] }`
#### Create package for a shipment — `POST /shipment/{id}/shipping`
- Params: `id: int, body: { type: str, state: str, trackingCode?: str, carrier?: str, warehouseId?: int }`
- Returns: `201 T26`
- Returns: `201 T27`
### Section: /shipping
@@ -573,7 +580,7 @@ _none_
- Returns: `204 void`
#### Update shipping — `PATCH /shipping/{id}`
- Params: `id: int, body: { type?: str, state?: str, trackingCode?: str, carrier?: str, warehouseId?: int }`
- Returns: `200 T26`
- Returns: `200 T27`
#### List packages of a shipping — `GET /shipping/{id}/package`
- Params: `id: int`
- Returns: `200 { packages: { id: int, shippingId: int, entityaddressId: int, number: str, type: str, state: str, details?: str|null }[] }`
@@ -591,28 +598,28 @@ _none_
#### Adjust stock manually — `POST /stock/adjust`
- Params: `body: { sku?: str, warehouseId?: int, amount?: num, text?: str|null, lines?: { sku: str, amount: num, warehouseId?: int, text?: str }[] }`
- Returns: `201 { manifest: { id: int, number: str, type: str, date: str, createdAt: str }, lines: { manifestarticle_id: int, sku: str, name: str, warehouse_id: int, amount: num, text: str }[], ledger: T17[] }`
- Returns: `201 { manifest: { id: int, number: str, type: str, date: str, createdAt: str }, lines: { manifestarticle_id: int, sku: str, name: str, warehouse_id: int, amount: num, text: str }[], ledger: T18[] }`
### Section: /supplier
#### List suppliers — `GET /supplier`
_none_
- Returns: `200 { suppliers: T42[] }`
- Returns: `200 { suppliers: T43[] }`
#### Create supplier — `POST /supplier`
- Params: `body: { name: str }`
- Returns: `201 { supplier: T42 }`
- Returns: `201 { supplier: T43 }`
#### Delete supplier — `DELETE /supplier/{id}`
- Params: `id: int`
- Returns: `204 void`
#### Update supplier — `PATCH /supplier/{id}`
- Params: `id: int, body: { name: str }`
- Returns: `200 { supplier: T42 }`
- Returns: `200 { supplier: T43 }`
#### List supplier articles by SKUs — `GET /supplier/{id}/articles`
- Params: `id: int, query: skus?: string`
- Returns: `200 { articles: { id: int, articleId: int, entityId: int, pu: num, sort: int, article: { id: int, sku: str, name?: str|null, slug?: str|null, photos?: { sort: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str }[], eans?: str[] }, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T45|null }[] }`
- Returns: `200 { articles: { id: int, articleId: int, entityId: int, pu: num, sort: int, article: { id: int, sku: str, name?: str|null, slug?: str|null, photos?: { sort: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str }[], eans?: str[] }, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T46|null }[] }`
#### Query supplier articles by SKUs (bulk) — `POST /supplier/{id}/articles`
- Params: `id: int, body?: { skus?: str[] }`
- Returns: `200 { articles: { id: int, articleId: int, entityId: int, pu: num, sort: int, article: { id: int, sku: str, name?: str|null, slug?: str|null, photos?: { sort: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str }[], eans?: str[] }, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T45|null }[] }`
- Returns: `200 { articles: { id: int, articleId: int, entityId: int, pu: num, sort: int, article: { id: int, sku: str, name?: str|null, slug?: str|null, photos?: { sort: int, fullHash: str, thumbW: int, thumbH: int, thumbHash: str }[], eans?: str[] }, supplierName?: str|null, sku?: str|null, stock?: num|null, priceId?: int|null, price?: T46|null }[] }`
### Section: /unit
@@ -621,19 +628,19 @@ _none_
- Returns: `204 void`
#### List units — `GET /unit`
_none_
- Returns: `200 { units: T34[] }`
- Returns: `200 { units: T35[] }`
#### Upsert unit — `PUT /unit`
- Params: `body: { si: str, basesi: str, basesifactor: num, symbol: str, name: str }`
- Returns: `200 { unit: T34 }`
- Returns: `200 { unit: T35 }`
### Section: /warehouse
#### List warehouses — `GET /warehouse`
_none_
- Returns: `200 { warehouses: T46[] }`
- Returns: `200 { warehouses: T47[] }`
#### Create warehouse — `POST /warehouse`
- Params: `body: { name: str, sort?: int }`
- Returns: `201 T44`
- Returns: `201 T45`
#### Reorder warehouses — `PUT /warehouse/order`
- Params: `body: { warehouseIds: int[] }`
- Returns: `200 { warehouseIds: int[] }`
@@ -642,13 +649,13 @@ _none_
- Returns: `204 void`
#### Get warehouse by ID — `GET /warehouse/{id}`
- Params: `id: int`
- Returns: `200 T44`
- Returns: `200 T45`
#### Update warehouse (partial) — `PATCH /warehouse/{id}`
- Params: `id: int, body: { name?: str, sort?: int }`
- Returns: `200 T44`
- Returns: `200 T45`
#### Update warehouse — `PUT /warehouse/{id}`
- Params: `id: int, body: { name?: str, sort?: int }`
- Returns: `200 T44`
- Returns: `200 T45`
### Binary & streaming routes (reachable only via `fetch()` in javascript_execute)
These routes are NOT in the table above because their responses are binary or long-lived streams, which the `dashback_request` tool cannot return usefully. They ARE reachable from inside `javascript_execute` with `fetch("/route")`, where you can decode the bytes, write them to the VFS and embed them in your reply:

View File

@@ -70,7 +70,8 @@ List of shipments
"thumby": 1,
"meta": {}
}
]
],
"state": "new"
}
]
}

View File

@@ -4,9 +4,12 @@ Protected. Requires a valid session cookie (`credentials: 'include'`).
Create shipment for an order
Creates a new partial or full shipment manifest for the order.
Validates that article positions belong to the order and cumulative shipped quantities
do not exceed ordered quantities.
Creates a new shipment manifest (Lieferschein) for an order containing one, some, or all items from the order.
If `lines` is omitted or empty, all remaining unshipped items from the order are included automatically.
On individual line items, `amount` is optional and defaults to the remaining unshipped quantity for that article.
Auto-assigns the shipment number formatted as `<order_number><shipment_prefix><index>`, e.g. `AUF-000001-L-1`.
Updates the materialized `ordersummary` table (`shipped_quantity`, `is_shipped`) and emits SSE events
(`order`, `shipment`) so that the order list and summary tables are rerendered in real time.
## Path parameters
@@ -15,15 +18,15 @@ do not exceed ordered quantities.
|-------|----------|------|-------------|
| `id` | yes | integer | Order ID |
## Body (JSON)
## Body (JSON) — _optional_
| Field | Required | Type | Description |
|-------|----------|------|-------------|
| `date` | no | string | |
| `externalNumber` | no | string | |
| `lines` | yes | object[] | |
| `lines[].sku` | yes | string | |
| `lines[].amount` | yes | number | |
| `date` | no | string | Optional shipment date (defaults to current date) |
| `externalNumber` | no | string | Optional external delivery note reference (defaults to order.externalNumber or order.number) |
| `lines` | no | object[] | Optional positions to ship. If omitted, all remaining unshipped items are shipped. |
| `lines[].sku` | yes | string | Article SKU |
| `lines[].amount` | no | number | Quantity to ship. Defaults to remaining unshipped quantity for this SKU. |
| `lines[].name` | no | string | |
| `lines[].pu` | no | number | |
| `lines[].net` | no | number | |
@@ -107,7 +110,8 @@ Created shipment
"thumby": 1,
"meta": {}
}
]
],
"state": "new"
}
}
```
@@ -119,7 +123,7 @@ Created shipment
| 400 | Validation error or article not in order — `{"error":"…"}` |
| 401 | Unauthorized — `{"error":"…"}` |
| 404 | Order not found — `{"error":"…"}` |
| 409 | Cumulative shipment amount exceeds ordered amount — `{"error":"…"}` |
| 409 | Cumulative shipment amount exceeds ordered amount, or all items are already shipped — `{"error":"…"}` |
---

View File

@@ -160,7 +160,8 @@ Created order
"thumby": 1,
"meta": {}
}
]
],
"state": "new"
}
],
"files": [

View File

@@ -134,7 +134,8 @@ Order
"thumby": 1,
"meta": {}
}
]
],
"state": "new"
}
],
"files": [

View File

@@ -143,7 +143,8 @@ Order list
"thumby": 1,
"meta": {}
}
]
],
"state": "new"
}
],
"files": [

View File

@@ -154,7 +154,8 @@ Updated order
"thumby": 1,
"meta": {}
}
]
],
"state": "new"
}
],
"files": [

View File

@@ -5,8 +5,10 @@ Protected. Requires a valid session cookie (`credentials: 'include'`).
Create order from quote
Creates a sales order from an existing quote for the authenticated user's selected company.
Copies lines, customer entity, and external number from the quote unless explicitly overridden.
Copies lines and customer entity from the quote.
Sets external reference (externalNumber) to the quote number unless explicitly overridden.
If the order number is omitted, it is auto-allocated from the sequence.
Fails with 400 (No entity selected) if neither the quote nor the request body specifies a customer entity.
## Path parameters
@@ -23,7 +25,7 @@ If the order number is omitted, it is auto-allocated from the sequence.
| `date` | no | string | Optional order date (ISO format). Defaults to current date. |
| `createdAt` | no | string | Optional creation timestamp. |
| `entityId` | no | integer | Customer entity ID override. Defaults to quote's entityId. |
| `externalNumber` | no | string | External customer reference override. Defaults to quote's externalNumber. |
| `externalNumber` | no | string | External customer reference override. Defaults to quote's number. |
| `lines` | no | ManifestLineInput[] | Optional line items override. Defaults to quote's lines. |
```json
@@ -170,7 +172,8 @@ Created order
"thumby": 1,
"meta": {}
}
]
],
"state": "new"
}
],
"files": [
@@ -199,7 +202,7 @@ Created order
| Status | Description |
|--------|-------------|
| 400 | No company selected, invalid quote id, or invalid order data — `{"error":"…"}` |
| 400 | No company selected, no entity selected, invalid quote id, or invalid order data — `{"error":"…"}` |
| 401 | Unauthorized — `{"error":"…"}` |
| 403 | Not authorized for company — `{"error":"…"}` |
| 404 | Quote not found or entity not found — `{"error":"…"}` |

View File

@@ -0,0 +1,64 @@
# `GET /shipment`
Protected. Requires a valid session cookie (`credentials: 'include'`).
List shipments
Company-wide paginated list of shipment manifests (`manifest` rows with `type = 'shipment'`)
with delivery state, package tracking info, and order references.
## Query parameters
| Param | Required | Type | Description |
|-------|----------|------|-------------|
| `offset` | no | integer | Number of shipments to skip |
| `limit` | no | integer | Number of shipments to return |
| `search` | no | string | Free-text search matching shipment number, order number, external number, tracking code, or customer name |
| `state` | no | string | Optional filter by delivery state |
| `seekMonths` | no | integer | Negative integer for cutoff months ago (e.g. -1 for shipments older than 1 month) |
## Response `200`
Paginated shipment list
```json
{
"shipments": [
{
"id": 1,
"number": "…",
"type": "shipment",
"entityId": 1,
"externalNumber": "…",
"date": "…",
"createdAt": "…",
"orderId": 1,
"orderNumber": "…",
"customerName": "…",
"positions": 1,
"totalQuantity": 1,
"packageCount": 1,
"carrier": "…",
"trackingCode": "…",
"state": "new"
}
],
"total": 1,
"unfilteredTotal": 1,
"offset": 1,
"limit": 1
}
```
## Errors
| Status | Description |
|--------|-------------|
| 400 | Invalid query parameters or no company selected — `{"error":"…"}` |
| 401 | Unauthorized — `{"error":"…"}` |
| 403 | Not authorized — `{"error":"…"}` |
---
_Generated from `@openapi` JSDoc. Do not edit by hand — run `npm run docs:api`._

View File

@@ -69,7 +69,8 @@ Shipment details
"thumby": 1,
"meta": {}
}
]
],
"state": "new"
}
}
```

View File

@@ -0,0 +1,106 @@
# `PATCH /shipment/{id}`
Protected. Requires a valid session cookie (`credentials: 'include'`).
Update shipment state or metadata
Updates delivery state (`new`, `delivered`, `returned`) for the shipment.
Emits SSE events (`shipment`, `order`) so connected clients rerender in real time.
## Path parameters
| Param | Required | Type | Description |
|-------|----------|------|-------------|
| `id` | yes | integer | Shipment ID |
## Body (JSON)
| Field | Required | Type | Description |
|-------|----------|------|-------------|
| `state` | no | string | Delivery state |
```json
{
"state": "delivered"
}
```
## Signals
On success, emits SSE signals: `shipment`, `order` (see [`GET /events`](../events.md)).
## Response `200`
Updated shipment
```json
{
"shipment": {
"id": 1,
"number": "…",
"type": "shipment",
"entityId": 1,
"externalNumber": "…",
"date": "…",
"createdAt": "…",
"lineCount": 1,
"packageCount": 1,
"lines": [
{
"id": 1,
"sku": "…",
"name": "…",
"pu": 1,
"amount": 1,
"net": 1,
"rebate": 1,
"taxrate": 1,
"comment": "…"
}
],
"shippings": [
{
"id": 1,
"manifestId": 1,
"number": "…",
"trackingCode": "…",
"carrier": "…",
"type": "…",
"state": "…"
}
],
"files": [
{
"id": 1,
"manifestId": 1,
"fileId": 1,
"sort": 1,
"hash": "…",
"mimetype": "…",
"name": "…",
"size": 1,
"created": "2026-08-10T00:00:00.000Z",
"modified": "2026-08-10T00:00:00.000Z",
"skeledash": "…",
"thumbx": 1,
"thumby": 1,
"meta": {}
}
],
"state": "new"
}
}
```
## Errors
| Status | Description |
|--------|-------------|
| 400 | Invalid state, invalid ID, or no company selected — `{"error":"…"}` |
| 401 | Unauthorized — `{"error":"…"}` |
| 404 | Shipment not found — `{"error":"…"}` |
---
_Generated from `@openapi` JSDoc. Do not edit by hand — run `npm run docs:api`._

View File

@@ -1310,6 +1310,56 @@
* description: Attached documents (e.g. shipment label PDF) for the shipment
* items:
* $ref: '#/components/schemas/DeliveryFile'
* state:
* type: string
* enum: [new, delivered, returned]
* description: Delivery state
* ShipmentSummary:
* type: object
* required: [id, number, type, date, state, positions, totalQuantity, packageCount]
* properties:
* id:
* type: integer
* number:
* type: string
* type:
* type: string
* enum: [shipment]
* entityId:
* type: integer
* nullable: true
* externalNumber:
* type: string
* nullable: true
* date:
* type: string
* createdAt:
* type: string
* nullable: true
* orderId:
* type: integer
* nullable: true
* orderNumber:
* type: string
* nullable: true
* customerName:
* type: string
* nullable: true
* positions:
* type: integer
* totalQuantity:
* type: number
* packageCount:
* type: integer
* carrier:
* type: string
* nullable: true
* trackingCode:
* type: string
* nullable: true
* state:
* type: string
* enum: [new, delivered, returned]
* Package:
* type: object
* required: [id, shippingId, entityaddressId, number, type, state]

View File

@@ -15,6 +15,8 @@ function requireSelectedCompany(req) {
function quoteErrorStatus(error) {
if (error.message === 'No company selected') return 400;
if (error.message === 'No entity selected') return 400;
if (error.message === 'Entity required') return 400;
if (error.message === 'Not authorized') return 403;
if (error.message === 'Company not found') return 404;
if (error.message === 'Quote not found') return 404;
@@ -581,8 +583,10 @@ export function register(app, basePath = '') {
* summary: Create order from quote
* description: |
* Creates a sales order from an existing quote for the authenticated user's selected company.
* Copies lines, customer entity, and external number from the quote unless explicitly overridden.
* Copies lines and customer entity from the quote.
* Sets external reference (externalNumber) to the quote number unless explicitly overridden.
* If the order number is omitted, it is auto-allocated from the sequence.
* Fails with 400 (No entity selected) if neither the quote nor the request body specifies a customer entity.
* security:
* - cookieAuth: []
* parameters:
@@ -616,7 +620,7 @@ export function register(app, basePath = '') {
* externalNumber:
* type: string
* nullable: true
* description: External customer reference override. Defaults to quote's externalNumber.
* description: External customer reference override. Defaults to quote's number.
* lines:
* type: array
* description: Optional line items override. Defaults to quote's lines.
@@ -634,7 +638,7 @@ export function register(app, basePath = '') {
* order:
* $ref: '#/components/schemas/Order'
* 400:
* description: No company selected, invalid quote id, or invalid order data
* description: No company selected, no entity selected, invalid quote id, or invalid order data
* content:
* application/json:
* schema:

View File

@@ -27,7 +27,11 @@ function shipmentErrorStatus(error) {
if (
error.message?.endsWith(' required') ||
error.message?.startsWith('Article (') ||
error.message?.includes('Invalid lines')
error.message?.includes('Invalid lines') ||
error.message === 'Invalid state' ||
error.message === 'Invalid offset' ||
error.message === 'Invalid limit' ||
error.message === 'Invalid seekMonths'
) {
return 400;
}
@@ -134,9 +138,12 @@ export function register(app, basePath = '') {
* tags: [Shipment]
* summary: Create shipment for an order
* description: |
* Creates a new partial or full shipment manifest for the order.
* Validates that article positions belong to the order and cumulative shipped quantities
* do not exceed ordered quantities.
* Creates a new shipment manifest (Lieferschein) for an order containing one, some, or all items from the order.
* If `lines` is omitted or empty, all remaining unshipped items from the order are included automatically.
* On individual line items, `amount` is optional and defaults to the remaining unshipped quantity for that article.
* Auto-assigns the shipment number formatted as `<order_number><shipment_prefix><index>`, e.g. `AUF-000001-L-1`.
* Updates the materialized `ordersummary` table (`shipped_quantity`, `is_shipped`) and emits SSE events
* (`order`, `shipment`) so that the order list and summary tables are rerendered in real time.
* security:
* - cookieAuth: []
* parameters:
@@ -147,28 +154,32 @@ export function register(app, basePath = '') {
* type: integer
* description: Order ID
* requestBody:
* required: true
* required: false
* content:
* application/json:
* schema:
* type: object
* required: [lines]
* properties:
* date:
* type: string
* format: date
* description: Optional shipment date (defaults to current date)
* externalNumber:
* type: string
* description: Optional external delivery note reference (defaults to order.externalNumber or order.number)
* lines:
* type: array
* description: Optional positions to ship. If omitted, all remaining unshipped items are shipped.
* items:
* type: object
* required: [sku, amount]
* required: [sku]
* properties:
* sku:
* type: string
* description: Article SKU
* amount:
* type: number
* description: Quantity to ship. Defaults to remaining unshipped quantity for this SKU.
* name:
* type: string
* pu:
@@ -210,7 +221,7 @@ export function register(app, basePath = '') {
* schema:
* $ref: '#/components/schemas/Error'
* 409:
* description: Cumulative shipment amount exceeds ordered amount
* description: Cumulative shipment amount exceeds ordered amount, or all items are already shipped
* content:
* application/json:
* schema:
@@ -245,6 +256,157 @@ export function register(app, basePath = '') {
// #endregion
/**
* @openapi
* /shipment:
* get:
* tags: [Shipment]
* summary: List shipments
* description: |
* Company-wide paginated list of shipment manifests (`manifest` rows with `type = 'shipment'`)
* with delivery state, package tracking info, and order references.
* security:
* - cookieAuth: []
* parameters:
* - in: query
* name: offset
* schema:
* type: integer
* default: 0
* minimum: 0
* description: Number of shipments to skip
* - in: query
* name: limit
* schema:
* type: integer
* default: 50
* minimum: 1
* maximum: 100
* description: Number of shipments to return
* - in: query
* name: search
* schema:
* type: string
* description: Free-text search matching shipment number, order number, external number, tracking code, or customer name
* - in: query
* name: state
* schema:
* type: string
* enum: [new, delivered, returned]
* description: Optional filter by delivery state
* - in: query
* name: seekMonths
* schema:
* type: integer
* description: Negative integer for cutoff months ago (e.g. -1 for shipments older than 1 month)
* responses:
* 200:
* description: Paginated shipment list
* content:
* application/json:
* schema:
* type: object
* required: [shipments, total, unfilteredTotal, offset, limit]
* properties:
* shipments:
* type: array
* items:
* $ref: '#/components/schemas/ShipmentSummary'
* total:
* type: integer
* unfilteredTotal:
* type: integer
* offset:
* type: integer
* limit:
* type: integer
* 400:
* description: Invalid query parameters or no company selected
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Error'
* 401:
* description: Unauthorized
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Error'
* 403:
* description: Not authorized
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Error'
*/
// #region GET /shipment
app.get(`${basePath}/shipment`, async (req, res) => {
const selected = requireSelectedCompany(req);
if (selected.error) {
return res.status(400).json({ error: selected.error });
}
const rawOffset = req.query.offset;
const rawLimit = req.query.limit;
let offset = 0;
let limit = 50;
if (rawOffset !== undefined) {
offset = parseInt(rawOffset, 10);
if (!Number.isInteger(offset) || offset < 0) {
return res.status(400).json({ error: 'offset must be an integer >= 0' });
}
}
if (rawLimit !== undefined) {
limit = parseInt(rawLimit, 10);
if (!Number.isInteger(limit) || limit < 1 || limit > 100) {
return res.status(400).json({ error: 'limit must be an integer between 1 and 100' });
}
}
const search = typeof req.query.search === 'string' && req.query.search.trim() !== ''
? req.query.search.trim()
: undefined;
let state = undefined;
if (typeof req.query.state === 'string' && req.query.state.trim() !== '') {
const trimmedState = req.query.state.trim().toLowerCase();
if (!['new', 'delivered', 'returned'].includes(trimmedState)) {
return res.status(400).json({ error: 'Invalid state' });
}
state = trimmedState;
}
let seekMonths = undefined;
if (req.query.seekMonths !== undefined && req.query.seekMonths !== '') {
const parsedSeek = parseInt(req.query.seekMonths, 10);
if (!Number.isInteger(parsedSeek)) {
return res.status(400).json({ error: 'seekMonths must be an integer' });
}
seekMonths = parsedSeek;
}
try {
const result = await db.list(req.user.id, {
offset,
limit,
search,
state,
seekMonths,
});
res.status(200).json(result);
} catch (error) {
const status = shipmentErrorStatus(error);
if (status === 500) console.error('List shipments failed:', error);
res.status(status).json({ error: error.message });
}
});
// #endregion
/**
* @openapi
* /shipment/{id}:
@@ -315,6 +477,102 @@ export function register(app, basePath = '') {
// #endregion
/**
* @openapi
* /shipment/{id}:
* patch:
* tags: [Shipment]
* summary: Update shipment state or metadata
* description: |
* Updates delivery state (`new`, `delivered`, `returned`) for the shipment.
* Emits SSE events (`shipment`, `order`) so connected clients rerender in real time.
* security:
* - cookieAuth: []
* x-signals: [shipment, order]
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: Shipment ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* state:
* type: string
* enum: [new, delivered, returned]
* description: Delivery state
* example:
* state: delivered
* responses:
* 200:
* description: Updated shipment
* content:
* application/json:
* schema:
* type: object
* properties:
* shipment:
* $ref: '#/components/schemas/Shipment'
* 400:
* description: Invalid state, invalid ID, or no company selected
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Error'
* 401:
* description: Unauthorized
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Error'
* 404:
* description: Shipment not found
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Error'
*/
// #region PATCH /shipment/:id
app.patch(`${basePath}/shipment/:id`, async (req, res) => {
const selected = requireSelectedCompany(req);
if (selected.error) {
return res.status(400).json({ error: selected.error });
}
const parsedId = parsePositiveInt(req.params.id, 'id');
if (parsedId.error) {
return res.status(400).json({ error: parsedId.error });
}
const { state } = req.body ?? {};
if (state !== undefined) {
if (typeof state !== 'string' || !['new', 'delivered', 'returned'].includes(state.trim().toLowerCase())) {
return res.status(400).json({ error: 'Invalid state' });
}
}
try {
const shipment = await db.update(req.user.id, parsedId.id, {
state: state ? state.trim().toLowerCase() : undefined,
});
emitShipmentEvents(selected.companyId);
res.status(200).json({ shipment });
} catch (error) {
const status = shipmentErrorStatus(error);
if (status === 500) console.error('Update shipment failed:', error);
res.status(status).json({ error: error.message });
}
});
// #endregion
/**
* @openapi
* /shipment/{id}:

View File

@@ -155,6 +155,11 @@ export async function createFromQuote(googleAuthId, quoteId, data) {
return enrichSingleOrder(store, googleAuthId, order);
}
export async function createShipment(googleAuthId, orderId, data) {
const store = await getStore();
return store.order.createShipment(googleAuthId, orderId, data);
}
export async function update(googleAuthId, id, data) {
const store = await getStore();
const order = await store.order.update(googleAuthId, id, data);

View File

@@ -1,6 +1,16 @@
import { getStore } from './store.js';
import { formatAttachments } from '../util/manifestAttachment.js';
export async function list(googleAuthId, opts) {
const store = await getStore();
return store.shipment.list(googleAuthId, opts);
}
export async function update(googleAuthId, id, patch) {
const store = await getStore();
return store.shipment.update(googleAuthId, id, patch);
}
export async function create(googleAuthId, data) {
const store = await getStore();
return store.shipment.create(googleAuthId, data);