This commit is contained in:
seb
2026-09-27 16:19:43 +02:00
parent 69f27a2942
commit 3e64fff747
13 changed files with 697 additions and 7 deletions

View File

@@ -91,6 +91,10 @@
{
"name": "Stock",
"description": "Manual stock additions and removals"
},
{
"name": "Serper",
"description": "Serper Google image search and thumbnail streaming"
}
],
"paths": {
@@ -986,6 +990,142 @@
}
}
},
"/serper/images": {
"post": {
"tags": [
"Serper"
],
"summary": "Search images via Serper.dev and stream WebP thumbnails (SSE)",
"description": "Queries Google Image search via `https://google.serper.dev/images` using the\ncompany setting `keys.serper` (or server `SERPER_API_KEY`), and streams the\nresults via Server-Sent Events (`text/event-stream`).\n\n1. First emits an `images` event with the full search result list (including `imageUrl`).\n2. Then streams `thumb` events with WebP base64 thumbnails (max 200×200) as they are generated.\n3. Emits `done` when all thumbnails have completed (or `error` on failure).\n",
"security": [
{
"cookieAuth": []
}
],
"x-markdown": "serper/images.md",
"x-sse-events": [
{
"name": "images",
"description": "First event; list of search result images with id, url, width, and height",
"payload": "{ \"images\": [ { \"id\": 0, \"url\": \"…\", \"width\": 1000, \"height\": 800 } ] }"
},
{
"name": "thumb",
"description": "Emitted for each image as its 200×200 max WebP thumbnail is generated",
"payload": "{ \"id\": 0, \"dataUrl\": \"data:image/webp;base64,…\" }"
},
{
"name": "done",
"description": "Emitted after all thumbnails have finished streaming; closes the SSE stream",
"payload": "{ \"total\": 100 }"
},
{
"name": "error",
"description": "Emitted when an error occurs during Serper request or processing",
"payload": "{ \"error\": \"…\" }"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"q"
],
"properties": {
"q": {
"type": "string",
"description": "Image search query (e.g. \"Purize logo\")"
},
"gl": {
"type": "string",
"default": "de",
"description": "Country code"
},
"hl": {
"type": "string",
"default": "de",
"description": "Language code"
},
"num": {
"type": "integer",
"default": 100,
"minimum": 1,
"maximum": 100,
"description": "Number of search results to fetch"
},
"preferSource": {
"type": "boolean",
"default": false,
"description": "Whether to prefer downloading from the full imageUrl before falling back to Google thumbnailUrl"
}
},
"example": {
"q": "Purize logo",
"gl": "de",
"hl": "de",
"num": 100
}
}
}
}
},
"responses": {
"200": {
"description": "`text/event-stream` — emits `images`, `thumb`, `done` (and `error` on failure).\n",
"content": {
"text/event-stream": {
"schema": {
"type": "string"
}
}
}
},
"400": {
"description": "Query missing, invalid input, or Serper API key not configured",
"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"
}
}
}
},
"404": {
"description": "Company not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/quote": {
"get": {
"tags": [
@@ -6617,7 +6757,7 @@
"CompanySetting"
],
"summary": "Upsert company setting",
"description": "Sets (upserts) a company setting for the selected company.\nOnly a fixed allow-list of keys can be set: `ui.theme`, `keys.tavily`,\n`keys.openrouter`, `labelprinter.addr`, `labelprinter.type`.\n",
"description": "Sets (upserts) a company setting for the selected company.\nOnly a fixed allow-list of keys can be set: `ui.theme`, `keys.tavily`,\n`keys.openrouter`, `keys.serper`, `labelprinter.addr`, `labelprinter.type`.\n",
"security": [
{
"cookieAuth": []
@@ -10834,11 +10974,43 @@
}
]
},
"BrandPic": {
"type": "object",
"required": [
"id",
"sort",
"fullHash",
"thumbW",
"thumbH",
"thumbHash"
],
"properties": {
"id": {
"type": "integer"
},
"sort": {
"type": "integer"
},
"fullHash": {
"type": "string"
},
"thumbW": {
"type": "integer"
},
"thumbH": {
"type": "integer"
},
"thumbHash": {
"type": "string"
}
}
},
"Brand": {
"type": "object",
"required": [
"id",
"name"
"name",
"pics"
],
"properties": {
"id": {
@@ -10850,6 +11022,13 @@
"gsprpinfo": {
"type": "string",
"nullable": true
},
"pics": {
"type": "array",
"description": "Brand pictures sorted by sort",
"items": {
"$ref": "#/components/schemas/BrandPic"
}
}
}
},