{"openapi":"3.1.0","info":{"title":"orgstack API","version":"1.0.0","description":"REST API for the orgstack review-collection platform. Pass `Authorization: Bearer orgstack_sk_(tnt|plat)_*` on every request.","contact":{"email":"support@orgstack.ai"}},"servers":[{"url":"https://reviews.orgstack.ai/api/v1","description":"Production"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"orgstack_sk_(tnt|plat)_*"}},"schemas":{"Tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"vertical":{"type":"string","nullable":true},"websiteUrl":{"type":"string","nullable":true},"googleMapsUrl":{"type":"string","nullable":true},"googlePlaceCid":{"type":"string","nullable":true},"xhsHandle":{"type":"string","nullable":true},"logoUrl":{"type":"string","nullable":true},"brandPrimaryColor":{"type":"string"},"brandAccentColor":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"ProvisionRequest":{"type":"object","required":["name","vertical"],"properties":{"name":{"type":"string","minLength":2},"slug":{"type":"string","description":"Auto-derived from name if omitted"},"vertical":{"type":"string","enum":["auto","fnb","beauty","clinic","retail","services","other"]},"businessDescription":{"type":"string","description":"Required when vertical=other; LLM uses it to generate 10 templates"},"mapsUrl":{"type":"string","description":"Google Maps URL — at least one of mapsUrl / xhsInput required"},"xhsInput":{"type":"string","description":"Xiaohongshu URL or @handle"},"websiteUrl":{"type":"string","description":"Optional; scraped for favicon + theme-color"},"ownerEmail":{"type":"string","description":"Optional; if set, owner gets reset-password email (closing flow)"}}},"ProvisionResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"mode":{"type":"string","enum":["owner","demo"]},"loginUsername":{"type":"string"},"loginEmail":{"type":"string"},"demoPassword":{"type":"string","nullable":true,"description":"Only set in demo mode; SALES_DEMO_PASSWORD value"},"enrichmentNotes":{"type":"array","items":{"type":"string"}}}},"AnalyticsResponse":{"type":"object","properties":{"days":{"type":"integer","enum":[7,30,90]},"summary":{"type":"object","properties":{"totalScans":{"type":"integer"},"branchAScans":{"type":"integer"},"branchBScans":{"type":"integer"},"branchARate":{"type":"number"},"branchBRate":{"type":"number"},"googleCopyTaps":{"type":"integer"},"branchBSubmits":{"type":"integer"}}},"employees":{"type":"array","items":{"type":"object"}},"shops":{"type":"array","items":{"type":"object"}}}},"Error":{"type":"object","properties":{"error":{"type":"string"},"fieldErrors":{"type":"object","additionalProperties":{"type":"string"}}}}}},"security":[{"bearerAuth":[]}],"paths":{"/tenants":{"get":{"summary":"List tenants","description":"Tenant-scoped keys see only their own tenant; platform-scoped keys see all.","security":[{"bearerAuth":["tenants:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"tenants":{"type":"array","items":{"$ref":"#/components/schemas/Tenant"}}}}}}},"401":{"description":"Unauthorised","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden"},"429":{"description":"Rate limit exceeded"}}},"post":{"summary":"Provision a new tenant","description":"Platform-scoped keys only (requires `tenants:write`). Atomically creates the tenant, default shop, login user, vertical templates, and Trial billing.","security":[{"bearerAuth":["tenants:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisionRequest"},"examples":{"demo":{"summary":"Demo mode (no owner email)","value":{"name":"Sin Ming Auto","vertical":"auto","mapsUrl":"https://maps.app.goo.gl/abc123","websiteUrl":"https://sinmingauto.com"}},"closing":{"summary":"Closing flow (owner email)","value":{"name":"Mei Mei Cafe","vertical":"fnb","mapsUrl":"https://maps.app.goo.gl/xyz789","ownerEmail":"owner@meimei.sg"}},"custom":{"summary":"Custom vertical (LLM-generated templates)","value":{"name":"Pawsitive Grooming","vertical":"other","businessDescription":"Mobile pet groomer for nervous dogs across Bukit Timah and Holland Village; bilingual EN/zh.","xhsInput":"@pawsitivegrooming"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisionResponse"}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorised"},"403":{"description":"Forbidden (key lacks tenants:write)"}}}},"/tenants/{tenantId}":{"get":{"summary":"Get one tenant","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"security":[{"bearerAuth":["tenants:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"tenant":{"$ref":"#/components/schemas/Tenant"}}}}}},"403":{"description":"Tenant-scope key cannot access another tenant"},"404":{"description":"Tenant not found"}}}},"/tenants/{tenantId}/employees":{"get":{"summary":"List employees for a tenant","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"security":[{"bearerAuth":["employees:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"employees":{"type":"array","items":{"type":"object"}}}}}}}}},"post":{"summary":"Create an employee under a shop","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"security":[{"bearerAuth":["employees:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["shopId","name"],"properties":{"shopId":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":120}}}}}},"responses":{"201":{"description":"Created"},"400":{"description":"Validation failed"},"404":{"description":"Shop not found in this tenant"}}}},"/tenants/{tenantId}/feedback":{"get":{"summary":"List private feedback for a tenant","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"security":[{"bearerAuth":["feedback:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"feedback":{"type":"array","items":{"type":"object"}}}}}}}}},"patch":{"summary":"Mark a feedback session resolved or unresolved","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"security":[{"bearerAuth":["feedback:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sessionId","resolved"],"properties":{"sessionId":{"type":"string","format":"uuid"},"resolved":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK"},"404":{"description":"Session not found in this tenant"}}}},"/tenants/{tenantId}/analytics":{"get":{"summary":"Funnel analytics for a tenant","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","enum":[7,30,90],"default":30}}],"security":[{"bearerAuth":["analytics:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsResponse"}}}}}}}}}