Cross-site register now updates the password to the signup value and documents passwordUpdated for storefronts. Co-authored-by: Cursor <cursoragent@cursor.com>
5.5 KiB
Meshkee Website API — AI / designer brief
Copy everything below into a new AI chat when building a Meshkee storefront.
System context (paste this)
You are building a Meshkee business website (storefront). You must use the Meshkee Website API only — never invent admin/CMS endpoints.
Canonical docs (always prefer these):
- Hub: https://api.meshkee.com/docs/website
- OpenAPI: https://api.meshkee.com/docs/website/openapi.json
- Postman: https://api.meshkee.com/docs/website/Meshkee-Website-API.postman_collection.json
API base URL: https://api.meshkee.com/api/v1
(Optional alias if configured: https://api.<WEBSITE_DOMAIN>/api/v1 — same backend.)
This website’s apex domain: <WEBSITE_DOMAIN>
(example: sanihome.ir — no www., no api., no customer., no business.)
Hard rules
- Resolve tenant first:
GET /tenants/<WEBSITE_DOMAIN>→ savebusinessIdfromid. - All public content uses
/tenants/<WEBSITE_DOMAIN>/...(no auth). - Cart, orders, favorites use
/businesses/<businessId>/...withAuthorization: Bearer <accessToken>. - Customer register body must include
"domain": "<WEBSITE_DOMAIN>". If the cell already exists on another Meshkee site and the password differs, API returns409withCELL_EXISTS_OTHER_SITE:.... Retry register with"acknowledgeExistingAccount": trueto link that account (profile unchanged; password is replaced with the new signup password), then complete SMS OTP. - Cell numbers are E.164 (
+98912...). - Do not call dashboard/CMS routes (
/businesses/.../productswrite APIs, media upload, domain-admin, etc.). - Partner SMS (
POST /public/sms/send) is for external partner backends with an issuedX-Api-Keyonly — not for normal storefront UI. See https://api.meshkee.com/docs/website/SMS.md
Typical bootstrap sequence
GET /tenants/{domain}→ branding +businessId+specialProductsSource(productorstore_item)- Homepage: business-info, static-images, sliders, category-groups, brand-groups, store-specials (
sourcerepeats the tenant setting; items are store listings whensourceisstore_item) - Catalog: categories, products (
GET /products/{slug}includesrelatedProducts: same category then same brand, in-stock first), store-items (nameinstant search: in-stock first, thenupdatedAt), user-products (customer stock listings) - Auth: register/login → store tokens. Optional:
POST /auth/send-otpthenPOST /auth/login-otp(passwordless) orPOST /auth/reset-password(forgot password).POST /auth/verify-otponly marks the cell verified (no tokens). - Cart checkout with
addressIdor inlineshippingAddress+payment- For online pay:
payment.type = "e_payment_gate",gatewayType(e.g."mellat"or"zarinpal"), and absolutereturnUrl - Response includes
payment.redirect{ method, url, fields }— POST/redirect shopper to the bank - Bank callback hits API then redirects to
returnUrl?status=success|failed&orderId=… - Enabled gateways:
GET /tenants/{domain}→ePayment, orGET /businesses/{businessId}/payments/methods
- For online pay:
User products (customer listings)
Public marketplace listings owned by customers — not catalog products.
GET /tenants/{domain}/user-products— list published (name/q,categoryId,cityId,countryId,condition,promoted, pagination)GET /tenants/{domain}/user-products/{slug}— details + galleryGET /tenants/{domain}/user-products/{slug}/technical-info— category form + values Use product categories fromGET /tenants/{domain}/categories?entityType=productfor filters. Creating/editing listings is customer-dashboard only (/businesses/.../my-user-products), not website-facing.
Static images
Named slots the business dashboard can replace. Fetch once per page:
GET /tenants/{domain}/website/static-images— all slotsGET /tenants/{domain}/website/static-images?pageKey=home— slots for one page (home,products,about, …)GET /tenants/{domain}/website/static-images/{key}— one slot (e.g.home-hero)
Use slot.key in the placeholder. Match pageKey to the website page. For a single image: images[0]?.url. For a list: map images (if itemCount is set, that many images are expected). Each image may include titleFa, titleEn, subtext, and linkUrl. If linkUrl is set, wrap in <a href={linkUrl}>. Pick titleFa or titleEn from the site locale. If images is empty, keep the local fallback.
Also publish a slot catalog on this website so the business dashboard Refresh button can import keys from the main domain:
GET https://<WEBSITE_DOMAIN>/meshkee/static-image-slots
{
"slots": [
{
"key": "slider",
"label": "Homepage slider",
"kind": "list",
"pageKey": "home",
"aspectRatio": "16:9",
"itemCount": null,
"recommendedWidth": 1440
},
{
"key": "home-side-banner",
"label": "Side banner",
"kind": "single",
"pageKey": "home",
"aspectRatio": "12:19",
"itemCount": 1,
"recommendedWidth": 480
}
]
}
kind is single (one image) or list (duplicatable). For a fixed row, set itemCount (e.g. 2). Leave itemCount null for an unbounded slider. aspectRatio must look like 16:9. Do not invent CMS/upload APIs.
If OpenAPI and this brief conflict, OpenAPI wins.
What to tell each website team
Replace <WEBSITE_DOMAIN> once per project. Everything else is global — same Postman, same OpenAPI, same base URL.