Add Torob Product API v3 for store-module sites with a store setting to enable it.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-09-03 15:26:23 +03:30
co-authored by Cursor
parent 6f1b13b6dc
commit 42cf29bc4e
28 changed files with 1080 additions and 62 deletions
+1
View File
@@ -28,6 +28,7 @@ You are building a **Meshkee business website (storefront)**. You must use the M
6. Do not call dashboard/CMS routes (`/businesses/.../products` write APIs, media upload, domain-admin, etc.).
7. **Partner SMS** (`POST /public/sms/send`) is for external partner backends with an issued `X-Api-Key` only — not for normal storefront UI. See https://api.meshkee.com/docs/website/SMS.md
8. **Technical details (labels + values):** Product/user-product detail responses may include `technicalValues` with **values only** (`fieldId` + `textValue` / `optionId` / `optionIds` — **no field labels**). To render a label→value specs table you **must** call the matching `.../technical-info` endpoint and join `form.fields[].id` ↔ `values[].fieldId`. Never invent a separate “variation fields” or “category fields” public route — those do not exist on the website API.
9. **Torob:** Do **not** add a Next.js route for `/torob_api`. Meshkee nginx on the store apex proxies `POST /torob_api/v3/products` to the API. Only businesses with the **store** module **and** Store settings → Torob switch on return products (otherwise 404). Storefront UI must not call this endpoint.
### Typical bootstrap sequence
1. `GET /tenants/{domain}` → branding + `businessId` + `specialProductsSource` (`product` or `store_item`)
@@ -1487,6 +1487,37 @@
}
]
},
{
"name": "Torob",
"item": [
{
"name": "Product API v3 (store module)",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "X-Torob-Token",
"value": "{{torobJwt}}"
},
{
"key": "X-Torob-Token-Version",
"value": "1"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"page\": 1,\n \"sort\": \"date_added_desc\"\n}"
},
"url": "{{baseUrl}}/tenants/{{domain}}/torob_api/v3/products",
"description": "Torob-only. 404 if the tenant does not have the store module. Prefer the shop-domain URL POST https://{domain}/torob_api/v3/products after nginx is patched."
}
}
]
},
{
"name": "Homepage",
"item": [
+11
View File
@@ -118,6 +118,17 @@
There is no public <code>product-category-variation-fields</code> route.
</p>
<h2>Torob (price comparison)</h2>
<p>
<code>POST /tenants/{domain}/torob_api/v3/products</code> is for
<strong>Torob</strong>, not storefront JavaScript. On the live shop,
nginx proxies <code>POST https://{domain}/torob_api/v3/products</code>
to that API. It only returns catalog store items when the business has
the <strong>store</strong> module enabled <em>and</em> Store settings →
Torob is on; otherwise 404.
Do not implement this path in Next.js.
</p>
<h2>For a new website AI / designer</h2>
<ol>
<li>Open <a href="/docs/website/AI_PROMPT.md">AI_PROMPT.md</a> and paste it into the AI chat.</li>
+109
View File
@@ -44,6 +44,10 @@
{
"name": "Store"
},
{
"name": "Torob",
"description": "Product API v3 for Torob. Called by Torob (not storefront JS). Nginx on the shop apex proxies POST /torob_api/v3/products. Only tenants with the store module enabled; otherwise 404."
},
{
"name": "Blogs"
},
@@ -1422,6 +1426,111 @@
}
}
},
"/tenants/{domain}/torob_api/v3/products": {
"post": {
"tags": [
"Torob"
],
"summary": "Torob Product API v3 (store module only)",
"description": "Torob POSTs here (or to `https://{domain}/torob_api/v3/products` which nginx proxies). JWT in `X-Torob-Token` (EdDSA, aud = shop host). Returns 404 when the tenant does not have the **store** module. Page size is 100.",
"parameters": [
{
"$ref": "#/components/parameters/domain"
},
{
"name": "X-Torob-Token",
"in": "header",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "X-Torob-Token-Version",
"in": "header",
"schema": {
"type": "string",
"example": "1"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"type": "object",
"required": [
"page",
"sort"
],
"properties": {
"page": {
"type": "integer",
"minimum": 1
},
"sort": {
"type": "string",
"enum": [
"date_added_desc",
"date_updated_desc"
]
}
}
},
{
"type": "object",
"required": [
"page_urls"
],
"properties": {
"page_urls": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
}
}
},
{
"type": "object",
"required": [
"page_uniques"
],
"properties": {
"page_uniques": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
}
}
}
]
}
}
}
},
"responses": {
"200": {
"description": "{ api_version: torob_api_v3, current_page, total, max_pages, products[] }"
},
"400": {
"description": "{ error: string }"
},
"401": {
"description": "Invalid or missing Torob JWT"
},
"404": {
"description": "Unknown domain, store module off, or Torob switch off in store settings"
}
}
}
},
"/tenants/{domain}/blogs": {
"get": {
"tags": [