Sample request and response payloads for /lookup, /draft, and /coupon with POS orders included.
Authenticated subscription reads use the signed-in bearer token and workspace access rules, not a service-role key. Configure SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY in production; the existing VITE_SUPABASE_URL and VITE_SUPABASE_PUBLISHABLE_KEY build settings are supported as a public fallback. Both must point to the same project as browser sign-in. Redeploy Vercel after changing settings; publishing the Lovable site does not update replizen.com.
All mobile routes take Authorization: Bearer (a user session or an extension token) plus x-extension-version, and return the standard error shape. POST /api/public/studio/jobs accepts { mode, preset | prompt, productId + storeConnectionId (+ variantId?) } or { catalogProductId } and returns { id, state: "queued" }; poll GET /api/public/studio/jobs/{id} for { id, state, assetUrl, expiresAt, caption, product } (asset URLs stay valid 1 hour; 50 jobs/workspace/day). POST /api/public/studio/jobs/{id}/approve is owner/admin only and idempotent. GET /api/public/catalogs returns { catalogs: [{ id, title, kind, productCount, url, lastSyncedAt }] } — the URL is a public read-only page with product title, price, photo and availability only. POST /api/public/translate takes { text (≤2000 chars), targetLanguage } and returns { text, targetLanguage }; any major written language, 30 requests/minute per workspace. POST /api/public/extension-token (full session only, never an extension token) mints a 15-minute extension-scoped token accepted by the studio, catalog, translate, products, inventory, draft and draft/suggestions routes only (never account, billing or admin). Membership is re-checked on every request, and a suspended (banned) account's extension token is rejected immediately with account_suspended (403) rather than working until expiry.
/admin/users supports account invitations, profile editing, password-reset emails, banning, and confirmed deletion. Writes require platform_admin authorization and a server-only service key. Invitations return to the same website's /auth page; configure that redirect and Supabase email delivery. No workspace or staff role is assigned. Deletion protects self, staff, and workspace owners and preserves workspace usage history. Creation and editing use createAdminUser and updateAdminUser server-function calls, not public extension endpoints. Account changes are audited before execution.
lookupOutcome field — "success" when we found a customer or orders, or "empty" when nothing matched (quota is refunded automatically; render the No match state).Success · request{ "email": "jane@example.com", "stores": [ "all" ] }
Success · response (lookupOutcome: success){ "ok": true, "customer": { "email": "jane@example.com", "name": "Jane Doe", "phone": "+1 555-0199", "lifetime_value_cents": 24780, "order_count": 4 }, "orders": [ { "platform": "shopify", "store_label": "Main Store", "order_id": "#1001", "external_order_id": "shpfy_1001", "status": "fulfilled", "fulfillment_status": "delivered", "financial_status": "paid", "currency": "USD", "total_cents": 12500, "created_at": "2025-07-10T14:23:00Z", "items": [ { "name": "Hydrating Face Serum", "quantity": 1, "unit_price_cents": 9800, "sku": "FACE-SER-30" } ], "shipping_address": { "name": "Jane Doe", "line1": "123 Maple St", "city": "Austin", "province": "TX", "zip": "78701", "country": "US" }, "tracking_url": "https://track.example.com/ABC123" }, { "platform": "square", "store_label": "Austin Pop-up", "order_id": "sq_ord_2aBcD3eFgH4", "external_order_id": "sq_ord_2aBcD3eFgH4", "status": "completed", "fulfillment_status": "picked_up", "financial_status": "paid", "currency": "USD", "total_cents": 4500, "created_at": "2025-07-15T18:45:00Z", "items": [ { "name": "Mini Moisturizer", "quantity": 2, "unit_price_cents": 2250, "sku": "MOIST-MINI-50" } ], "location": "Austin Pop-up", "tender_type": "CARD", "receipt_url": "https://squareup.com/receipt/abcd1234" }, { "platform": "clover", "store_label": "Clover HQ", "order_id": "clv_ORD-ABCDEFG", "external_order_id": "clv_ORD-ABCDEFG", "status": "paid", "fulfillment_status": "in_store", "financial_status": "paid", "currency": "USD", "total_cents": 6780, "created_at": "2025-07-18T12:12:00Z", "items": [ { "name": "Cleansing Balm", "quantity": 1, "unit_price_cents": 6780, "sku": "BALM-CLN-100" } ], "location": "Clover HQ", "employee_name": "Sam P." }, { "platform": "lightspeed", "store_label": "Lightspeed Retail", "order_id": "ls_sale_987654", "external_order_id": "ls_sale_987654", "status": "processed", "fulfillment_status": "shipped", "financial_status": "paid", "currency": "USD", "total_cents": 8900, "created_at": "2025-07-20T09:30:00Z", "items": [ { "name": "Vitamin C Serum", "quantity": 1, "unit_price_cents": 8900, "sku": "VITC-SER-30" } ], "location": "Lightspeed Retail", "receipt_id": "ls_rcpt_987654" } ], "lookupOutcome": "success", "meta": { "stores_queried": 4, "orders_found": 4, "cache_hits": 0 } }
Empty · request{ "email": "unknown@example.com", "stores": [ "all" ] }
Empty · response (lookupOutcome: empty){ "ok": true, "customer": null, "orders": [], "lookupOutcome": "empty", "meta": { "stores_queried": 4, "orders_found": 0, "cache_hits": 0, "note": "No matching customer or orders found. This lookup does not count against your monthly quota." } }
1. Send the sample request to POST /api/public/lookup with a valid API key to confirm the extension can parse the unified order shape.
2. POS orders use the same top-level schema as ecommerce orders; only platform and platform-specific fields (e.g., tender_type, location, receipt_url) differ.
3. For coupon flows, the extension should show a "pending approval" state when coupon.status === "pending_approval".