{"openapi":"3.1.0","info":{"title":"InAI E-Commerce API","version":"1.0.0","description":"Multi-tenant e-commerce platform API"},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded"]},"version":{"type":"string","example":"0.0.1"},"uptime":{"type":"integer","minimum":0,"example":123},"timestamp":{"type":"string","format":"date-time","example":"2026-05-19T12:00:00.000Z"},"services":{"type":"object","properties":{"database":{"$ref":"#/components/schemas/HealthService"},"kv":{"$ref":"#/components/schemas/HealthService"},"r2":{"$ref":"#/components/schemas/HealthService"},"queues":{"$ref":"#/components/schemas/HealthService"}},"required":["database","kv","r2","queues"]}},"required":["status","version","uptime","timestamp","services"]},"HealthService":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]},"latency_ms":{"type":"integer","minimum":0}},"required":["status"]},"ReadinessResponse":{"type":"object","properties":{"status":{"type":"string","enum":["ready","not_ready"]},"timestamp":{"type":"string","format":"date-time"},"checks":{"type":"object","properties":{"database":{"$ref":"#/components/schemas/ReadinessCheck"},"kv":{"$ref":"#/components/schemas/ReadinessCheck"},"r2":{"$ref":"#/components/schemas/ReadinessCheck"}},"required":["database","kv","r2"]}},"required":["status","timestamp","checks"]},"ReadinessCheck":{"type":"object","properties":{"status":{"type":"string","enum":["ok","degraded","error"]},"latency_ms":{"type":"integer","minimum":0},"error":{"type":"string"}},"required":["status"]},"PayPalWebhookAck":{"type":"object","properties":{"received":{"type":"boolean"}},"required":["received"]},"PayPalProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"PaymentsWebhookAck":{"type":"object","properties":{"received":{"type":"boolean"}},"required":["received"]},"PaymentsProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"RedsysWebhookForm":{"type":"object","properties":{"Ds_SignatureVersion":{"type":"string"},"Ds_MerchantParameters":{"type":"string","minLength":1},"Ds_Signature":{"type":"string","minLength":1}},"required":["Ds_MerchantParameters","Ds_Signature"]},"SequraWebhookForm":{"type":"object","properties":{"order_ref":{"type":"string","minLength":1},"sq_state":{"type":"string","minLength":1},"signature":{"type":"string","minLength":1}},"required":["order_ref","sq_state","signature"]},"StatusSnapshot":{"type":"object","properties":{"updated_at":{"type":"string","format":"date-time"},"overall":{"type":"string","enum":["operational","degraded","outage","unknown"]},"components":{"type":"array","items":{"$ref":"#/components/schemas/StatusComponent"}}},"required":["updated_at","overall","components"]},"StatusComponent":{"type":"object","properties":{"name":{"type":"string","example":"platform_db"},"status":{"type":"string","enum":["operational","degraded","outage","unknown"]},"latency_p50_ms":{"type":"integer","minimum":0},"last_checked":{"type":"string","format":"date-time"},"detail":{"type":"string"}},"required":["name","status","last_checked"]},"StatusError":{"type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status","detail"]},"TrendingSearchResponse":{"type":"object","properties":{"trending":{"type":"array","items":{"type":"string"},"example":["shirts","dress","sneakers"]}},"required":["trending"]},"ExchangeRatesResponse":{"type":"object","properties":{"base":{"type":"string","example":"USD"},"date":{"type":"string","example":"2026-05-27T00:00:00.000Z"},"rates":{"type":"object","additionalProperties":{"type":"number"},"example":{"EUR":0.92,"GBP":0.79,"JPY":156.3}}},"required":["base","date","rates"]},"Problem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"ConvertResponse":{"type":"object","properties":{"converted":{"type":"integer","description":"Converted amount in cents","example":9200},"rate":{"type":"number","example":0.92},"computed_at":{"type":"string","example":"2026-05-27T00:00:00.000Z"}},"required":["converted","rate","computed_at"]},"ConvertRequest":{"type":"object","properties":{"amount":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Amount in cents","example":10000},"from":{"type":"string","minLength":3,"maxLength":3,"example":"USD"},"to":{"type":"string","minLength":3,"maxLength":3,"example":"EUR"}},"required":["amount","from","to"]},"RefreshResponse":{"type":"object","properties":{"usd":{"type":"object","properties":{"updated":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}}},"required":["updated","errors"]},"eur":{"type":"object","properties":{"updated":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}}},"required":["updated","errors"]}},"required":["usd","eur"]},"StripeSubscriptionUpdated":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"customer":{"type":"string"},"current_period_start":{"type":"number"},"current_period_end":{"type":"number"},"cancel_at_period_end":{"type":"boolean"}},"required":["id","status","customer","current_period_start","current_period_end","cancel_at_period_end"]},"StripeSubscriptionCancelled":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"cancel_at_period_end":{"type":"boolean"},"canceled_at":{"type":"number","nullable":true}},"required":["id","status","cancel_at_period_end","canceled_at"]},"StripeSubscriptionPaused":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"}},"required":["id","status"]},"StripeSubscriptionResumed":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"}},"required":["id","status"]},"StripeProrationPreview":{"type":"object","properties":{"id":{"type":"string"},"amount_due":{"type":"number"},"amount_paid":{"type":"number"},"currency":{"type":"string"},"status":{"type":"string"}},"required":["id","amount_due","amount_paid","currency","status"]},"PayPalSubscriptionCreated":{"type":"object","properties":{"subscriptionId":{"type":"string"},"status":{"type":"string"},"approvalUrl":{"type":"string","nullable":true}},"required":["subscriptionId","status","approvalUrl"]},"PayPalReviseResponse":{"type":"object","properties":{"approvalUrl":{"type":"string","nullable":true},"links":{"type":"array","items":{"type":"object","properties":{"href":{"type":"string"},"rel":{"type":"string"},"method":{"type":"string"}},"required":["href","rel","method"]}}},"required":["approvalUrl"]},"Cart":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["active","merged","abandoned","converted"]},"currency":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/CartItem"}},"subtotal":{"type":"integer"},"itemCount":{"type":"integer"},"discountCode":{"type":"string","nullable":true}},"required":["id","status","currency","items","subtotal","itemCount","discountCode"]},"CartItem":{"type":"object","properties":{"id":{"type":"string"},"cartId":{"type":"string"},"productId":{"type":"string"},"variantId":{"type":"string","nullable":true},"name":{"type":"string"},"sku":{"type":"string","nullable":true},"price":{"type":"integer"},"quantity":{"type":"integer"},"total":{"type":"integer"},"imageUrl":{"type":"string","nullable":true},"inStock":{"type":"boolean"}},"required":["id","cartId","productId","variantId","name","sku","price","quantity","total","imageUrl","inStock"]},"CartProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"CartCalculation":{"type":"object","properties":{"cartId":{"type":"string"},"currency":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/CartCalculationLine"}},"subtotal":{"type":"integer"},"taxTotal":{"type":"integer"},"total":{"type":"integer"},"taxExempt":{"type":"boolean"},"itemCount":{"type":"integer"}},"required":["cartId","currency","items","subtotal","taxTotal","total","taxExempt","itemCount"]},"CartCalculationLine":{"type":"object","properties":{"id":{"type":"string"},"productId":{"type":"string"},"variantId":{"type":"string","nullable":true},"name":{"type":"string"},"quantity":{"type":"integer"},"unitPrice":{"type":"integer"},"lineTotal":{"type":"integer"},"priceSource":{"type":"string","enum":["base","variant","tier","price_list"]}},"required":["id","productId","variantId","name","quantity","unitPrice","lineTotal","priceSource"]},"CartCalculationProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"AddToCart":{"type":"object","properties":{"productId":{"type":"string","minLength":1},"variantId":{"type":"string"},"quantity":{"type":"integer","minimum":1}},"required":["productId","quantity"]},"UpdateCartItem":{"type":"object","properties":{"quantity":{"type":"integer","minimum":1}},"required":["quantity"]},"ApplyCartDiscount":{"type":"object","properties":{"code":{"type":"string","minLength":1}},"required":["code"]},"MergeCartResponse":{"type":"object","properties":{"merged":{"type":"integer"},"cart":{"$ref":"#/components/schemas/Cart"}},"required":["merged","cart"]},"MergeCartBody":{"type":"object","properties":{"sessionId":{"type":"string","format":"uuid","example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"}},"required":["sessionId"]},"PickupPoint":{"type":"object","nullable":true,"properties":{"provider":{"type":"string","enum":["packlink","sendcloud"],"example":"sendcloud"},"pointId":{"type":"string","minLength":1,"maxLength":64,"example":"10875349"},"name":{"type":"string","minLength":1,"maxLength":200,"example":"Estanco Plaza Mayor"},"address":{"type":"string","minLength":1,"maxLength":300,"example":"Calle Mayor 12"},"postalCode":{"type":"string","minLength":1,"maxLength":16,"example":"28013"},"city":{"type":"string","minLength":1,"maxLength":120,"example":"Madrid"},"lat":{"type":"number","minimum":-90,"maximum":90,"example":40.4154},"lng":{"type":"number","minimum":-180,"maximum":180,"example":-3.7074}},"required":["provider","pointId","name","address","postalCode","city","lat","lng"]},"StorefrontPaymentMethodsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StorefrontPaymentMethod"}}},"required":["data"]},"StorefrontPaymentMethod":{"type":"object","properties":{"id":{"type":"string","example":"bizum"},"provider":{"type":"string","example":"redsys"},"type":{"type":"string","enum":["element","redirect","manual"],"description":"Render hint: element = embedded JS element, redirect = full-page redirect form, manual = offline instructions"},"labelKey":{"type":"string","example":"checkout.payment.bizum","description":"i18n key — translations live in the storefront catalogs (EN+ES)"},"testMode":{"type":"boolean"},"feeCents":{"type":"integer","nullable":true,"description":"COD surcharge (cents)"},"maxOrderCents":{"type":"integer","nullable":true},"instructions":{"$ref":"#/components/schemas/LocalizedInstructions"},"iban":{"type":"string","nullable":true},"beneficiary":{"type":"string","nullable":true}},"required":["id","provider","type","labelKey","testMode","feeCents","maxOrderCents","instructions","iban","beneficiary"]},"LocalizedInstructions":{"type":"object","nullable":true,"properties":{"en":{"type":"string"},"es":{"type":"string"}},"required":["en","es"]},"PayPalCreateOrderResponse":{"type":"object","properties":{"paypalOrderId":{"type":"string"},"approveUrl":{"type":"string","format":"uri"}},"required":["paypalOrderId","approveUrl"]},"PayPalCaptureResponse":{"type":"object","properties":{"orderId":{"type":"string"},"orderNumber":{"type":"string"},"status":{"type":"string"},"total":{"type":"integer"},"currency":{"type":"string"},"createdAt":{"type":"string"},"paypalCaptureId":{"type":"string","nullable":true}},"required":["orderId","orderNumber","status","total","currency","createdAt","paypalCaptureId"]},"RedsysRedirectFormResponse":{"type":"object","properties":{"url":{"type":"string","example":"https://sis-t.redsys.es:25443/sis/realizarPago"},"fields":{"type":"object","properties":{"Ds_SignatureVersion":{"type":"string"},"Ds_MerchantParameters":{"type":"string"},"Ds_Signature":{"type":"string"}},"required":["Ds_SignatureVersion","Ds_MerchantParameters","Ds_Signature"]},"dsOrder":{"type":"string","description":"Generated Ds_Merchant_Order (4 leading digits + 8 alphanumeric)"},"method":{"type":"string","enum":["card","bizum"]}},"required":["url","fields","dsOrder","method"]},"RedsysCreatePaymentInput":{"type":"object","properties":{"method":{"type":"string","enum":["card","bizum"],"default":"card","description":"Redsys pay method: 'card' (TPV) or 'bizum' (Ds_Merchant_PayMethods='z')"},"returnUrlOk":{"type":"string","format":"uri","example":"https://shop.example.com/checkout/success"},"returnUrlKo":{"type":"string","format":"uri","example":"https://shop.example.com/checkout/failed"}},"required":["returnUrlOk","returnUrlKo"]},"SequraStartResponse":{"type":"object","properties":{"orderUri":{"type":"string","description":"SeQura order resource URI"},"formUrl":{"type":"string","description":"Hosted identification form URL (redirect/widget)"}},"required":["orderUri","formUrl"]},"SequraStartInput":{"type":"object","properties":{"returnUrl":{"type":"string","format":"uri","example":"https://shop.example.com/checkout/success"}},"required":["returnUrl"]},"ManualPaymentResponse":{"type":"object","properties":{"order":{"type":"object","properties":{"id":{"type":"string"},"orderNumber":{"type":"string"},"status":{"type":"string","example":"pending_payment"},"paymentStatus":{"type":"string","example":"pending"},"total":{"type":"integer","description":"cents — includes COD fee when applicable"},"currency":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","orderNumber","status","paymentStatus","total","currency","createdAt"]},"paymentMethod":{"type":"string","enum":["cod","bank_transfer"]},"codFeeCents":{"type":"integer","nullable":true,"description":"COD surcharge applied (cents), null for transfer"},"instructions":{"$ref":"#/components/schemas/LocalizedInstructions"},"iban":{"type":"string","nullable":true},"beneficiary":{"type":"string","nullable":true},"reference":{"type":"string","nullable":true,"description":"Transfer concept — falls back to the order number"}},"required":["order","paymentMethod","codFeeCents","instructions","iban","beneficiary","reference"]},"ManualPaymentInput":{"type":"object","properties":{"method":{"type":"string","enum":["cod","bank_transfer"],"description":"Offline payment method: 'cod' (contrareembolso) or 'bank_transfer' (transferencia)"}},"required":["method"]},"PickupPointWithHours":{"allOf":[{"$ref":"#/components/schemas/PickupPoint"},{"type":"object","properties":{"openingHours":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}}]},"B2bAccount":{"type":"object","properties":{"id":{"type":"string"},"customerId":{"type":"string"},"companyName":{"type":"string"},"taxId":{"type":"string","nullable":true},"industry":{"type":"string","nullable":true},"websiteUrl":{"type":"string","nullable":true},"creditLimit":{"type":"integer","minimum":0},"creditUsed":{"type":"integer","minimum":0},"creditAvailable":{"type":"integer"},"paymentTerms":{"$ref":"#/components/schemas/PaymentTerms"},"approverId":{"type":"string","nullable":true},"status":{"$ref":"#/components/schemas/B2bAccountStatus"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","customerId","companyName","taxId","industry","websiteUrl","creditLimit","creditUsed","creditAvailable","paymentTerms","approverId","status","createdAt","updatedAt"]},"PaymentTerms":{"type":"string","enum":["immediate","net_15","net_30","net_60","net_90"]},"B2bAccountStatus":{"type":"string","enum":["pending_approval","active","suspended","closed"]},"B2bProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]},"StorefrontQuoteList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Quote"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"]},"Quote":{"type":"object","properties":{"id":{"type":"string"},"quoteNumber":{"type":"string"},"accountId":{"type":"string"},"requestedBy":{"type":"string"},"status":{"$ref":"#/components/schemas/QuoteStatus"},"items":{"type":"array","items":{"$ref":"#/components/schemas/QuoteItem"}},"subtotal":{"type":"integer","minimum":0},"discountTotal":{"type":"integer","minimum":0},"taxTotal":{"type":"integer","minimum":0},"shippingTotal":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3},"customerNote":{"type":"string","nullable":true},"internalNote":{"type":"string","nullable":true},"expiresAt":{"type":"string","nullable":true},"approvedBy":{"type":"string","nullable":true},"approvedAt":{"type":"string","nullable":true},"rejectedReason":{"type":"string","nullable":true},"convertedOrderId":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","quoteNumber","accountId","requestedBy","status","items","subtotal","discountTotal","taxTotal","shippingTotal","total","currency","customerNote","internalNote","expiresAt","approvedBy","approvedAt","rejectedReason","convertedOrderId","createdAt","updatedAt"]},"QuoteStatus":{"type":"string","enum":["draft","submitted","under_review","approved","rejected","expired","converted"]},"QuoteItem":{"type":"object","properties":{"productId":{"type":"string"},"variantId":{"type":"string","nullable":true},"qty":{"type":"integer","minimum":1},"unitPrice":{"type":"integer","minimum":0},"lineTotal":{"type":"integer","minimum":0},"note":{"type":"string","nullable":true}},"required":["productId","qty","unitPrice","lineTotal"]},"CreateQuote":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"items":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string","minLength":1},"variantId":{"type":"string","minLength":1},"qty":{"type":"integer","minimum":1},"note":{"type":"string","maxLength":500}},"required":["productId","qty"]},"minItems":1,"maxItems":200},"customerNote":{"type":"string","maxLength":2000},"expiresAt":{"type":"string","format":"date-time"}},"required":["accountId","items"]},"QuoteRevisionList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/QuoteRevision"}}},"required":["data"]},"QuoteRevision":{"type":"object","properties":{"id":{"type":"string"},"quoteId":{"type":"string"},"kind":{"$ref":"#/components/schemas/QuoteRevisionKind"},"createdBy":{"type":"string","nullable":true},"items":{"type":"array","items":{"$ref":"#/components/schemas/QuoteItem"}},"subtotal":{"type":"integer"},"total":{"type":"integer"},"note":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","quoteId","kind","createdBy","items","subtotal","total","note","createdAt"]},"QuoteRevisionKind":{"type":"string","enum":["customer_request","merchant_offer","customer_counter"]},"CounterQuote":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string","minLength":1},"variantId":{"type":"string","nullable":true},"qty":{"type":"integer","minimum":1},"unitPrice":{"type":"integer","minimum":0}},"required":["productId","qty"]},"minItems":1},"note":{"type":"string","maxLength":2000}},"required":["items"]},"ConvertQuoteResponse":{"type":"object","properties":{"orderId":{"type":"string"},"orderNumber":{"type":"string"},"status":{"type":"string"},"requiresApproval":{"type":"boolean"},"approvalRequestId":{"type":"string","nullable":true},"purchaseOrderId":{"type":"string","nullable":true}},"required":["orderId","orderNumber","status","requiresApproval","approvalRequestId","purchaseOrderId"]},"ConvertQuote":{"type":"object","properties":{"paymentMethod":{"type":"string","enum":["po","credit_card","paypal","stripe_terms"]},"poNumber":{"type":"string","minLength":1,"maxLength":120},"poAttachmentUrl":{"type":"string","format":"uri"}},"required":["paymentMethod"]},"OnAccountOrderResponse":{"type":"object","properties":{"orderId":{"type":"string"},"orderNumber":{"type":"string"},"status":{"type":"string"},"total":{"type":"integer","minimum":0},"dueDate":{"type":"string","nullable":true},"paymentTerms":{"$ref":"#/components/schemas/PaymentTerms"},"creditAvailableAfter":{"type":"integer"}},"required":["orderId","orderNumber","status","total","dueDate","paymentTerms","creditAvailableAfter"]},"CreateOnAccountOrder":{"type":"object","properties":{"accountId":{"type":"string","minLength":1},"items":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string","minLength":1},"variantId":{"type":"string","minLength":1},"qty":{"type":"integer","minimum":1}},"required":["productId","qty"]},"minItems":1,"maxItems":200},"poNumber":{"type":"string","minLength":1,"maxLength":120},"customerNote":{"type":"string","maxLength":2000}},"required":["accountId","items"]},"StorefrontPurchaseOrderList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseOrder"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"]},"PurchaseOrder":{"type":"object","properties":{"id":{"type":"string"},"orderId":{"type":"string"},"quoteId":{"type":"string","nullable":true},"accountId":{"type":"string"},"poNumber":{"type":"string"},"attachmentUrl":{"type":"string","nullable":true},"dueDate":{"type":"string","nullable":true},"status":{"$ref":"#/components/schemas/PurchaseOrderStatus"},"paidAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","orderId","quoteId","accountId","poNumber","attachmentUrl","dueDate","status","paidAt","createdAt","updatedAt"]},"PurchaseOrderStatus":{"type":"string","enum":["pending","sent_for_approval","approved","paid","overdue","cancelled"]},"CreatePurchaseOrder":{"type":"object","properties":{"orderId":{"type":"string","minLength":1},"quoteId":{"type":"string","minLength":1},"poNumber":{"type":"string","minLength":1,"maxLength":120},"attachmentUrl":{"type":"string","format":"uri"},"dueDate":{"type":"string","format":"date-time"}},"required":["orderId","poNumber"]},"ApprovalRequestList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ApprovalRequest"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"]},"ApprovalRequest":{"type":"object","properties":{"id":{"type":"string"},"orderId":{"type":"string","nullable":true},"quoteId":{"type":"string","nullable":true},"accountId":{"type":"string"},"approverId":{"type":"string"},"reason":{"$ref":"#/components/schemas/ApprovalReason"},"status":{"$ref":"#/components/schemas/ApprovalRequestStatus"},"level":{"type":"integer"},"requiredLevels":{"type":"integer"},"amountCents":{"type":"integer"},"decisionNote":{"type":"string","nullable":true},"decidedAt":{"type":"string","nullable":true},"expiresAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","orderId","quoteId","accountId","approverId","reason","status","level","requiredLevels","amountCents","decisionNote","decidedAt","expiresAt","createdAt"]},"ApprovalReason":{"type":"string","enum":["exceeds_credit_limit","requires_approval_flag","amount_threshold"]},"ApprovalRequestStatus":{"type":"string","enum":["pending","approved","rejected","expired"]},"ApprovalDecisionHistory":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ApprovalDecisionRecord"}}},"required":["data"]},"ApprovalDecisionRecord":{"type":"object","properties":{"id":{"type":"string"},"approvalRequestId":{"type":"string"},"level":{"type":"integer"},"deciderId":{"type":"string"},"decision":{"type":"string","enum":["approved","rejected"]},"note":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","approvalRequestId","level","deciderId","decision","note","createdAt"]},"ApprovalDecision":{"type":"object","properties":{"decisionNote":{"type":"string","maxLength":2000}}},"QuickOrderResult":{"type":"object","properties":{"lines":{"type":"array","items":{"$ref":"#/components/schemas/QuickOrderLine"}},"notFound":{"type":"array","items":{"type":"string"}},"parseErrors":{"type":"array","items":{"type":"string"}},"subtotalCents":{"type":"integer"}},"required":["lines","notFound","parseErrors","subtotalCents"]},"QuickOrderLine":{"type":"object","properties":{"sku":{"type":"string"},"productId":{"type":"string"},"variantId":{"type":"string","nullable":true},"name":{"type":"string"},"qty":{"type":"integer"},"unitPriceCents":{"type":"integer"},"lineTotalCents":{"type":"integer"},"priceSource":{"type":"string","enum":["price_list","base"]},"availableQty":{"type":"integer"},"inStock":{"type":"boolean"}},"required":["sku","productId","variantId","name","qty","unitPriceCents","lineTotalCents","priceSource","availableQty","inStock"]},"QuickOrderValidate":{"type":"object","properties":{"accountId":{"type":"string"},"items":{"type":"array","items":{"type":"object","properties":{"sku":{"type":"string","minLength":1},"qty":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["sku","qty"]},"maxItems":500},"raw":{"type":"string","maxLength":50000}}},"B2bStorefrontContext":{"type":"object","properties":{"is_b2b":{"type":"boolean"},"customer_id":{"type":"string"},"company":{"$ref":"#/components/schemas/Company"},"membership":{"$ref":"#/components/schemas/CompanyUser"},"account":{"$ref":"#/components/schemas/B2bContextAccount"},"price_list_id":{"type":"string","nullable":true},"shared_catalog_id":{"type":"string","nullable":true}},"required":["is_b2b","customer_id","company","membership","account","price_list_id","shared_catalog_id"]},"Company":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["active","pending","blocked"]},"credit_limit_cents":{"type":"integer"},"payment_terms_days":{"type":"integer"},"default_price_list_id":{"type":"string","nullable":true},"tax_exempt":{"type":"boolean"},"created_at":{"type":"integer"},"updated_at":{"type":"integer"}},"required":["id","name","status","credit_limit_cents","payment_terms_days","default_price_list_id","tax_exempt","created_at","updated_at"]},"CompanyUser":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"company_id":{"type":"string"},"customer_id":{"type":"string"},"role":{"type":"string","enum":["admin","buyer","approver"]},"spending_limit_cents":{"type":"integer","nullable":true},"is_active":{"type":"boolean"},"created_at":{"type":"integer"}},"required":["id","company_id","customer_id","role","spending_limit_cents","is_active","created_at"]},"B2bContextAccount":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"company_name":{"type":"string"},"status":{"type":"string"},"payment_terms":{"type":"string"},"credit_limit_cents":{"type":"integer"},"credit_used_cents":{"type":"integer"},"credit_available_cents":{"type":"integer"}},"required":["id","company_name","status","payment_terms","credit_limit_cents","credit_used_cents","credit_available_cents"]},"UpdateCompanyUserBody":{"type":"object","properties":{"role":{"type":"string","enum":["admin","buyer","approver"]},"spending_limit_cents":{"type":"integer","nullable":true,"minimum":0},"is_active":{"type":"boolean"}}},"RequisitionList":{"type":"object","properties":{"id":{"type":"string"},"company_id":{"type":"string"},"customer_id":{"type":"string"},"name":{"type":"string"},"created_at":{"type":"integer"}},"required":["id","company_id","customer_id","name","created_at"]},"UpdateRequisitionListBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200}},"required":["name"]},"ResolveMarketResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Market"},"matchedBy":{"type":"string","enum":["id","handle","country","currency","default","fallback"]}},"required":["data","matchedBy"]},"Market":{"type":"object","properties":{"id":{"type":"string","example":"mkt_eu"},"name":{"type":"string","example":"Europe"},"handle":{"type":"string","example":"europe"},"countries":{"type":"array","items":{"type":"string"},"example":["ES","FR","DE"]},"region":{"type":"string","nullable":true,"example":"EU"},"presentmentCurrency":{"type":"string","example":"EUR"},"priceAdjustmentPct":{"type":"integer","description":"Signed basis points applied on top of the converted base price (e.g. +1000 = +10%)","example":1000},"roundingRule":{"type":"string","enum":["none","nearest_99","nearest_95","nearest_00","nearest_int"],"example":"nearest_99"},"taxInclusive":{"type":"boolean","example":true},"isDefault":{"type":"boolean","example":false},"isActive":{"type":"boolean","example":true},"createdAt":{"type":"integer","example":1700000000},"updatedAt":{"type":"integer","example":1700000000}},"required":["id","name","handle","countries","region","presentmentCurrency","priceAdjustmentPct","roundingRule","taxInclusive","isDefault","isActive","createdAt","updatedAt"]},"MarketsProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"ResolvePriceResponse":{"type":"object","properties":{"amount":{"type":"integer","description":"Presentment price in cents","example":10120},"compareAt":{"type":"integer","nullable":true,"example":14400},"currency":{"type":"string","description":"Presentment currency","example":"EUR"},"baseAmount":{"type":"integer","description":"Original base price in cents","example":10000},"baseCurrency":{"type":"string","example":"USD"},"market":{"type":"object","properties":{"id":{"type":"string"},"handle":{"type":"string"},"presentmentCurrency":{"type":"string"},"taxInclusive":{"type":"boolean"},"isDefault":{"type":"boolean"}},"required":["id","handle","presentmentCurrency","taxInclusive","isDefault"]},"exchangeRate":{"type":"number","description":"base→presentment rate used (1 if same currency)","example":1},"priceAdjustmentPct":{"type":"integer","example":1000},"roundingRule":{"type":"string","enum":["none","nearest_99","nearest_95","nearest_00","nearest_int"]},"taxBehavior":{"type":"string","enum":["inclusive","exclusive"],"example":"inclusive"},"priceSource":{"type":"string","enum":["override","converted","base"],"description":"override = per-market catalog override; converted = rate+adjustment; base = same currency / no rate","example":"converted"}},"required":["amount","compareAt","currency","baseAmount","baseCurrency","market","exchangeRate","priceAdjustmentPct","roundingRule","taxBehavior","priceSource"]},"GreenClaimsGateSummary":{"type":"object","properties":{"mode":{"type":"string","enum":["warn"]},"compliant":{"type":"boolean"},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/GreenClaimWarning"}}},"required":["mode","compliant","warnings"],"description":"Green-claims lint summary (warn mode only): the write proceeded but the copy contains environmental claims not substantiated by the product's DPP."},"GreenClaimWarning":{"type":"object","properties":{"kind":{"type":"string","example":"carbon_neutral"},"phrase":{"type":"string","example":"carbon neutral"},"severity":{"type":"string","enum":["error","warning"]},"message":{"type":"string"},"evidenceNeeded":{"type":"string","example":"dpp_carbon_footprint_grams + a carbon/climate-neutral certification"},"suggestion":{"type":"string"}},"required":["kind","phrase","severity","message","evidenceNeeded","suggestion"]},"SeoRedirectResolution":{"type":"object","properties":{"toPath":{"type":"string","example":"/products/vestido-flores"},"httpStatus":{"type":"integer","example":301}},"required":["toPath","httpStatus"]},"ThemeTokens":{"type":"object","properties":{"version":{"type":"number","enum":[1]},"colors":{"type":"object","properties":{"primary":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"secondary":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"accent":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"background":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"foreground":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"muted":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"border":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"destructive":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"}},"required":["primary","secondary","accent","background","foreground","muted","border","destructive"]},"fonts":{"type":"object","properties":{"sans":{"type":"string","minLength":1,"maxLength":200},"serif":{"type":"string","minLength":1,"maxLength":200},"mono":{"type":"string","minLength":1,"maxLength":200}},"required":["sans","serif","mono"]},"layout":{"type":"object","properties":{"header":{"type":"string","enum":["minimal","classic","full"]},"footer":{"type":"string","enum":["minimal","rich"]},"product":{"type":"string","enum":["compact","editorial","immersive"]}},"required":["header","footer","product"]},"logo":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"removedBg":{"type":"boolean","default":false}},"required":["url"]}},"required":["version","colors","fonts","layout"],"example":{"version":1,"colors":{"primary":"oklch(55% 0.2 264)","secondary":"oklch(70% 0.12 200)","accent":"oklch(75% 0.15 80)","background":"oklch(99% 0.005 264)","foreground":"oklch(15% 0.02 264)","muted":"oklch(95% 0.01 264)","border":"oklch(88% 0.01 264)","destructive":"oklch(55% 0.22 25)"},"fonts":{"sans":"Bricolage Grotesque Variable, Bricolage Grotesque, ui-sans-serif, system-ui, sans-serif","serif":"Fraunces Variable, Fraunces, ui-serif, Georgia, serif","mono":"JetBrains Mono Variable, ui-monospace, SFMono-Regular, monospace"},"layout":{"header":"classic","footer":"rich","product":"editorial"}}},"ExportaSettings":{"type":"object","properties":{"enabledLocales":{"type":"array","items":{"type":"string","enum":["es","en","ca","eu","gl","pt"]}},"displayCurrencies":{"type":"array","items":{"type":"string","minLength":3,"maxLength":3}},"taxDisplay":{"type":"string","enum":["inclusive","exclusive","auto"]}},"required":["enabledLocales","displayCurrencies","taxDisplay"]},"ListReviewsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Review"}},"pagination":{"$ref":"#/components/schemas/ReviewPagination"}},"required":["data","pagination"]},"Review":{"type":"object","properties":{"id":{"type":"string","example":"rev_01"},"productId":{"type":"string","example":"prod_01"},"customerId":{"type":"string","nullable":true},"orderId":{"type":"string","nullable":true},"rating":{"type":"integer","minimum":1,"maximum":5,"example":5},"title":{"type":"string","nullable":true},"body":{"type":"string","nullable":true},"status":{"$ref":"#/components/schemas/ReviewStatus"},"verifiedPurchase":{"type":"boolean","example":true},"authorName":{"type":"string","nullable":true},"helpfulCount":{"type":"integer","minimum":0},"createdAt":{"type":"integer","description":"Unix seconds."},"updatedAt":{"type":"integer","description":"Unix seconds."}},"required":["id","productId","customerId","orderId","rating","title","body","status","verifiedPurchase","authorName","helpfulCount","createdAt","updatedAt"]},"ReviewStatus":{"type":"string","enum":["pending","approved","rejected"]},"ReviewPagination":{"type":"object","properties":{"page":{"type":"integer"},"perPage":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","perPage","total","totalPages"]},"ReviewProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"ReviewSummary":{"type":"object","properties":{"productId":{"type":"string"},"count":{"type":"integer","minimum":0,"example":12,"description":"Total approved reviews."},"average":{"type":"number","minimum":0,"maximum":5,"example":4.5,"description":"Average rating 0..5 over approved reviews; 0 when none."},"breakdown":{"type":"object","properties":{"1":{"type":"integer","minimum":0},"2":{"type":"integer","minimum":0},"3":{"type":"integer","minimum":0},"4":{"type":"integer","minimum":0},"5":{"type":"integer","minimum":0}},"required":["1","2","3","4","5"],"description":"Count of approved reviews per star bucket."}},"required":["productId","count","average","breakdown"]},"CreateReview":{"type":"object","properties":{"rating":{"type":"integer","minimum":1,"maximum":5,"example":5},"title":{"type":"string","nullable":true,"maxLength":200},"body":{"type":"string","nullable":true,"maxLength":5000},"orderId":{"type":"string","nullable":true,"description":"Optional order to attribute the review to; verified-purchase is recomputed server-side regardless."},"authorName":{"type":"string","nullable":true,"maxLength":120}},"required":["rating"]},"ContactReceived":{"type":"object","properties":{"id":{"type":"string","example":"cmsg_a1b2c3d4e5f6"},"status":{"type":"string","enum":["received"]}},"required":["id","status"]},"ContactProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status","detail"]},"SubmitContact":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"example":"Jane Doe","description":"Sender name"},"email":{"type":"string","maxLength":254,"format":"email","example":"jane@example.com","description":"Sender email (reply destination)"},"subject":{"type":"string","maxLength":200,"example":"Question about my order","description":"Optional subject line"},"message":{"type":"string","minLength":1,"maxLength":4000,"example":"Hi, I have a question…","description":"Message body"},"contactEmail":{"type":"string","maxLength":254,"format":"email","description":"Forwarded fallback destination (store support email)"}},"required":["name","email","message"]},"AuditLogList":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AuditLog"}},"total":{"type":"integer"},"page":{"type":"integer"},"per_page":{"type":"integer"}},"required":["items","total","page","per_page"]},"AuditLog":{"type":"object","properties":{"id":{"type":"string","example":"aud_a1b2c3d4e5f6"},"tenantId":{"type":"string","nullable":true,"example":"tnt_a1b2c3d4e5f6"},"userId":{"type":"string","nullable":true,"example":"usr_a1b2c3d4e5f6"},"action":{"type":"string","example":"product.created"},"resource":{"type":"string","example":"products"},"resourceId":{"type":"string","nullable":true,"example":"prod_a1b2c3d4e5f6"},"details":{"type":"string","nullable":true},"ipAddress":{"type":"string","nullable":true},"userAgent":{"type":"string","nullable":true},"severity":{"type":"string","nullable":true,"enum":["info","warn","critical",null]},"statusCode":{"type":"integer","nullable":true},"actorEmail":{"type":"string","nullable":true},"expiresAt":{"type":"integer","nullable":true,"description":"Unix seconds"},"createdAt":{"type":"string","description":"ISO-8601 timestamp","example":"2026-05-26T10:00:00.000Z"}},"required":["id","tenantId","userId","action","resource","resourceId","details","ipAddress","userAgent","severity","statusCode","actorEmail","expiresAt","createdAt"]},"AlertRuleList":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AlertRule"}},"total":{"type":"integer"}},"required":["items","total"]},"AlertRule":{"type":"object","properties":{"id":{"type":"string","example":"alr_a1b2c3d4e5f6"},"tenantId":{"type":"string","nullable":true,"example":"tnt_a1b2c3d4e5f6"},"name":{"type":"string","example":"Critical events"},"enabled":{"type":"boolean","example":true},"severity":{"type":"string","enum":["critical","warn"],"example":"critical"},"actionPattern":{"type":"string","nullable":true,"example":"customer\\..*|settings\\..*","description":"Regex matched against audit action. Null = all actions."},"channels":{"type":"array","items":{"type":"string","enum":["webhook","email","slack"]},"example":["webhook","email"]},"webhookUrl":{"type":"string","nullable":true,"format":"uri","example":"https://hooks.example.com/alert"},"slackWebhookUrl":{"type":"string","nullable":true,"format":"uri","example":"https://hooks.slack.com/services/…"},"emailRecipients":{"type":"array","nullable":true,"items":{"type":"string","format":"email"},"example":["admin@example.com"]},"cooldownSeconds":{"type":"integer","nullable":true,"minimum":0,"example":300,"description":"Seconds between consecutive fires to prevent spam."},"lastTriggeredAt":{"type":"integer","nullable":true,"description":"Unix seconds of last trigger."},"createdAt":{"type":"string","description":"ISO-8601","example":"2026-05-26T10:00:00.000Z"},"updatedAt":{"type":"string","description":"ISO-8601","example":"2026-05-26T10:00:00.000Z"}},"required":["id","tenantId","name","enabled","severity","actionPattern","channels","webhookUrl","slackWebhookUrl","emailRecipients","cooldownSeconds","lastTriggeredAt","createdAt","updatedAt"]},"CreateAlertRuleBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Critical events"},"enabled":{"type":"boolean","default":true},"severity":{"type":"string","enum":["critical","warn"],"example":"critical"},"actionPattern":{"type":"string","nullable":true,"maxLength":500,"example":"customer\\..*"},"channels":{"type":"array","items":{"type":"string","enum":["webhook","email","slack"]},"minItems":1,"example":["webhook","slack"]},"webhookUrl":{"type":"string","nullable":true,"format":"uri"},"slackWebhookUrl":{"type":"string","nullable":true,"format":"uri"},"emailRecipients":{"type":"array","nullable":true,"items":{"type":"string","format":"email"}},"cooldownSeconds":{"type":"integer","minimum":0,"maximum":86400,"default":300}},"required":["name","severity","channels"]},"UpdateAlertRuleBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Critical events"},"enabled":{"type":"boolean","default":true},"severity":{"type":"string","enum":["critical","warn"],"example":"critical"},"actionPattern":{"type":"string","nullable":true,"maxLength":500,"example":"customer\\..*"},"channels":{"type":"array","items":{"type":"string","enum":["webhook","email","slack"]},"minItems":1,"example":["webhook","slack"]},"webhookUrl":{"type":"string","nullable":true,"format":"uri"},"slackWebhookUrl":{"type":"string","nullable":true,"format":"uri"},"emailRecipients":{"type":"array","nullable":true,"items":{"type":"string","format":"email"}},"cooldownSeconds":{"type":"integer","minimum":0,"maximum":86400,"default":300}}},"SavedReport":{"type":"object","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"report_type":{"type":"string","enum":["order_stats","product_stats","customer_ltv","inventory","custom"]},"filters":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"columns":{"type":"array","nullable":true,"items":{"type":"string"}},"format":{"type":"string","enum":["csv","json","xlsx","pdf"]},"is_shared":{"type":"integer"},"created_at":{"type":"integer"},"updated_at":{"type":"integer"}},"required":["id","tenant_id","user_id","name","description","report_type","filters","columns","format","is_shared","created_at","updated_at"]},"ReportExecution":{"type":"object","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"report_id":{"type":"string"},"triggered_by":{"type":"string","enum":["schedule","manual","api"]},"actor_user_id":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","running","completed","failed"]},"row_count":{"type":"integer","nullable":true},"file_size_bytes":{"type":"integer","nullable":true},"download_url":{"type":"string","nullable":true},"error":{"type":"string","nullable":true},"started_at":{"type":"integer"},"completed_at":{"type":"integer","nullable":true},"created_at":{"type":"integer"}},"required":["id","tenant_id","report_id","triggered_by","actor_user_id","status","row_count","file_size_bytes","download_url","error","started_at","completed_at","created_at"]},"ReportSchedule":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"report_id":{"type":"string"},"cron":{"type":"string"},"recipients":{"type":"array","items":{"type":"string","format":"email"}},"is_active":{"type":"integer"},"last_run_at":{"type":"integer","nullable":true},"next_run_at":{"type":"integer","nullable":true},"created_at":{"type":"integer"},"updated_at":{"type":"integer"}},"required":["id","tenant_id","report_id","cron","recipients","is_active","last_run_at","next_run_at","created_at","updated_at"]},"Metafield":{"type":"object","properties":{"id":{"type":"string"},"owner_id":{"type":"string"},"namespace":{"type":"string"},"key":{"type":"string"},"value":{"type":"string","nullable":true},"type":{"type":"string","enum":["string","integer","number","boolean","json","date","url","color","money","rich_text"]},"created_at":{"type":"integer"},"updated_at":{"type":"integer"}},"required":["id","owner_id","namespace","key","value","type","created_at","updated_at"]},"GreenClaimsProblem":{"type":"object","properties":{"type":{"type":"string","example":"https://inaishop.com/errors/green-claims-unsubstantiated"},"title":{"type":"string","example":"Green Claims Unsubstantiated"},"status":{"type":"number","example":422},"detail":{"type":"string"},"instance":{"type":"string"},"code":{"type":"string","example":"green_claims_unsubstantiated"},"claims":{"type":"array","items":{"$ref":"#/components/schemas/GreenClaimWarning"}},"products":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string"},"claims":{"type":"array","items":{"$ref":"#/components/schemas/GreenClaimWarning"}}},"required":["productId","claims"]}}},"required":["type","title","status"]},"GreenClaimsDppOverride":{"type":"object","properties":{"recyclability":{"type":"string","nullable":true},"repairabilityScore":{"type":"integer","nullable":true},"carbonFootprintGrams":{"type":"integer","nullable":true},"materials":{"type":"array","nullable":true,"items":{"type":"object","properties":{"name":{"type":"string","nullable":true},"percentage":{"type":"number","nullable":true},"recyclable":{"type":"boolean","nullable":true},"recycled":{"type":"boolean","nullable":true}}}},"certifications":{"type":"array","nullable":true,"items":{"type":"string"}},"countryOfOrigin":{"type":"string","nullable":true}},"description":"Optional DPP evidence override (preview unsaved data). Defaults to the stored DPP."},"AddOrderItem":{"type":"object","properties":{"productId":{"type":"string","minLength":1,"example":"prod_01"},"variantId":{"type":"string","example":"var_01"},"quantity":{"type":"integer","minimum":1,"example":1,"description":"Units to add"}},"required":["productId","quantity"]},"UpdateOrderItem":{"type":"object","properties":{"quantity":{"type":"integer","minimum":1,"example":3,"description":"New quantity for the line item"}},"required":["quantity"]},"CategoryTreeResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CategoryTreeNode"}}},"required":["data"]},"CategoryTreeNode":{"type":"object","properties":{"id":{"type":"string","example":"cat_abc123def456"},"name":{"type":"string","example":"Electronics"},"slug":{"type":"string","example":"electronics"},"parentId":{"type":"string","nullable":true,"example":null},"description":{"type":"string","nullable":true,"example":"All electronic devices"},"imageUrl":{"type":"string","nullable":true,"example":null},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"productCount":{"type":"integer","example":5},"children":{"type":"array","items":{"$ref":"#/components/schemas/CategoryTreeNode"},"description":"Child categories"}},"required":["id","name","slug","parentId","description","imageUrl","position","createdAt","updatedAt","productCount","children"]},"AgenticSettings":{"type":"object","properties":{"mcpEnabled":{"type":"boolean"},"ucpManifestEnabled":{"type":"boolean"},"acpEnabled":{"type":"boolean"},"llmsTxtEnabled":{"type":"boolean"},"agentFeedEnabled":{"type":"boolean"}},"required":["mcpEnabled","ucpManifestEnabled","acpEnabled","llmsTxtEnabled","agentFeedEnabled"]},"PatchAgenticSettings":{"type":"object","properties":{"mcpEnabled":{"type":"boolean"},"ucpManifestEnabled":{"type":"boolean"},"acpEnabled":{"type":"boolean"},"llmsTxtEnabled":{"type":"boolean"},"agentFeedEnabled":{"type":"boolean"}}},"AgentAccessLogEntry":{"type":"object","properties":{"id":{"type":"string"},"protocol":{"type":"string","enum":["mcp","ucp","acp","llms","feed"]},"agentHint":{"type":"string","nullable":true},"path":{"type":"string"},"statusCode":{"type":"integer"},"createdAt":{"type":"integer"}},"required":["id","protocol","agentHint","path","statusCode","createdAt"]},"PaymentMethodsSettings":{"type":"object","properties":{"enabled":{"type":"array","items":{"type":"string"},"example":["card","klarna"]},"supported":{"type":"array","items":{"type":"string"}},"applePay":{"type":"object","properties":{"available":{"type":"boolean"},"disabledReason":{"type":"string","nullable":true}},"required":["available","disabledReason"]},"paypal":{"type":"object","properties":{"configured":{"type":"boolean"}},"required":["configured"]}},"required":["enabled","supported","applePay","paypal"]},"PaymentMethodsProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]},"UpdatePaymentMethodsResponse":{"type":"object","properties":{"enabled":{"type":"array","items":{"type":"string"}}},"required":["enabled"]},"PaymentMethodsUpdateProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]},"UpdatePaymentMethods":{"type":"object","properties":{"methods":{"type":"array","items":{"type":"string","enum":["card","klarna","affirm","afterpay_clearpay"]},"minItems":1,"example":["card","klarna","affirm"],"description":"`card` is always implicitly enabled even if omitted."}},"required":["methods"]},"PaymentGatewaySummary":{"type":"object","properties":{"provider":{"type":"string","example":"redsys"},"isActive":{"type":"boolean"},"isTestMode":{"type":"boolean"},"publicCredentials":{"type":"object","additionalProperties":{"type":"string"},"example":{"merchantCode":"999008881","terminal":"001"},"description":"Display-safe credential fields only — secret values are NEVER included."},"hasSecrets":{"type":"boolean"},"config":{"type":"object","additionalProperties":{"nullable":true},"example":{"bizumEnabled":true},"description":"Free-form provider config (manual methods: instructions/iban/feeCents…)."}},"required":["provider","isActive","isTestMode","publicCredentials","hasSecrets","config"]},"PaymentGatewaysProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]},"UpsertPaymentGateway":{"type":"object","properties":{"isActive":{"type":"boolean"},"isTestMode":{"type":"boolean"},"credentials":{"type":"object","additionalProperties":{"type":"string"}},"config":{"type":"object","additionalProperties":{"nullable":true}}},"required":["isActive","isTestMode"]},"PutExportaSettings":{"type":"object","properties":{"enabledLocales":{"type":"array","items":{"type":"string","enum":["es","en","ca","eu","gl","pt"]},"minItems":1,"maxItems":6,"example":["es","en","ca"]},"displayCurrencies":{"type":"array","items":{"type":"string","minLength":3,"maxLength":3},"maxItems":30,"example":["EUR","USD","GBP"]},"taxDisplay":{"type":"string","enum":["inclusive","exclusive","auto"],"example":"inclusive"}},"required":["enabledLocales","displayCurrencies","taxDisplay"]},"ThemeTokensPatch":{"type":"object","properties":{"colors":{"type":"object","properties":{"primary":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"secondary":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"accent":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"background":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"foreground":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"muted":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"border":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"},"destructive":{"type":"string","pattern":"^oklch\\(\\s*\\d+(?:\\.\\d+)?%?\\s+\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?(?:\\s*\\/\\s*(?:\\d+(?:\\.\\d+)?%?))?\\s*\\)$"}}},"fonts":{"type":"object","properties":{"sans":{"type":"string","minLength":1,"maxLength":200},"serif":{"type":"string","minLength":1,"maxLength":200},"mono":{"type":"string","minLength":1,"maxLength":200}}},"layout":{"type":"object","properties":{"header":{"type":"string","enum":["minimal","classic","full"]},"footer":{"type":"string","enum":["minimal","rich"]},"product":{"type":"string","enum":["compact","editorial","immersive"]}}},"logo":{"type":"object","nullable":true,"properties":{"url":{"type":"string","format":"uri"},"removedBg":{"type":"boolean","default":false}},"required":["url"]}},"example":{"colors":{"primary":"oklch(60% 0.18 250)"}}},"ThemePreviewSessionRequest":{"type":"object","properties":{"tokens":{"$ref":"#/components/schemas/ThemeTokens"}},"required":["tokens"]},"SubscribeNewsletterResponse":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"alreadySubscribed":{"type":"boolean"}},"required":["success","message","alreadySubscribed"]},"NewsletterError":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status","detail"]},"SubscribeNewsletter":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"customer@example.com","description":"Email address to subscribe"}},"required":["email"]},"UnsubscribeNewsletterResponse":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}},"required":["success","message"]},"UnsubscribeNewsletter":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"customer@example.com","description":"Email address to unsubscribe"}},"required":["email"]},"NewsletterListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/NewsletterSubscriber"}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]},"NewsletterSubscriber":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string","format":"email"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"status":{"type":"string","enum":["active","unsubscribed"]},"subscribedAt":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","email","firstName","lastName","status","subscribedAt","createdAt"]},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"secret":{"type":"string"},"isActive":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenantId","url","events","secret","isActive","createdAt","updatedAt"]},"CreateWebhookEndpoint":{"type":"object","properties":{"url":{"type":"string","format":"uri","example":"https://example.com/webhooks"},"events":{"type":"array","items":{"type":"string"},"minItems":1,"example":["order.created","product.updated"]}},"required":["url","events"]},"UpdateWebhookEndpoint":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"},"minItems":1},"isActive":{"type":"boolean"}}},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string"},"endpointId":{"type":"string"},"event":{"type":"string"},"payload":{"type":"string"},"responseStatus":{"type":"number","nullable":true},"responseBody":{"type":"string","nullable":true},"attempts":{"type":"number"},"maxAttempts":{"type":"number"},"nextRetryAt":{"type":"string","nullable":true},"lastAttemptedAt":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","in_flight","delivered","failed","exhausted"]},"requestId":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","endpointId","event","payload","responseStatus","responseBody","attempts","status","requestId","createdAt"]},"WebhookRetryResponse":{"type":"object","properties":{"delivery":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"attempts":{"type":"integer"},"nextRetryAt":{"type":"string","nullable":true}},"required":["id","status","attempts","nextRetryAt"]}},"required":["delivery"]},"TestWebhookResponse":{"type":"object","properties":{"accepted":{"type":"boolean","enum":[true]},"deliveryId":{"type":"string"}},"required":["accepted"]},"TestWebhookBody":{"type":"object","properties":{"eventType":{"type":"string","enum":["order.created","order.updated","order.cancelled","order.fulfilled","order.refunded","product.created","product.updated","product.deleted","customer.created","customer.updated","payment.succeeded","payment.failed","payment.refunded","subscription.created","subscription.cancelled","subscription.renewed","cart.abandoned","review.created","inventory.low"],"example":"order.created","description":"The event type to simulate in the test delivery"}},"required":["eventType"]},"WebhookDeliveryDetail":{"type":"object","properties":{"id":{"type":"string"},"endpointId":{"type":"string"},"event":{"type":"string"},"payload":{"type":"string"},"requestHeaders":{"type":"object","additionalProperties":{"type":"string"}},"requestBody":{"type":"string"},"responseStatus":{"type":"number","nullable":true},"responseBody":{"type":"string","nullable":true},"attempts":{"type":"number"},"maxAttempts":{"type":"number"},"status":{"type":"string","enum":["pending","in_flight","delivered","failed","exhausted"]},"lastAttemptedAt":{"type":"string","nullable":true},"nextRetryAt":{"type":"string","nullable":true},"requestId":{"type":"string","nullable":true},"createdAt":{"type":"string"},"duration":{"type":"number","nullable":true}},"required":["id","endpointId","event","payload","requestBody","responseStatus","responseBody","attempts","maxAttempts","status","lastAttemptedAt","nextRetryAt","requestId","createdAt"]},"WebhookScopedRetryResponse":{"type":"object","properties":{"delivery":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"attempts":{"type":"integer"},"nextRetryAt":{"type":"string","nullable":true}},"required":["id","status","attempts","nextRetryAt"]}},"required":["delivery"]},"MarkOrderPaidResponse":{"type":"object","properties":{"orderId":{"type":"string"},"status":{"type":"string","example":"confirmed"},"paymentStatus":{"type":"string","example":"succeeded"},"alreadyPaid":{"type":"boolean"}},"required":["orderId","status","paymentStatus","alreadyPaid"]},"MarkOrderPaidInput":{"type":"object","properties":{"reference":{"type":"string","maxLength":200,"description":"Bank/courier reconciliation reference"},"note":{"type":"string","maxLength":500}}},"CustomerGroupList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustomerGroup"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"]},"CustomerGroup":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":"string","nullable":true},"taxExempt":{"type":"boolean"},"requiresApproval":{"type":"boolean"},"defaultPaymentTerms":{"$ref":"#/components/schemas/PaymentTerms"},"isActive":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","slug","description","taxExempt","requiresApproval","defaultPaymentTerms","isActive","createdAt","updatedAt"]},"CreateCustomerGroup":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"example":"Wholesale Tier 1"},"slug":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[a-z0-9-]+$/i","example":"wholesale-1"},"description":{"type":"string","maxLength":500},"taxExempt":{"type":"boolean"},"requiresApproval":{"type":"boolean"},"defaultPaymentTerms":{"$ref":"#/components/schemas/PaymentTerms"},"isActive":{"type":"boolean"}},"required":["name","slug"]},"UpdateCustomerGroup":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"slug":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[a-z0-9-]+$/i"},"description":{"type":"string","nullable":true,"maxLength":500},"taxExempt":{"type":"boolean"},"requiresApproval":{"type":"boolean"},"defaultPaymentTerms":{"$ref":"#/components/schemas/PaymentTerms"},"isActive":{"type":"boolean"}}},"TierPriceList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TierPrice"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"]},"TierPrice":{"type":"object","properties":{"id":{"type":"string"},"productId":{"type":"string"},"variantId":{"type":"string","nullable":true},"customerGroupId":{"type":"string"},"minQty":{"type":"integer","minimum":1},"price":{"type":"integer","minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3},"startsAt":{"type":"string","nullable":true},"endsAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","productId","variantId","customerGroupId","minQty","price","currency","startsAt","endsAt","createdAt","updatedAt"]},"BulkTierPriceResult":{"type":"object","properties":{"created":{"type":"integer"},"skipped":{"type":"integer"},"errors":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"message":{"type":"string"}},"required":["index","message"]}}},"required":["created","skipped","errors"]},"BulkTierPrices":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/CreateTierPrice"},"minItems":1,"maxItems":500}},"required":["items"]},"CreateTierPrice":{"type":"object","properties":{"productId":{"type":"string","minLength":1},"variantId":{"type":"string","minLength":1},"customerGroupId":{"type":"string","minLength":1},"minQty":{"type":"integer","minimum":1},"price":{"type":"integer","minimum":0,"example":1999,"description":"Price in cents"},"currency":{"type":"string","minLength":3,"maxLength":3},"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"}},"required":["productId","customerGroupId","price"]},"UpdateTierPrice":{"type":"object","properties":{"minQty":{"type":"integer","minimum":1},"price":{"type":"integer","minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3},"startsAt":{"type":"string","nullable":true,"format":"date-time"},"endsAt":{"type":"string","nullable":true,"format":"date-time"}}},"PriceListList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PriceList"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"]},"PriceList":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"customerGroupId":{"type":"string","nullable":true},"accountId":{"type":"string","nullable":true},"currency":{"type":"string","minLength":3,"maxLength":3},"priority":{"type":"integer"},"isActive":{"type":"boolean"},"startsAt":{"type":"string","nullable":true},"endsAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","description","customerGroupId","accountId","currency","priority","isActive","startsAt","endsAt","createdAt","updatedAt"]},"PriceListWithItems":{"allOf":[{"$ref":"#/components/schemas/PriceList"},{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PriceListItem"}}},"required":["items"]}]},"PriceListItem":{"type":"object","properties":{"id":{"type":"string"},"priceListId":{"type":"string"},"productId":{"type":"string"},"variantId":{"type":"string","nullable":true},"price":{"type":"integer","minimum":0},"minQty":{"type":"integer","minimum":1},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","priceListId","productId","variantId","price","minQty","createdAt","updatedAt"]},"CreatePriceList":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":160,"example":"Acme Corp Negotiated 2026"},"description":{"type":"string","maxLength":500},"customerGroupId":{"type":"string","minLength":1},"accountId":{"type":"string","minLength":1},"currency":{"type":"string","minLength":3,"maxLength":3},"priority":{"type":"integer"},"isActive":{"type":"boolean"},"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"},"items":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string","minLength":1},"variantId":{"type":"string","minLength":1},"price":{"type":"integer","minimum":0,"example":7000,"description":"Price in cents"},"minQty":{"type":"integer","minimum":1}},"required":["productId","price"]},"maxItems":1000}},"required":["name"]},"SetPriceListItems":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string","minLength":1},"variantId":{"type":"string","minLength":1},"price":{"type":"integer","minimum":0,"example":7000,"description":"Price in cents"},"minQty":{"type":"integer","minimum":1}},"required":["productId","price"]},"minItems":1,"maxItems":1000}},"required":["items"]},"UpdatePriceList":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":160},"description":{"type":"string","nullable":true,"maxLength":500},"currency":{"type":"string","minLength":3,"maxLength":3},"priority":{"type":"integer"},"isActive":{"type":"boolean"},"startsAt":{"type":"string","nullable":true,"format":"date-time"},"endsAt":{"type":"string","nullable":true,"format":"date-time"}}},"B2bAccountList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/B2bAccount"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"]},"CreateB2bAccount":{"type":"object","properties":{"customerId":{"type":"string","minLength":1},"companyName":{"type":"string","minLength":1,"maxLength":200},"taxId":{"type":"string","maxLength":50},"industry":{"type":"string","maxLength":120},"websiteUrl":{"type":"string","maxLength":255,"format":"uri"},"creditLimit":{"type":"integer","minimum":0},"paymentTerms":{"$ref":"#/components/schemas/PaymentTerms"},"approverId":{"type":"string"},"status":{"$ref":"#/components/schemas/B2bAccountStatus"}},"required":["customerId","companyName"]},"UpdateB2bAccount":{"type":"object","properties":{"companyName":{"type":"string","minLength":1,"maxLength":200},"taxId":{"type":"string","nullable":true,"maxLength":50},"industry":{"type":"string","nullable":true,"maxLength":120},"websiteUrl":{"type":"string","nullable":true,"maxLength":255,"format":"uri"},"creditLimit":{"type":"integer","minimum":0},"paymentTerms":{"$ref":"#/components/schemas/PaymentTerms"},"approverId":{"type":"string","nullable":true},"status":{"$ref":"#/components/schemas/B2bAccountStatus"}}},"QuoteList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/QuoteListItem"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"]},"QuoteListItem":{"allOf":[{"$ref":"#/components/schemas/Quote"},{"type":"object","properties":{"accountName":{"type":"string","nullable":true}},"required":["accountName"]}]},"UpdateQuote":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string","minLength":1},"variantId":{"type":"string","minLength":1},"qty":{"type":"integer","minimum":1},"unitPrice":{"type":"integer","minimum":0},"note":{"type":"string","maxLength":500}},"required":["productId","qty"]},"minItems":1,"maxItems":200},"customerNote":{"type":"string","maxLength":2000},"internalNote":{"type":"string","maxLength":2000},"expiresAt":{"type":"string","format":"date-time"},"discountTotal":{"type":"integer","minimum":0},"shippingTotal":{"type":"integer","minimum":0}}},"RejectQuote":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500}},"required":["reason"]},"PurchaseOrderList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseOrder"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"]},"UpdatePurchaseOrder":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/PurchaseOrderStatus"},"attachmentUrl":{"type":"string","nullable":true,"format":"uri"},"dueDate":{"type":"string","nullable":true,"format":"date-time"},"paidAt":{"type":"string","nullable":true,"format":"date-time"}}},"ApprovalRequestAdminList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ApprovalRequest"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"]},"CreditMemoList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CreditMemo"}}},"required":["data"]},"CreditMemo":{"type":"object","properties":{"id":{"type":"string"},"memoNumber":{"type":"string"},"accountId":{"type":"string"},"type":{"$ref":"#/components/schemas/CreditMemoType"},"amountCents":{"type":"integer"},"appliedCents":{"type":"integer"},"remainingCents":{"type":"integer"},"reason":{"type":"string","nullable":true},"status":{"$ref":"#/components/schemas/CreditMemoStatus"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","memoNumber","accountId","type","amountCents","appliedCents","remainingCents","reason","status","createdAt","updatedAt"]},"CreditMemoType":{"type":"string","enum":["online","offline"]},"CreditMemoStatus":{"type":"string","enum":["open","partially_applied","applied","void"]},"CreateCreditMemo":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/CreditMemoType"},"amountCents":{"type":"integer","minimum":0,"exclusiveMinimum":true},"reason":{"type":"string","maxLength":2000}},"required":["type","amountCents"]},"AccountStatement":{"type":"object","properties":{"accountId":{"type":"string"},"creditLimitCents":{"type":"integer"},"creditUsedCents":{"type":"integer"},"creditAvailableCents":{"type":"integer"},"outstandingCents":{"type":"integer"},"creditMemoBalanceCents":{"type":"integer"},"netDueCents":{"type":"integer"},"aging":{"$ref":"#/components/schemas/AgingBuckets"},"asOf":{"type":"string"}},"required":["accountId","creditLimitCents","creditUsedCents","creditAvailableCents","outstandingCents","creditMemoBalanceCents","netDueCents","aging","asOf"]},"AgingBuckets":{"type":"object","properties":{"b0_30":{"type":"integer"},"b31_60":{"type":"integer"},"b61_90":{"type":"integer"},"b90_plus":{"type":"integer"}},"required":["b0_30","b31_60","b61_90","b90_plus"]},"ApplyCreditMemo":{"type":"object","properties":{"orderId":{"type":"string"},"amountCents":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["amountCents"]},"ReturnReason":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"label":{"type":"string"},"customerVisible":{"type":"boolean"},"autoApprove":{"type":"boolean"},"isActive":{"type":"boolean"},"position":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","code","label","customerVisible","autoApprove","isActive","position","createdAt","updatedAt"]},"ReturnProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedTransitions":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]},"CreateReturnReason":{"type":"object","properties":{"code":{"type":"string","minLength":1,"maxLength":60,"pattern":"^[a-z0-9_]+$"},"label":{"type":"string","minLength":1,"maxLength":200},"customerVisible":{"type":"boolean"},"autoApprove":{"type":"boolean"},"isActive":{"type":"boolean"},"position":{"type":"integer","minimum":0}},"required":["code","label"]},"UpdateReturnReason":{"type":"object","properties":{"code":{"type":"string","minLength":1,"maxLength":60,"pattern":"^[a-z0-9_]+$"},"label":{"type":"string","minLength":1,"maxLength":200},"customerVisible":{"type":"boolean"},"autoApprove":{"type":"boolean"},"isActive":{"type":"boolean"},"position":{"type":"integer","minimum":0}}},"ReturnDetail":{"allOf":[{"$ref":"#/components/schemas/Return"},{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ReturnItem"}}},"required":["items"]}]},"ReturnItem":{"type":"object","properties":{"id":{"type":"string"},"returnId":{"type":"string"},"orderItemId":{"type":"string"},"quantity":{"type":"integer","minimum":0,"exclusiveMinimum":true},"reasonId":{"type":"string","nullable":true},"conditionOnArrival":{"type":"string","nullable":true,"enum":["new","good","damaged","unusable",null]},"restock":{"type":"boolean"},"unitRefundAmount":{"type":"integer","minimum":0},"totalRefundAmount":{"type":"integer","minimum":0},"createdAt":{"type":"string"}},"required":["id","returnId","orderItemId","quantity","reasonId","conditionOnArrival","restock","unitRefundAmount","totalRefundAmount","createdAt"]},"Return":{"type":"object","properties":{"id":{"type":"string"},"returnNumber":{"type":"string"},"orderId":{"type":"string"},"customerId":{"type":"string","nullable":true},"status":{"type":"string","enum":["requested","approved","rejected","shipped_by_customer","received","inspecting","refunded","cancelled"]},"reasonId":{"type":"string","nullable":true},"customerNote":{"type":"string","nullable":true},"internalNote":{"type":"string","nullable":true},"refundAmount":{"type":"integer","minimum":0},"refundMethod":{"type":"string","enum":["original_payment","store_credit","gift_card","manual"]},"refundId":{"type":"string","nullable":true},"restock":{"type":"boolean"},"shippingLabelUrl":{"type":"string","nullable":true},"trackingNumber":{"type":"string","nullable":true},"approvedBy":{"type":"string","nullable":true},"approvedAt":{"type":"string","nullable":true},"receivedAt":{"type":"string","nullable":true},"refundedAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","returnNumber","orderId","customerId","status","reasonId","customerNote","internalNote","refundAmount","refundMethod","refundId","restock","shippingLabelUrl","trackingNumber","approvedBy","approvedAt","receivedAt","refundedAt","createdAt","updatedAt"]},"CreateReturn":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"orderItemId":{"type":"string","minLength":1},"quantity":{"type":"integer","minimum":0,"exclusiveMinimum":true},"reasonCode":{"type":"string"}},"required":["orderItemId","quantity"]},"minItems":1,"description":"Order items to return"},"customerNote":{"type":"string","maxLength":2000},"refundMethod":{"type":"string","enum":["original_payment","store_credit"]}},"required":["items"]},"PagedReturns":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Return"}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]},"UpdateReturnStatus":{"type":"object","properties":{"toStatus":{"type":"string","enum":["requested","approved","rejected","shipped_by_customer","received","inspecting","refunded","cancelled"]},"internalNote":{"type":"string","maxLength":2000},"refundAmount":{"type":"integer","minimum":0}},"required":["toStatus"]},"ReturnStatusHistoryEntry":{"type":"object","properties":{"id":{"type":"string"},"returnId":{"type":"string"},"fromStatus":{"type":"string","nullable":true},"toStatus":{"type":"string"},"changedByUserId":{"type":"string","nullable":true},"changedByActor":{"type":"string","nullable":true,"enum":["admin","customer","system","webhook",null]},"reason":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"createdAt":{"type":"integer"}},"required":["id","returnId","fromStatus","toStatus","changedByUserId","changedByActor","reason","notes","createdAt"]},"ModerateReview":{"type":"object","properties":{"status":{"allOf":[{"$ref":"#/components/schemas/ReviewStatus"},{"description":"New moderation status."}]}},"required":["status"]},"DownloadProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"Download":{"type":"object","properties":{"id":{"type":"string"},"productId":{"type":"string"},"variantId":{"type":"string","nullable":true},"fileName":{"type":"string"},"fileUrl":{"type":"string"},"fileSizeBytes":{"type":"integer","nullable":true},"mimeType":{"type":"string","nullable":true},"downloadLimit":{"type":"integer"},"expiresDays":{"type":"integer"},"position":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","productId","variantId","fileName","fileUrl","fileSizeBytes","mimeType","downloadLimit","expiresDays","position","createdAt","updatedAt"]},"CreateDownload":{"type":"object","properties":{"variantId":{"type":"string"},"fileName":{"type":"string","minLength":1,"maxLength":255},"fileUrl":{"type":"string","minLength":1},"fileSizeBytes":{"type":"integer","minimum":0},"mimeType":{"type":"string","maxLength":120},"downloadLimit":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":100},"expiresDays":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":3650},"position":{"type":"integer","minimum":0}},"required":["fileName","fileUrl"]},"GiftCardBalance":{"type":"object","properties":{"currentBalance":{"type":"integer"},"currency":{"type":"string"},"status":{"type":"string","enum":["active","expired","fully_redeemed","voided"]}},"required":["currentBalance","currency","status"]},"GiftCardProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"CheckGiftCardBalance":{"type":"object","properties":{"code":{"type":"string","minLength":1}},"required":["code"]},"GiftCardRedeemResult":{"type":"object","properties":{"redeemed":{"type":"integer"},"balanceAfter":{"type":"integer"},"currency":{"type":"string"},"status":{"type":"string","enum":["active","expired","fully_redeemed","voided"]}},"required":["redeemed","balanceAfter","currency","status"]},"RedeemGiftCard":{"type":"object","properties":{"code":{"type":"string","minLength":1},"amount":{"type":"integer","minimum":0,"exclusiveMinimum":true},"orderId":{"type":"string"}},"required":["code"]},"GiftCard":{"type":"object","properties":{"id":{"type":"string"},"productId":{"type":"string","nullable":true},"orderId":{"type":"string","nullable":true},"recipientEmail":{"type":"string","nullable":true},"recipientName":{"type":"string","nullable":true},"initialBalance":{"type":"integer"},"currentBalance":{"type":"integer"},"currency":{"type":"string"},"status":{"type":"string","enum":["active","expired","fully_redeemed","voided"]},"expiresAt":{"type":"string","nullable":true},"issuedAt":{"type":"string"},"message":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","productId","orderId","recipientEmail","recipientName","initialBalance","currentBalance","currency","status","expiresAt","issuedAt","message","createdAt","updatedAt"]},"UpdateGiftCard":{"type":"object","properties":{"expiresAt":{"type":"string","nullable":true,"format":"date-time"},"recipientEmail":{"type":"string","nullable":true,"format":"email"},"message":{"type":"string","nullable":true,"maxLength":500}}},"CreateGiftCard":{"type":"object","properties":{"initialBalance":{"type":"integer","minimum":0,"exclusiveMinimum":true},"currency":{"type":"string","minLength":3,"maxLength":3},"recipientEmail":{"type":"string","format":"email"},"recipientName":{"type":"string","maxLength":200},"message":{"type":"string","maxLength":500},"expiresAt":{"type":"string","format":"date-time"}},"required":["initialBalance"]},"CustomerSubscription":{"type":"object","properties":{"id":{"type":"string"},"customerId":{"type":"string"},"planId":{"type":"string"},"stripeSubscriptionId":{"type":"string","nullable":true},"status":{"type":"string","enum":["trialing","active","past_due","paused","cancelled","incomplete"]},"currentPeriodStart":{"type":"string","nullable":true},"currentPeriodEnd":{"type":"string","nullable":true},"trialEndsAt":{"type":"string","nullable":true},"pausedAt":{"type":"string","nullable":true},"cancelledAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","customerId","planId","stripeSubscriptionId","status","currentPeriodStart","currentPeriodEnd","trialEndsAt","pausedAt","cancelledAt","createdAt","updatedAt"]},"SubscriptionProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"SubscriptionPlan":{"type":"object","properties":{"id":{"type":"string"},"productId":{"type":"string"},"stripePriceId":{"type":"string","nullable":true},"billingCycle":{"type":"string","enum":["weekly","biweekly","monthly","quarterly","yearly"]},"intervalCount":{"type":"integer"},"trialDays":{"type":"integer"},"cancelAtPeriodEnd":{"type":"boolean"},"amount":{"type":"integer"},"currency":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","productId","stripePriceId","billingCycle","intervalCount","trialDays","cancelAtPeriodEnd","amount","currency","createdAt","updatedAt"]},"CreateSubscriptionPlan":{"type":"object","properties":{"stripePriceId":{"type":"string"},"billingCycle":{"type":"string","enum":["weekly","biweekly","monthly","quarterly","yearly"]},"intervalCount":{"type":"integer","minimum":0,"exclusiveMinimum":true},"trialDays":{"type":"integer","minimum":0},"cancelAtPeriodEnd":{"type":"boolean"},"amount":{"type":"integer","minimum":0,"exclusiveMinimum":true},"currency":{"type":"string","minLength":3,"maxLength":3}},"required":["amount"]},"UpdateSubscriptionPlan":{"type":"object","properties":{"stripePriceId":{"type":"string"},"billingCycle":{"type":"string","enum":["weekly","biweekly","monthly","quarterly","yearly"]},"intervalCount":{"type":"integer","minimum":0,"exclusiveMinimum":true},"trialDays":{"type":"integer","minimum":0},"cancelAtPeriodEnd":{"type":"boolean"},"amount":{"type":"integer","minimum":0,"exclusiveMinimum":true},"currency":{"type":"string","minLength":3,"maxLength":3}}},"SalesReport":{"type":"object","properties":{"rows":{"type":"array","items":{"type":"object","properties":{"bucket":{"type":"string","description":"Time bucket key (date / ISO week / month)"},"orders_count":{"type":"integer"},"revenue_cents":{"type":"integer"},"refunds_count":{"type":"integer"},"refunds_cents":{"type":"integer"},"net_revenue_cents":{"type":"integer"},"avg_order_value_cents":{"type":"integer"}},"required":["bucket","orders_count","revenue_cents","refunds_count","refunds_cents","net_revenue_cents","avg_order_value_cents"]}},"totals":{"type":"object","properties":{"orders_count":{"type":"integer"},"revenue_cents":{"type":"integer"},"refunds_count":{"type":"integer"},"refunds_cents":{"type":"integer"},"net_revenue_cents":{"type":"integer"},"avg_order_value_cents":{"type":"integer"}},"required":["orders_count","revenue_cents","refunds_count","refunds_cents","net_revenue_cents","avg_order_value_cents"]},"period":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"group_by":{"type":"string","enum":["day","week","month"]}},"required":["from","to","group_by"]}},"required":["rows","totals","period"]},"ProductsReport":{"type":"object","properties":{"rows":{"type":"array","items":{"type":"object","properties":{"product_id":{"type":"string"},"product_name":{"type":"string","nullable":true},"units_sold":{"type":"integer"},"revenue_cents":{"type":"integer"},"orders_count":{"type":"integer"}},"required":["product_id","product_name","units_sold","revenue_cents","orders_count"]}},"totals":{"type":"object","properties":{"units_sold":{"type":"integer"},"revenue_cents":{"type":"integer"}},"required":["units_sold","revenue_cents"]},"period":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"group_by":{"type":"string","enum":["day","week","month"]}},"required":["from","to","group_by"]}},"required":["rows","totals","period"]},"InventoryReport":{"type":"object","properties":{"rows":{"type":"array","items":{"type":"object","properties":{"product_variant_id":{"type":"string"},"available_qty":{"type":"integer"},"reserved_qty":{"type":"integer"},"reorder_point":{"type":"integer"},"below_reorder_point":{"type":"boolean"},"last_sync_at":{"type":"integer"}},"required":["product_variant_id","available_qty","reserved_qty","reorder_point","below_reorder_point","last_sync_at"]}},"totals":{"type":"object","properties":{"variants_tracked":{"type":"integer"},"available_qty":{"type":"integer"},"reserved_qty":{"type":"integer"},"below_reorder_count":{"type":"integer"}},"required":["variants_tracked","available_qty","reserved_qty","below_reorder_count"]}},"required":["rows","totals"]},"CustomersReport":{"type":"object","properties":{"rows":{"type":"array","items":{"type":"object","properties":{"customer_id":{"type":"string"},"total_orders":{"type":"integer"},"total_spent_cents":{"type":"integer"},"avg_order_value_cents":{"type":"integer"},"first_order_at":{"type":"integer","nullable":true},"last_order_at":{"type":"integer","nullable":true}},"required":["customer_id","total_orders","total_spent_cents","avg_order_value_cents","first_order_at","last_order_at"]}},"totals":{"type":"object","properties":{"customers":{"type":"integer"},"total_spent_cents":{"type":"integer"},"avg_ltv_cents":{"type":"integer"}},"required":["customers","total_spent_cents","avg_ltv_cents"]}},"required":["rows","totals"]},"FinanceReport":{"type":"object","properties":{"gross_revenue_cents":{"type":"integer"},"refunds_cents":{"type":"integer"},"net_revenue_cents":{"type":"integer"},"tax_collected_cents":{"type":"integer"},"shipping_collected_cents":{"type":"integer"},"discounts_cents":{"type":"integer"},"orders_count":{"type":"integer"},"by_currency":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string"},"gross_revenue_cents":{"type":"integer"},"tax_collected_cents":{"type":"integer"},"shipping_collected_cents":{"type":"integer"},"discounts_cents":{"type":"integer"},"orders_count":{"type":"integer"}},"required":["currency","gross_revenue_cents","tax_collected_cents","shipping_collected_cents","discounts_cents","orders_count"]}},"period":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"]}},"required":["gross_revenue_cents","refunds_cents","net_revenue_cents","tax_collected_cents","shipping_collected_cents","discounts_cents","orders_count","by_currency","period"]},"LoyaltyProgram":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"isActive":{"type":"integer"},"pointsPerCurrencyUnit":{"type":"integer"},"pointsValueCents":{"type":"integer"},"minRedeemPoints":{"type":"integer"},"expirationDays":{"type":"integer","nullable":true},"signupBonus":{"type":"integer"},"birthdayBonus":{"type":"integer"},"reviewBonus":{"type":"integer"},"referralBonus":{"type":"integer"},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","name","isActive","pointsPerCurrencyUnit","pointsValueCents","minRedeemPoints","expirationDays","signupBonus","birthdayBonus","reviewBonus","referralBonus","createdAt","updatedAt"]},"LoyaltyProblem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"UpsertLoyaltyProgram":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"isActive":{"type":"integer","minimum":0,"maximum":1},"pointsPerCurrencyUnit":{"type":"integer","minimum":1},"pointsValueCents":{"type":"integer","minimum":1},"minRedeemPoints":{"type":"integer","minimum":1},"expirationDays":{"type":"integer","nullable":true,"minimum":0,"exclusiveMinimum":true},"signupBonus":{"type":"integer","minimum":0},"birthdayBonus":{"type":"integer","minimum":0},"reviewBonus":{"type":"integer","minimum":0},"referralBonus":{"type":"integer","minimum":0}},"required":["name"]},"LoyaltyTier":{"type":"object","properties":{"id":{"type":"string"},"programId":{"type":"string"},"name":{"type":"string"},"minPoints":{"type":"integer"},"multiplier":{"type":"number"},"benefits":{"type":"string","nullable":true},"badgeColor":{"type":"string","nullable":true},"position":{"type":"integer"},"createdAt":{"type":"integer"}},"required":["id","programId","name","minPoints","multiplier","benefits","badgeColor","position","createdAt"]},"CreateLoyaltyTier":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"minPoints":{"type":"integer","minimum":0},"multiplier":{"type":"number","minimum":0.1,"maximum":10},"benefits":{"type":"string","nullable":true,"maxLength":2000},"badgeColor":{"type":"string","nullable":true,"maxLength":20},"position":{"type":"integer","minimum":0}},"required":["name","minPoints"]},"UpdateLoyaltyTier":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"minPoints":{"type":"integer","minimum":0},"multiplier":{"type":"number","minimum":0.1,"maximum":10},"benefits":{"type":"string","nullable":true,"maxLength":2000},"badgeColor":{"type":"string","nullable":true,"maxLength":20},"position":{"type":"integer","minimum":0}}},"CustomerLoyalty":{"type":"object","nullable":true,"properties":{"customerId":{"type":"string"},"programId":{"type":"string"},"totalEarned":{"type":"integer"},"totalRedeemed":{"type":"integer"},"currentBalance":{"type":"integer"},"tierId":{"type":"string","nullable":true},"tierName":{"type":"string","nullable":true},"lastActivityAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["customerId","programId","totalEarned","totalRedeemed","currentBalance","tierId","tierName","lastActivityAt","createdAt","updatedAt"]},"LoyaltyTransaction":{"type":"object","properties":{"id":{"type":"string"},"customerId":{"type":"string"},"programId":{"type":"string"},"type":{"type":"string","enum":["earned","redeemed","adjusted","expired","bonus"]},"source":{"type":"string","enum":["order","signup","birthday","review","referral","manual","expiration"]},"points":{"type":"integer"},"balanceAfter":{"type":"integer"},"orderId":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"expiresAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"}},"required":["id","customerId","programId","type","source","points","balanceAfter","orderId","note","expiresAt","createdAt"]},"LoyaltyManualAdjust":{"type":"object","properties":{"customerId":{"type":"string","minLength":1},"points":{"type":"integer"},"note":{"type":"string","maxLength":500}},"required":["customerId","points"]},"LoyaltyStats":{"type":"object","properties":{"totalMembers":{"type":"integer"},"pointsOutstanding":{"type":"integer"},"totalTransactions":{"type":"integer"},"pointsIssuedAllTime":{"type":"integer"},"pointsRedeemedAllTime":{"type":"integer"},"redemptionRate":{"type":"number"}},"required":["totalMembers","pointsOutstanding","totalTransactions","pointsIssuedAllTime","pointsRedeemedAllTime","redemptionRate"]},"SequentialResults":{"type":"object","properties":{"method":{"type":"string","enum":["sequential_msprt"]},"alpha":{"type":"number"},"tau":{"type":"number"},"variants":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"},"assignments":{"type":"integer"},"conversions":{"type":"integer"},"conversionRate":{"type":"number"},"isControl":{"type":"boolean"},"alwaysValidPValue":{"type":"number"},"significant":{"type":"boolean"},"liftPct":{"type":"number","nullable":true}},"required":["key","name","assignments","conversions","conversionRate","isControl","alwaysValidPValue","significant","liftPct"]}},"winner":{"type":"string","nullable":true},"canStopEarly":{"type":"boolean"}},"required":["method","alpha","tau","variants","winner","canStopEarly"]},"MetafieldDefinition":{"type":"object","properties":{"id":{"type":"string"},"owner_type":{"type":"string","enum":["product","customer"]},"namespace":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["string","integer","number","boolean","json","date","url","color","money","rich_text"]},"description":{"type":"string","nullable":true},"validations":{"$ref":"#/components/schemas/MetafieldValidations"},"position":{"type":"integer"},"created_at":{"type":"integer"},"updated_at":{"type":"integer"}},"required":["id","owner_type","namespace","key","name","type","description","validations","position","created_at","updated_at"]},"MetafieldValidations":{"type":"object","properties":{"required":{"type":"boolean"},"min":{"type":"number"},"max":{"type":"number"},"regex":{"type":"string","maxLength":500},"options":{"type":"array","items":{"type":"string"},"maxItems":200}},"additionalProperties":false,"description":"Typed validation rules applied to metafield writes that match this definition.","example":{"required":true,"options":["aluminium","steel","titanium"]}},"SearchSynonym":{"type":"object","properties":{"id":{"type":"string"},"terms":{"type":"array","items":{"type":"string"}},"type":{"type":"string","enum":["oneway","twoway"]},"created_at":{"type":"integer"}},"required":["id","terms","type","created_at"]},"SearchBoostRule":{"type":"object","properties":{"id":{"type":"string"},"query_match":{"type":"string","nullable":true},"product_match":{"type":"array","nullable":true,"items":{"type":"string"}},"action":{"type":"string","enum":["boost","bury"]},"weight":{"type":"integer"},"position":{"type":"integer"},"is_active":{"type":"boolean"},"created_at":{"type":"integer"}},"required":["id","query_match","product_match","action","weight","position","is_active","created_at"]},"SearchAnalytics":{"type":"object","properties":{"total_queries":{"type":"integer"},"top_queries":{"type":"array","items":{"type":"object","properties":{"query":{"type":"string"},"count":{"type":"integer"},"last_used_at":{"type":"integer"}},"required":["query","count","last_used_at"]}},"zero_result_queries":{"type":"array","items":{"type":"object","properties":{"query":{"type":"string"},"count":{"type":"integer"},"last_used_at":{"type":"integer"}},"required":["query","count","last_used_at"]}}},"required":["total_queries","top_queries","zero_result_queries"]},"ListAutopilotActionsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AutopilotAction"}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"perPage":{"type":"integer"},"total":{"type":"integer"}},"required":["page","perPage","total"]}},"required":["data","pagination"]},"AutopilotAction":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending","approved","auto_applied","reverted","dismissed"]},"actionType":{"type":"string","enum":["hide_from_search","create_restock_suggestion","flag_order_for_review","apply_safety_discount"]},"payload":{"type":"object","additionalProperties":{"nullable":true}},"targetId":{"type":"string"},"priorStateSnapshot":{"type":"object","additionalProperties":{"nullable":true}},"impactCents":{"type":"integer"},"confidence":{"type":"number","minimum":0,"maximum":1},"reasoning":{"type":"string"},"detectedAt":{"type":"integer","nullable":true},"decidedAt":{"type":"integer","nullable":true},"decidedBy":{"type":"string","nullable":true},"tenantId":{"type":"string"},"createdAt":{"type":"integer","nullable":true},"updatedAt":{"type":"integer","nullable":true}},"required":["id","status","actionType","payload","targetId","priorStateSnapshot","impactCents","confidence","reasoning","detectedAt","decidedAt","decidedBy","tenantId","createdAt","updatedAt"]},"AutopilotError":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"AutopilotPolicy":{"type":"object","properties":{"autoApplyMaxImpactCents":{"type":"integer","minimum":0,"maximum":100000,"default":5000},"autoApplyMinConfidence":{"type":"number","minimum":0,"maximum":1,"default":0.7},"allowlistActionTypes":{"type":"array","items":{"type":"string","enum":["hide_from_search","create_restock_suggestion","flag_order_for_review","apply_safety_discount"]},"default":["hide_from_search"]}}},"CreateCompanyBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200,"example":"Acme Corp"},"status":{"type":"string","enum":["active","pending","blocked"],"default":"pending"},"credit_limit_cents":{"type":"integer","minimum":0,"default":0},"payment_terms_days":{"type":"integer","minimum":0,"maximum":365,"default":0},"default_price_list_id":{"type":"string","nullable":true},"tax_exempt":{"type":"boolean","default":false}},"required":["name"]},"UpdateCompanyBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"status":{"type":"string","enum":["active","pending","blocked"]},"credit_limit_cents":{"type":"integer","minimum":0},"payment_terms_days":{"type":"integer","minimum":0,"maximum":365},"default_price_list_id":{"type":"string","nullable":true},"tax_exempt":{"type":"boolean"}}},"CreateCompanyUserBody":{"type":"object","properties":{"customer_id":{"type":"string","minLength":1},"role":{"type":"string","enum":["admin","buyer","approver"],"default":"buyer"},"spending_limit_cents":{"type":"integer","nullable":true,"minimum":0},"is_active":{"type":"boolean","default":true}},"required":["customer_id"]},"CompanyCatalog":{"allOf":[{"$ref":"#/components/schemas/SharedCatalog"},{"type":"object","properties":{"via":{"type":"string","enum":["assigned","all"]}},"required":["via"]}]},"SharedCatalog":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"price_list_id":{"type":"string","nullable":true},"visibility":{"type":"string","enum":["all","companies","groups"]},"created_at":{"type":"integer"},"updated_at":{"type":"integer"}},"required":["id","name","price_list_id","visibility","created_at","updated_at"]},"CreateSharedCatalogBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"price_list_id":{"type":"string","nullable":true},"visibility":{"type":"string","enum":["all","companies","groups"],"default":"all"}},"required":["name"]},"UpdateSharedCatalogBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"price_list_id":{"type":"string","nullable":true},"visibility":{"type":"string","enum":["all","companies","groups"]}}},"AssignCompaniesBody":{"type":"object","properties":{"company_ids":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":500}},"required":["company_ids"]},"SetCatalogProductsBody":{"type":"object","properties":{"products":{"type":"array","items":{"type":"object","properties":{"product_id":{"type":"string","minLength":1},"is_visible":{"type":"boolean","default":true}},"required":["product_id"]},"minItems":1,"maxItems":1000}},"required":["products"]},"CreateRequisitionListBody":{"type":"object","properties":{"company_id":{"type":"string","minLength":1},"customer_id":{"type":"string","minLength":1},"name":{"type":"string","minLength":1,"maxLength":200}},"required":["company_id","customer_id","name"]},"RequisitionListItem":{"type":"object","properties":{"id":{"type":"string"},"requisition_list_id":{"type":"string"},"product_id":{"type":"string"},"variant_id":{"type":"string","nullable":true},"quantity":{"type":"integer"}},"required":["id","requisition_list_id","product_id","variant_id","quantity"]},"CreateRequisitionListItemBody":{"type":"object","properties":{"product_id":{"type":"string","minLength":1},"variant_id":{"type":"string","nullable":true},"quantity":{"type":"integer","minimum":1,"default":1}},"required":["product_id"]},"UpdateRequisitionListItemBody":{"type":"object","properties":{"quantity":{"type":"integer","minimum":1}},"required":["quantity"]},"CreateMarketBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"example":"Europe"},"handle":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9][a-z0-9-]*$","example":"europe"},"countries":{"type":"array","items":{"type":"string","minLength":2,"maxLength":2,"pattern":"^[A-Za-z]{2}$"},"maxItems":250,"default":[],"example":["ES","FR","DE"]},"region":{"type":"string","nullable":true,"maxLength":64,"example":"EU"},"presentmentCurrency":{"type":"string","minLength":3,"maxLength":3,"pattern":"^[A-Za-z]{3}$","example":"EUR"},"priceAdjustmentPct":{"type":"integer","minimum":-10000,"maximum":100000,"default":0,"example":1000},"roundingRule":{"type":"string","enum":["none","nearest_99","nearest_95","nearest_00","nearest_int"],"default":"none","example":"nearest_99"},"taxInclusive":{"type":"boolean","default":false,"example":true},"isDefault":{"type":"boolean","default":false,"example":false},"isActive":{"type":"boolean","default":true,"example":true}},"required":["name","handle","presentmentCurrency"]},"UpdateMarketBody":{"type":"object","properties":{"name":{"type":"string","minLength":1},"countries":{"type":"array","items":{"type":"string","minLength":2,"maxLength":2,"pattern":"^[A-Za-z]{2}$"},"maxItems":250},"region":{"type":"string","nullable":true,"maxLength":64},"presentmentCurrency":{"type":"string","minLength":3,"maxLength":3,"pattern":"^[A-Za-z]{3}$"},"priceAdjustmentPct":{"type":"integer","minimum":-10000,"maximum":100000},"roundingRule":{"type":"string","enum":["none","nearest_99","nearest_95","nearest_00","nearest_int"]},"taxInclusive":{"type":"boolean"},"isDefault":{"type":"boolean"},"isActive":{"type":"boolean"}}},"AgentKeyList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AgentKey"}}},"required":["data"]},"AgentKey":{"type":"object","properties":{"keyId":{"type":"string"},"tenantId":{"type":"string"},"status":{"type":"string","enum":["active","revoked"]},"scopes":{"type":"array","items":{"type":"string"}},"spendLimitCents":{"type":"number","nullable":true},"label":{"type":"string","nullable":true},"createdAt":{"type":"number"},"revokedAt":{"type":"number","nullable":true}},"required":["keyId","tenantId","status","scopes","spendLimitCents","label","createdAt","revokedAt"]},"RegisterAgentKeyBody":{"type":"object","properties":{"keyId":{"type":"string","minLength":3,"maxLength":128,"pattern":"^[a-zA-Z0-9_\\-:.]+$"},"publicJwk":{"$ref":"#/components/schemas/AgentJwk"},"scopes":{"type":"array","items":{"type":"string","minLength":1},"maxItems":20},"spendLimitCents":{"type":"integer","minimum":0},"label":{"type":"string","maxLength":200}},"required":["publicJwk"]},"AgentJwk":{"type":"object","properties":{"kty":{"type":"string","enum":["EC"]},"crv":{"type":"string","enum":["P-256"]},"x":{"type":"string","minLength":1},"y":{"type":"string","minLength":1}},"required":["kty","crv","x","y"],"additionalProperties":{"nullable":true}},"MigrationJob":{"type":"object","properties":{"id":{"type":"string"},"sourcePlatform":{"type":"string","enum":["prestashop16","prestashop17","prestashop8","woocommerce","shopify"],"description":"Source e-commerce platform of the import"},"status":{"type":"string","enum":["created","uploading","parsing","importing","dry_run_ready","promoting","promoted","discarding","discarded","failed"]},"tablePrefix":{"type":"string","nullable":true},"sourceFiles":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"kind":{"type":"string","enum":["dump","products","customers","orders"]},"name":{"type":"string"},"size":{"type":"integer","minimum":0}},"required":["key","kind","name","size"]}},"candidateDbName":{"type":"string","nullable":true},"candidateDbUrl":{"type":"string","nullable":true},"previousDbUrl":{"type":"string","nullable":true},"report":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"error":{"type":"string","nullable":true},"progress":{"type":"object","nullable":true,"properties":{"entity":{"type":"string"},"index":{"type":"integer","minimum":0}},"required":["entity","index"]},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","sourcePlatform","status","tablePrefix","sourceFiles","candidateDbName","candidateDbUrl","previousDbUrl","report","error","progress","createdAt","updatedAt"]},"CreateMigrationJobBody":{"type":"object","properties":{"sourcePlatform":{"type":"string","enum":["prestashop16","prestashop17","prestashop8","woocommerce","shopify"],"description":"Source e-commerce platform of the import"},"tablePrefix":{"type":"string","pattern":"^[A-Za-z0-9_]{0,20}$"}},"required":["sourcePlatform"]}},"parameters":{}},"paths":{"/health":{"get":{"tags":["Health"],"summary":"Service health check","description":"Returns overall service health including database, KV, R2, and queues. Status \"healthy\" when all critical dependencies are up; \"degraded\" otherwise. Returns HTTP 503 if the platform database is unreachable.","responses":{"200":{"description":"Service is healthy (or degraded but DB is reachable)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"503":{"description":"Platform database is unreachable — service is degraded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/v1/ready":{"get":{"tags":["Health"],"summary":"Readiness probe","description":"K8s readiness probe. Verifies critical dependencies (DB SELECT 1 with 500ms timeout, KV, R2). Returns 503 if a critical dependency is down.","responses":{"200":{"description":"Service is ready to accept traffic","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadinessResponse"}}}},"503":{"description":"A critical dependency is down","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadinessResponse"}}}}}}},"/v1/auth/register":{"post":{"tags":["Auth"],"summary":"Register a new user","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":255,"format":"email","example":"user@example.com"},"password":{"type":"string","minLength":8,"maxLength":128,"example":"secureP@ss1"},"name":{"type":"string","minLength":1,"maxLength":255,"example":"Jane Doe"},"tosVersion":{"type":"string","maxLength":32,"example":"1.0","description":"Version of the platform Terms of Service being accepted (must match the current version from GET /v1/legal/platform-docs/tos)"}},"required":["email","password","name"]}}}},"responses":{"201":{"description":"User registered — please verify your email","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"If a user with this email exists, a password reset link has been sent."}},"required":["message"]}}}},"400":{"description":"Terms of Service not accepted (missing or outdated tosVersion)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Email already registered","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/auth/login":{"post":{"tags":["Auth"],"summary":"Log in with email and password","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":255,"format":"email","example":"user@example.com"},"password":{"type":"string","minLength":1,"maxLength":128,"example":"secureP@ss1"}},"required":["email","password"]}}}},"responses":{"200":{"description":"Login successful or MFA required","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","example":"usr_01abc"},"email":{"type":"string","example":"user@example.com"},"name":{"type":"string","nullable":true,"example":"Jane Doe"},"role":{"type":"string","example":"member"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","email","name","role","createdAt"]},"tokens":{"type":"object","properties":{"accessToken":{"type":"string","example":"eyJhbGciOi..."},"refreshToken":{"type":"string","example":"eyJhbGciOi..."},"expiresIn":{"type":"integer","example":900}},"required":["accessToken","refreshToken","expiresIn"]}},"required":["user","tokens"]},{"type":"object","properties":{"mfa_required":{"type":"boolean","enum":[true]},"challenge_id":{"type":"string"}},"required":["mfa_required","challenge_id"]}]}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Email not verified","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"429":{"description":"Account temporarily locked","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/auth/forgot-password":{"post":{"tags":["Auth"],"summary":"Request a password reset email","description":"Sends a password reset email if the user exists. Always returns 200 to prevent email enumeration.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":255,"format":"email","example":"user@example.com"}},"required":["email"]}}}},"responses":{"200":{"description":"Password reset email sent (if user exists)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"If a user with this email exists, a password reset link has been sent."}},"required":["message"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/auth/reset-password":{"post":{"tags":["Auth"],"summary":"Reset password using a reset token","description":"Accepts a valid reset token and new password. Updates the password and invalidates the token.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","minLength":1,"example":"abc123def456..."},"password":{"type":"string","minLength":8,"maxLength":128,"example":"newSecureP@ss1"}},"required":["token","password"]}}}},"responses":{"200":{"description":"Password reset successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"If a user with this email exists, a password reset link has been sent."}},"required":["message"]}}}},"400":{"description":"Invalid or expired reset token","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/auth/my-tenants":{"get":{"tags":["Auth"],"summary":"List tenants for authenticated user","description":"Returns all tenants the authenticated user belongs to, including their role in each.","security":[{"Bearer":[]}],"responses":{"200":{"description":"List of tenants the user belongs to","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"tnt_abc123"},"name":{"type":"string","example":"My Store"},"slug":{"type":"string","example":"my-store"},"plan":{"type":"string","enum":["free","starter","pro","enterprise"],"example":"starter"},"status":{"type":"string","enum":["active","suspended","cancelled"],"example":"active"},"role":{"type":"string","enum":["owner","admin","member"],"example":"owner"}},"required":["id","name","slug","plan","status","role"]}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/auth/logout":{"post":{"tags":["Auth"],"summary":"Log out by revoking the refresh token","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"refreshToken":{"type":"string","minLength":1,"example":"eyJhbGciOi..."}},"required":["refreshToken"]}}}},"responses":{"204":{"description":"Logout successful, token revoked"},"401":{"description":"Token not found or already revoked","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/auth/refresh":{"post":{"tags":["Auth"],"summary":"Refresh access token","description":"Exchanges a valid refresh token for a new access token. Applies token rotation — the old refresh token is revoked and a new one is issued.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"refreshToken":{"type":"string","minLength":1,"example":"eyJhbGciOi..."}},"required":["refreshToken"]}}}},"responses":{"200":{"description":"Tokens refreshed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"tokens":{"type":"object","properties":{"accessToken":{"type":"string","example":"eyJhbGciOi..."},"refreshToken":{"type":"string","example":"eyJhbGciOi..."},"expiresIn":{"type":"integer","example":900}},"required":["accessToken","refreshToken","expiresIn"]}},"required":["tokens"]}}}},"401":{"description":"Invalid, expired, or revoked refresh token","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/auth/session":{"post":{"tags":["Auth"],"summary":"Create authenticated session (httpOnly cookies)","description":"Validates credentials and sets __Host-access_token and __Secure-refresh_token httpOnly cookies. Returns user payload only — tokens are never exposed to client JS.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":255,"format":"email","example":"user@example.com"},"password":{"type":"string","minLength":1,"maxLength":128,"example":"secureP@ss1"}},"required":["email","password"]}}}},"responses":{"200":{"description":"Session created (cookies set) or MFA required","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"name":{"type":"string","nullable":true},"role":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","email","name","role","createdAt"]}},"required":["user"]},{"type":"object","properties":{"mfa_required":{"type":"boolean","enum":[true]},"challenge_id":{"type":"string"}},"required":["mfa_required","challenge_id"]}]}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Email not verified","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"429":{"description":"Account temporarily locked","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Auth"],"summary":"Destroy session (clear cookies, revoke refresh token)","description":"Reads the refresh cookie, marks it revoked in the DB, and clears both access and refresh cookies. Idempotent — safe to call without a session.","responses":{"204":{"description":"Session destroyed"},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/auth/session/refresh":{"post":{"tags":["Auth"],"summary":"Rotate session via refresh cookie","description":"Reads the refresh cookie, validates + rotates it, and refreshes both access and refresh cookies. Returns the user payload. No tokens are exposed to client JS.","responses":{"200":{"description":"Session refreshed (cookies rotated)","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"name":{"type":"string","nullable":true},"role":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","email","name","role","createdAt"]}},"required":["user"]}}}},"401":{"description":"Missing, invalid, expired, or revoked refresh cookie","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/auth/select-tenant":{"post":{"tags":["Auth"],"summary":"Select a tenant and receive a tenant-scoped JWT","description":"Allows an authenticated user to select an active tenant they belong to and receive a new JWT scoped to that tenant.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tenantId":{"type":"string","minLength":1,"example":"tnt_abc123"}},"required":["tenantId"]}}}},"responses":{"200":{"description":"Tenant selected, tenant-scoped token issued","content":{"application/json":{"schema":{"type":"object","properties":{"accessToken":{"type":"string","example":"eyJhbGciOi..."},"expiresIn":{"type":"integer","example":900},"tenant":{"type":"object","properties":{"id":{"type":"string","example":"tnt_abc123"},"name":{"type":"string","example":"My Store"},"slug":{"type":"string","example":"my-store"},"role":{"type":"string","example":"owner"}},"required":["id","name","slug","role"]}},"required":["accessToken","expiresIn","tenant"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"User is not a member of the requested tenant","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/auth/switch-tenant":{"post":{"tags":["Auth"],"summary":"Switch to a different tenant","description":"Switches the active tenant for an authenticated user and issues a new tenant-scoped JWT that supersedes the previous one.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tenantId":{"type":"string","minLength":1,"example":"tnt_abc123"}},"required":["tenantId"]}}}},"responses":{"200":{"description":"Tenant switched, new tenant-scoped token issued","content":{"application/json":{"schema":{"type":"object","properties":{"accessToken":{"type":"string","example":"eyJhbGciOi..."},"expiresIn":{"type":"integer","example":900},"tenant":{"type":"object","properties":{"id":{"type":"string","example":"tnt_abc123"},"name":{"type":"string","example":"My Store"},"slug":{"type":"string","example":"my-store"},"role":{"type":"string","example":"owner"}},"required":["id","name","slug","role"]}},"required":["accessToken","expiresIn","tenant"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"User is not a member of the target tenant or tenant is inactive","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/auth/verify-email":{"post":{"tags":["Auth"],"summary":"Verify email address with token","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","minLength":1,"example":"abc123def456..."}},"required":["token"]}}}},"responses":{"200":{"description":"Email verified successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Email verified successfully"},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"emailVerified":{"type":"boolean"}},"required":["id","email","emailVerified"]}},"required":["message","user"]}}}},"400":{"description":"Invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/auth/resend-verification":{"post":{"tags":["Auth"],"summary":"Resend email verification token","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":255,"format":"email","example":"user@example.com"}},"required":["email"]}}}},"responses":{"200":{"description":"Verification email sent (if account exists)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"If a user with this email exists, a password reset link has been sent."}},"required":["message"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/cross-sell":{"get":{"tags":["Catalog"],"summary":"Cross-sell recommendations for a set of cart products","description":"Blends merchant-curated bundles, behavioral co-occurrence (SPINE-B), category adjacency, trending, and a cold-start floor. No authentication required.","parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01,prod_02","description":"Comma-separated seed product ids (cart contents)"},"required":true,"description":"Comma-separated seed product ids (cart contents)","name":"product_ids","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":12,"default":6,"example":3},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Cross-sell products","content":{"application/json":{"schema":{"type":"object","properties":{"products":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"price":{"type":"integer","description":"Unit price in cents"},"image":{"type":"string","nullable":true},"variantId":{"type":"string","nullable":true},"reason":{"type":"string","enum":["bundle","purchased_together","same_category","trending","popular"],"description":"Why this product was recommended"}},"required":["productId","name","slug","price","image","variantId","reason"]}}},"required":["products"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/by-ids":{"get":{"tags":["Catalog"],"summary":"Hydrate an explicit, ordered set of product ids into cards","description":"Returns product cards for the given ids in request order (archived/deleted dropped). No authentication required.","parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01,prod_02","description":"Comma-separated product ids, in display order"},"required":true,"description":"Comma-separated product ids, in display order","name":"ids","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":48,"default":24},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Product cards","content":{"application/json":{"schema":{"type":"object","properties":{"products":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"price":{"type":"integer","description":"Unit price in cents"},"image":{"type":"string","nullable":true},"variantId":{"type":"string","nullable":true},"inStock":{"type":"boolean"}},"required":["productId","name","slug","price","image","variantId","inStock"]}}},"required":["products"]}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/assistant":{"post":{"tags":["Catalog","AI"],"summary":"Grounded shopping assistant (0 SKU hallucination)","description":"Answers a shopper question grounded ONLY in real catalog products retrieved via search. Public + tenant-resolved.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","minLength":1,"maxLength":1000}},"required":["message"]}}}},"responses":{"200":{"description":"Grounded answer + the real products it references","content":{"application/json":{"schema":{"type":"object","properties":{"answer":{"type":"string"},"products":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"price":{"type":"integer"},"image":{"type":"string","nullable":true},"inStock":{"type":"boolean"}},"required":["id","name","slug","price","image","inStock"]}},"blockedHallucinations":{"type":"integer"},"retrievedCount":{"type":"integer"}},"required":["answer","products","blockedHallucinations","retrievedCount"]}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"503":{"description":"Assistant unavailable (not configured)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/social-proof":{"get":{"tags":["Catalog"],"summary":"Honest social-proof signals for a set of products","description":"Real purchase counts (paid orders in a rolling window), live stock and a low-stock flag. No fabricated or randomised values. No authentication required.","parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01,prod_02","description":"Comma-separated product ids"},"required":true,"description":"Comma-separated product ids","name":"product_ids","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":365,"default":90,"example":90},"required":false,"name":"window_days","in":"query"}],"responses":{"200":{"description":"Social-proof signals","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string"},"purchasedOrders":{"type":"integer"},"purchasedUnits":{"type":"integer"},"stock":{"type":"integer"},"lowStock":{"type":"boolean"}},"required":["productId","purchasedOrders","purchasedUnits","stock","lowStock"]}},"windowDays":{"type":"integer"}},"required":["items","windowDays"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{id}/presence":{"post":{"tags":["Catalog"],"summary":"Heartbeat a product view and read the live viewer count","description":"Registers the anonymous session as currently viewing the product and returns the real count of concurrent viewers. No authentication required.","parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Live viewer count","content":{"application/json":{"schema":{"type":"object","properties":{"viewersNow":{"type":"integer"}},"required":["viewersNow"]}}}}}}},"/v1/products/for-you":{"get":{"tags":["Catalog"],"summary":"Personalized \"for you\" products + visitor segment","description":"Recommendations from the visitor's own behavioural history (SPINE-B), with a coarse segment for edge caching. Falls back to newest-in-stock for cold visitors. No authentication required.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":24,"default":8,"example":8},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Personalized products + segment","content":{"application/json":{"schema":{"type":"object","properties":{"segment":{"type":"string","enum":["new","browser","researcher","intent","returning"]},"personalized":{"type":"boolean"},"products":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"price":{"type":"integer"},"image":{"type":"string","nullable":true},"variantId":{"type":"string","nullable":true}},"required":["productId","name","slug","price","image","variantId"]}}},"required":["segment","personalized","products"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/search/autocomplete":{"get":{"tags":["Catalog"],"summary":"Autocomplete product names","description":"Returns product name suggestions for a partial query. Optimized for speed with Orama prefix search and SQL LIKE fallback.","parameters":[{"schema":{"type":"string","minLength":1,"example":"cot","description":"Partial search query for autocomplete"},"required":true,"description":"Partial search query for autocomplete","name":"q","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":20,"default":10,"example":10,"description":"Maximum suggestions to return (1-20)"},"required":false,"description":"Maximum suggestions to return (1-20)","name":"limit","in":"query"}],"responses":{"200":{"description":"Autocomplete suggestions","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"Cotton T-Shirt"},"slug":{"type":"string","example":"cotton-t-shirt"},"price":{"type":"integer","example":2999,"description":"Price in cents"},"image":{"type":"object","nullable":true,"properties":{"url":{"type":"string"},"alt":{"type":"string","nullable":true}},"required":["url","alt"],"description":"Product thumbnail"},"category":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"}},"required":["name","slug"],"description":"First/primary category of the product."},"rating":{"type":"number","minimum":0,"maximum":5,"example":4.5,"description":"Avg rating, 0..5. Placeholder until product_reviews lands (A9)."},"reviewCount":{"type":"integer","minimum":0,"example":0,"description":"Approved review count. Placeholder until product_reviews lands (A9)."}},"required":["id","name","slug","price","image"]}}},"required":["data"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/search":{"get":{"tags":["Catalog"],"summary":"Search products","description":"Full-text search across the product catalog with faceted filtering. Uses Orama for ranked results with automatic SQL fallback.","parameters":[{"schema":{"type":"string","minLength":1,"example":"shirt","description":"Search query"},"required":true,"description":"Search query","name":"q","in":"query"},{"schema":{"type":"string","example":"cat_01","description":"Filter by category ID"},"required":false,"description":"Filter by category ID","name":"category","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"example":1000,"description":"Minimum price in cents"},"required":false,"description":"Minimum price in cents","name":"minPrice","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"example":5000,"description":"Maximum price in cents"},"required":false,"description":"Maximum price in cents","name":"maxPrice","in":"query"},{"schema":{"type":"string","enum":["relevance","price-asc","price-desc","newest"],"default":"relevance","example":"relevance","description":"Sort order: relevance, price-asc, price-desc, newest"},"required":false,"description":"Sort order: relevance, price-asc, price-desc, newest","name":"sort","in":"query"},{"schema":{"type":"string","enum":["auto","text","semantic","hybrid"],"default":"auto","example":"auto","description":"Search mode: auto, text, semantic, hybrid"},"required":false,"description":"Search mode: auto, text, semantic, hybrid","name":"mode","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Search results with facets and pagination","content":{"application/json":{"schema":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"Cotton T-Shirt"},"slug":{"type":"string","example":"cotton-t-shirt"},"content":{"type":"string","nullable":true,"example":"A premium cotton t-shirt"},"price":{"type":"integer","example":2999,"description":"Price in cents"},"compareAtPrice":{"type":"integer","nullable":true,"example":3999},"status":{"type":"string","enum":["active","draft","archived"],"example":"active"},"type":{"type":"string","enum":["simple","configurable","bundle","grouped"],"example":"simple"},"sku":{"type":"string","nullable":true,"example":"TSH-001"},"stock":{"type":"integer","example":50},"score":{"type":"number","example":8.5,"description":"Relevance score"},"category":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"],"description":"Product category"},"image":{"type":"object","nullable":true,"properties":{"url":{"type":"string"},"alt":{"type":"string","nullable":true}},"required":["url","alt"],"description":"Primary product image"}},"required":["id","name","slug","content","price","compareAtPrice","status","type","sku","stock","score","category","image"]}},"facets":{"type":"object","properties":{"categories":{"type":"object","additionalProperties":{"type":"number"},"description":"Category name → count"},"priceRanges":{"type":"object","additionalProperties":{"type":"number"},"description":"Price range → count"}},"required":["categories","priceRanges"]},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["data","facets","pagination"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/search/visual":{"post":{"tags":["Catalog"],"summary":"Visual / image-similarity search","description":"Find products visually similar to a query image. Accepts a multipart `image` upload OR a JSON body `{ imageUrl, limit?, category? }`. Returns ranked products by visual similarity. Requires the Workers AI + Vectorize bindings (staging/prod); degrades to 503 where they are absent (e.g. local dev).","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"image":{"type":"string","format":"binary","description":"Query image (jpeg/png/webp/gif, <= 6 MB)"},"limit":{"type":"string","example":"20","description":"Max results (1..50)"},"category":{"type":"string","example":"cat_01","description":"Filter by category ID"}}}},"application/json":{"schema":{"type":"object","properties":{"imageUrl":{"type":"string","format":"uri","example":"https://cdn.example.com/photo.jpg","description":"Publicly-fetchable image URL"},"limit":{"type":"integer","minimum":1,"maximum":50,"example":20},"category":{"type":"string","example":"cat_01"}}}}}},"responses":{"200":{"description":"Visually-similar products, ranked","content":{"application/json":{"schema":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"Cotton T-Shirt"},"slug":{"type":"string","example":"cotton-t-shirt"},"price":{"type":"integer","example":2999,"description":"Price in cents"},"compareAtPrice":{"type":"integer","nullable":true,"example":3999},"sku":{"type":"string","nullable":true,"example":"TSH-001"},"stock":{"type":"integer","example":50},"inStock":{"type":"boolean","example":true},"similarity":{"type":"number","example":0.87,"description":"Visual cosine similarity (0..1)"},"category":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"],"description":"Product category"},"image":{"type":"object","nullable":true,"properties":{"url":{"type":"string"},"alt":{"type":"string","nullable":true}},"required":["url","alt"],"description":"Primary product image"}},"required":["id","name","slug","price","compareAtPrice","sku","stock","inStock","similarity","category","image"]}},"count":{"type":"integer","example":12}},"required":["data","count"]}}}},"400":{"description":"Bad request (no/invalid image)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"413":{"description":"Image too large","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"503":{"description":"Visual search unavailable (Workers AI / Vectorize binding absent)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/search/nl":{"post":{"tags":["Catalog"],"summary":"Conversational (natural-language) product search","description":"Parses a natural-language query into structured constraints (price, category, attributes, sort) and runs the existing hybrid catalog search. Returns the interpreted constraints + filtered results. Deterministic, rule-based parser — no LLM/AI binding required for the default path.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","minLength":1,"maxLength":500,"example":"a warm waterproof jacket under $100 for hiking","description":"Natural-language shopping query"},"limit":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"page":{"type":"integer","minimum":1,"default":1,"example":1}},"required":["query"]}}}},"responses":{"200":{"description":"Interpreted constraints + filtered search results","content":{"application/json":{"schema":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD"},"interpreted":{"type":"object","properties":{"priceMin":{"type":"integer","nullable":true,"description":"Parsed price floor in cents"},"priceMax":{"type":"integer","nullable":true,"description":"Parsed price ceiling in cents"},"category":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"],"description":"Resolved tenant category (null if the hint matched nothing)"},"categoryHint":{"type":"string","nullable":true,"description":"Raw category name hint from the parser"},"attributes":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["color","size","material","feature"]},"value":{"type":"string"}},"required":["kind","value"]}},"sort":{"type":"string","enum":["relevance","price-asc","price-desc","newest"]},"semanticQuery":{"type":"string","description":"Cleaned query fed to the retriever"},"summary":{"type":"string","example":"Showing waterproof jackets under $100"}},"required":["priceMin","priceMax","category","categoryHint","attributes","sort","semanticQuery","summary"]},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"Cotton T-Shirt"},"slug":{"type":"string","example":"cotton-t-shirt"},"content":{"type":"string","nullable":true,"example":"A premium cotton t-shirt"},"price":{"type":"integer","example":2999,"description":"Price in cents"},"compareAtPrice":{"type":"integer","nullable":true,"example":3999},"status":{"type":"string","enum":["active","draft","archived"],"example":"active"},"type":{"type":"string","enum":["simple","configurable","bundle","grouped"],"example":"simple"},"sku":{"type":"string","nullable":true,"example":"TSH-001"},"stock":{"type":"integer","example":50},"score":{"type":"number","example":8.5,"description":"Relevance score"},"category":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"],"description":"Product category"},"image":{"type":"object","nullable":true,"properties":{"url":{"type":"string"},"alt":{"type":"string","nullable":true}},"required":["url","alt"],"description":"Primary product image"}},"required":["id","name","slug","content","price","compareAtPrice","status","type","sku","stock","score","category","image"]}},"facets":{"type":"object","properties":{"categories":{"type":"object","additionalProperties":{"type":"number"},"description":"Category name → count"},"priceRanges":{"type":"object","additionalProperties":{"type":"number"},"description":"Price range → count"}},"required":["categories","priceRanges"]},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["interpreted","data","facets","pagination"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/resolve/{type}/{slug}":{"get":{"tags":["Catalog"],"summary":"Resolve slug redirect","description":"Looks up if a slug has been changed and returns the new slug for 301 redirects.","parameters":[{"schema":{"type":"string","minLength":1,"example":"product","description":"Resource type (product, category, page)"},"required":true,"description":"Resource type (product, category, page)","name":"type","in":"path"},{"schema":{"type":"string","minLength":1,"example":"old-product-slug"},"required":true,"name":"slug","in":"path"}],"responses":{"200":{"description":"Redirect found","content":{"application/json":{"schema":{"type":"object","properties":{"redirect":{"type":"boolean","example":true},"newSlug":{"type":"string","example":"updated-product-slug"},"resourceType":{"type":"string","example":"product"}},"required":["redirect","newSlug","resourceType"]}}}},"404":{"description":"No redirect found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/recommendations/{productId}":{"get":{"tags":["Catalog"],"summary":"Get similar product recommendations","description":"Finds similar products using vector similarity search. Requires Workers AI and Vectorize bindings.","parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"productId","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":20,"default":6,"example":6},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Similar products","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"price":{"type":"integer"},"compareAtPrice":{"type":"integer","nullable":true},"score":{"type":"number","description":"Cosine similarity score"},"category":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"image":{"type":"object","nullable":true,"properties":{"url":{"type":"string"},"alt":{"type":"string","nullable":true}},"required":["url","alt"]}},"required":["id","name","slug","price","compareAtPrice","score","category","image"]}},"productId":{"type":"string"}},"required":["data","productId"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"503":{"description":"AI/Vectorize not available","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/search/reindex":{"post":{"tags":["Catalog"],"summary":"Trigger catalog reindex","description":"Rebuilds the Orama search index for all active products and persists the snapshot to KV storage.","security":[{"bearerAuth":[]}],"responses":{"202":{"description":"Reindex job accepted and completed","content":{"application/json":{"schema":{"type":"object","properties":{"jobId":{"type":"string","example":"job_a1b2c3d4e5f6","description":"Job ID for status polling"},"status":{"type":"string","enum":["completed","pending","failed"],"example":"completed"},"documentCount":{"type":"integer","example":42,"description":"Number of documents indexed"},"timestamp":{"type":"string","example":"2026-04-02T12:00:00.000Z","description":"When the reindex was performed"}},"required":["jobId","status","documentCount","timestamp"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden — admin role required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/search/status":{"get":{"tags":["Catalog"],"summary":"Get search index status","description":"Returns the current state of the search index including last indexed timestamp, document count, and job status.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Index status","content":{"application/json":{"schema":{"type":"object","properties":{"lastIndexed":{"type":"string","nullable":true,"example":"2026-04-02T12:00:00.000Z","description":"When the index was last rebuilt"},"documentCount":{"type":"integer","example":42,"description":"Number of documents in the index"},"lastJobId":{"type":"string","nullable":true,"example":"job_a1b2c3d4e5f6","description":"ID of the last reindex job"},"status":{"type":"string","enum":["completed","pending","failed","none"],"example":"completed","description":"Current index status"}},"required":["lastIndexed","documentCount","lastJobId","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden — admin role required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/register":{"post":{"tags":["Storefront"],"summary":"Register a new customer account","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":255,"format":"email","example":"customer@example.com"},"password":{"type":"string","minLength":8,"maxLength":128,"example":"secureP@ss1"},"firstName":{"type":"string","minLength":1,"maxLength":255,"example":"Jane"},"lastName":{"type":"string","minLength":1,"maxLength":255,"example":"Doe"}},"required":["email","password"]}}}},"responses":{"201":{"description":"Customer registered — email verification required","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Operation completed successfully"}},"required":["message"]}}}},"409":{"description":"Email already registered","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/login":{"post":{"tags":["Storefront"],"summary":"Customer login","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":255,"format":"email","example":"customer@example.com"},"password":{"type":"string","minLength":1,"maxLength":128,"example":"secureP@ss1"}},"required":["email","password"]}}}},"responses":{"200":{"description":"Login successful","content":{"application/json":{"schema":{"type":"object","properties":{"customer":{"type":"object","properties":{"id":{"type":"string","example":"cst_01abc"},"email":{"type":"string","example":"customer@example.com"},"firstName":{"type":"string","nullable":true,"example":"Jane"},"lastName":{"type":"string","nullable":true,"example":"Doe"},"phone":{"type":"string","nullable":true,"example":"+1234567890"},"acceptsMarketing":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","email","firstName","lastName","phone","acceptsMarketing","createdAt"]},"accessToken":{"type":"string","example":"eyJhbGciOi..."},"refreshToken":{"type":"string","example":"eyJhbGciOi..."},"expiresIn":{"type":"integer","example":900}},"required":["customer","accessToken","refreshToken","expiresIn"]}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Email not verified","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"429":{"description":"Too many failed login attempts","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"retryAfter":{"type":"number"}},"required":["type","title","status","detail"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/verify-email":{"post":{"tags":["Storefront"],"summary":"Verify customer email address with token","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","minLength":1,"example":"abc123def456..."}},"required":["token"]}}}},"responses":{"200":{"description":"Email verified successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Operation completed successfully"}},"required":["message"]}}}},"400":{"description":"Invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/forgot-password":{"post":{"tags":["Storefront"],"summary":"Request password reset for customer","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":255,"format":"email","example":"customer@example.com"}},"required":["email"]}}}},"responses":{"200":{"description":"Password reset email sent (if account exists)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Operation completed successfully"}},"required":["message"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/reset-password":{"post":{"tags":["Storefront"],"summary":"Reset customer password with token","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","minLength":1,"example":"abc123def456..."},"password":{"type":"string","minLength":8,"maxLength":128,"example":"newSecureP@ss1"}},"required":["token","password"]}}}},"responses":{"200":{"description":"Password reset successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Operation completed successfully"}},"required":["message"]}}}},"400":{"description":"Invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/payments/webhook":{"post":{"tags":["Payments"],"summary":"Stripe webhook handler","description":"Receives and processes Stripe webhook events. Validates signature, updates order status based on event type.","requestBody":{"required":true,"content":{"text/plain":{"schema":{"type":"string"}}}},"responses":{"200":{"description":"Webhook received","content":{"application/json":{"schema":{"type":"object","properties":{"received":{"type":"boolean"}},"required":["received"]}}}},"400":{"description":"Invalid signature or payload","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/payments/paypal/webhook":{"post":{"tags":["Payments","PayPal"],"summary":"PayPal webhook endpoint","description":"Verifies the signature with PayPal then applies side-effects (capture completed/refunded).","requestBody":{"required":true,"content":{"application/json":{"schema":{"nullable":true}}}},"responses":{"200":{"description":"Acknowledged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalWebhookAck"}}}},"400":{"description":"Invalid signature or payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}},"422":{"description":"Credentials not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}}}}},"/v1/payments/redsys/webhook":{"post":{"tags":["Payments","Redsys"],"summary":"Redsys SIS notification webhook","description":"Verifies Ds_Signature by recomputation (fail closed), confirms the checkout idempotently when Ds_Response is 0000–0099, and acknowledges declines.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/RedsysWebhookForm"}}}},"responses":{"200":{"description":"Notification processed (or idempotent duplicate)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsWebhookAck"}}}},"400":{"description":"Malformed notification","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"403":{"description":"Invalid signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"422":{"description":"Redsys not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}}}}},"/v1/payments/sequra/webhook":{"post":{"tags":["Payments","SeQura"],"summary":"SeQura IPN webhook","description":"Verifies the IPN HMAC signature (fail closed) and confirms the order idempotently when sq_state=approved.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/SequraWebhookForm"}}}},"responses":{"200":{"description":"IPN processed (or idempotent duplicate)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsWebhookAck"}}}},"403":{"description":"Invalid signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"422":{"description":"SeQura not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}}}}},"/v1/status":{"get":{"tags":["Health"],"summary":"Status page snapshot","description":"Returns the latest status snapshot for all platform components. Reads a pre-computed snapshot from KV — never runs probes inline. Refreshed every 5 minutes by a cron job.","responses":{"200":{"description":"Status snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSnapshot"}}}},"503":{"description":"No snapshot available yet (cron has not run, or KV unbound)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusError"}}}}}}},"/v1/storefront/search/trending":{"get":{"tags":["Catalog","Storefront"],"summary":"Trending search queries","description":"Returns the most-used search queries for this tenant, ordered by count then recency. Public endpoint, no auth required. A1.5 cross-team request.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":50,"example":10,"description":"Maximum number of trending terms to return (default 10)."},"required":false,"description":"Maximum number of trending terms to return (default 10).","name":"limit","in":"query"}],"responses":{"200":{"description":"List of trending search terms","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrendingSearchResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/unsubscribe":{"get":{"tags":["Marketing Campaigns"],"summary":"One-click unsubscribe via signed token (public)","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"token","in":"query"}],"responses":{"200":{"description":"Unsubscribed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"400":{"description":"Invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/exchange-rates":{"get":{"tags":["Currency"],"summary":"List exchange rates","description":"Returns exchange rates from the platform DB. Cached max-age=3600. No auth required.","parameters":[{"schema":{"type":"string","minLength":3,"maxLength":3,"default":"USD","example":"USD"},"required":false,"name":"base","in":"query"},{"schema":{"type":"string","example":"EUR,GBP,JPY","description":"Comma-separated target currencies. Omit for all."},"required":false,"description":"Comma-separated target currencies. Omit for all.","name":"targets","in":"query"}],"responses":{"200":{"description":"Exchange rates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExchangeRatesResponse"}}}},"404":{"description":"No rates found for the requested base currency","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/exchange-rates/convert":{"post":{"tags":["Currency"],"summary":"Convert amount between currencies","description":"Converts a monetary amount (in cents) using cached exchange rates.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertRequest"}}}},"responses":{"200":{"description":"Converted amount","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertResponse"}}}},"404":{"description":"Rate not found for the currency pair","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/exchange-rates/refresh":{"post":{"tags":["Currency"],"summary":"Force refresh exchange rates","description":"Admin-only endpoint to trigger an immediate rates refresh without waiting for the cron.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Refresh summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/legal/platform-docs":{"get":{"tags":["Legal"],"summary":"List platform legal documents","description":"Public list of the current platform legal documents (Terms of Service, DPA, MSA) with their active version.","responses":{"200":{"description":"Current legal documents","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["tos","dpa","msa"]},"version":{"type":"string","example":"1.0"},"effectiveDate":{"type":"string","example":"2026-06-09"},"title":{"type":"string"}},"required":["type","version","effectiveDate","title"]}}},"required":["data"]}}}}}}},"/v1/legal/platform-docs/{type}":{"get":{"tags":["Legal"],"summary":"Get a platform legal document","description":"Public full content + version of a platform legal document (tos | dpa | msa).","parameters":[{"schema":{"type":"string","example":"tos"},"required":true,"name":"type","in":"path"}],"responses":{"200":{"description":"Legal document","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["tos","dpa","msa"]},"version":{"type":"string","example":"1.0"},"effectiveDate":{"type":"string","example":"2026-06-09"},"title":{"type":"string"},"content":{"type":"string","description":"Full markdown body of the document"}},"required":["type","version","effectiveDate","title","content"]}}}},"404":{"description":"Unknown document type","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/platform/tenants":{"get":{"tags":["Platform"],"summary":"List all tenants (super-admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"1","description":"Page number (default: 1)"},"required":false,"description":"Page number (default: 1)","name":"page","in":"query"},{"schema":{"type":"string","example":"25","description":"Items per page (max 100)"},"required":false,"description":"Items per page (max 100)","name":"limit","in":"query"},{"schema":{"type":"string","example":"-createdAt","description":"Sort field. Prefix - for desc. Fields: name, plan, status, createdAt, updatedAt"},"required":false,"description":"Sort field. Prefix - for desc. Fields: name, plan, status, createdAt, updatedAt","name":"sort","in":"query"},{"schema":{"type":"string","example":"id,name,slug,plan","description":"Fields to return (csv)"},"required":false,"description":"Fields to return (csv)","name":"fields","in":"query"},{"schema":{"type":"string","description":"Full-text search in: name, slug"},"required":false,"description":"Full-text search in: name, slug","name":"search","in":"query"}],"responses":{"200":{"description":"Paginated list of all tenants","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"plan":{"type":"string"},"status":{"type":"string"},"customDomain":{"type":"string","nullable":true},"stripeAccountId":{"type":"string","nullable":true},"stripeConnectStatus":{"type":"string"},"trialEndsAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","slug","plan","status","customDomain","stripeAccountId","stripeConnectStatus","trialEndsAt","createdAt","updatedAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/platform/tenants/{id}":{"get":{"tags":["Platform"],"summary":"Get tenant details (super-admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Full tenant detail with usage counts","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"plan":{"type":"string"},"status":{"type":"string"},"customDomain":{"type":"string","nullable":true},"stripeAccountId":{"type":"string","nullable":true},"stripeConnectStatus":{"type":"string"},"trialEndsAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"dbUrl":{"type":"string","nullable":true},"usageCounts":{"type":"object","properties":{"users":{"type":"number"},"subscriptions":{"type":"number"}},"required":["users","subscriptions"]}},"required":["id","name","slug","plan","status","customDomain","stripeAccountId","stripeConnectStatus","trialEndsAt","createdAt","updatedAt","dbUrl","usageCounts"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Platform"],"summary":"Delete a tenant (super-admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Tenant deleted","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/platform/tenants/{id}/suspend":{"post":{"tags":["Platform"],"summary":"Suspend a tenant (super-admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Tenant suspended","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"plan":{"type":"string"},"status":{"type":"string"},"customDomain":{"type":"string","nullable":true},"stripeAccountId":{"type":"string","nullable":true},"stripeConnectStatus":{"type":"string"},"trialEndsAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","slug","plan","status","customDomain","stripeAccountId","stripeConnectStatus","trialEndsAt","createdAt","updatedAt"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Tenant already suspended","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/platform/tenants/{id}/restore":{"post":{"tags":["Platform"],"summary":"Restore a suspended tenant (super-admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Tenant restored","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"plan":{"type":"string"},"status":{"type":"string"},"customDomain":{"type":"string","nullable":true},"stripeAccountId":{"type":"string","nullable":true},"stripeConnectStatus":{"type":"string"},"trialEndsAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","slug","plan","status","customDomain","stripeAccountId","stripeConnectStatus","trialEndsAt","createdAt","updatedAt"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Tenant is not suspended","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/platform/tenants/{id}/impersonate":{"post":{"tags":["Platform"],"summary":"Impersonate tenant owner (super-admin, debugging)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Impersonation JWT issued","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"tenantId":{"type":"string"},"tenantName":{"type":"string"},"expiresIn":{"type":"number"}},"required":["token","tenantId","tenantName","expiresIn"]}}}},"404":{"description":"Tenant not found or has no owner","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/platform/tenants/{id}/usage":{"get":{"tags":["Platform"],"summary":"Get tenant usage analytics (super-admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Tenant usage statistics","content":{"application/json":{"schema":{"type":"object","properties":{"tenantId":{"type":"string"},"tenantName":{"type":"string"},"usage":{"type":"object","properties":{"users":{"type":"object","properties":{"current":{"type":"number"}},"required":["current"]},"subscriptions":{"type":"object","properties":{"current":{"type":"number"}},"required":["current"]},"provisioningLogs":{"type":"object","properties":{"total":{"type":"number"}},"required":["total"]}},"required":["users","subscriptions","provisioningLogs"]}},"required":["tenantId","tenantName","usage"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/platform/migrate-fleet":{"post":{"tags":["Platform"],"summary":"Run versioned migrations across the active-tenant fleet (super-admin)","description":"Pages active tenants and runs the versioned migrator idempotently against each tenant DB. Re-running on an up-to-date tenant is a no-op (reported as already-current).","security":[{"bearerAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"pageSize":{"type":"integer","minimum":1,"maximum":500,"example":50}}}}}},"responses":{"200":{"description":"Per-tenant migration summary","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"integer","example":12},"migrated":{"type":"integer","example":3},"alreadyCurrent":{"type":"integer","example":9},"failed":{"type":"integer","example":0},"results":{"type":"array","items":{"type":"object","properties":{"tenantId":{"type":"string"},"slug":{"type":"string"},"outcome":{"type":"string","enum":["migrated","already-current","failed"]},"applied":{"type":"array","items":{"type":"integer"}},"current":{"type":"integer"},"error":{"type":"string"}},"required":["tenantId","slug","outcome","applied"]}}},"required":["total","migrated","alreadyCurrent","failed","results"]}}}},"500":{"description":"Fleet migration failed to start","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/platform/stats":{"get":{"tags":["Platform"],"summary":"Platform statistics (super-admin)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Platform stats including MRR, tenant counts, plan distribution","content":{"application/json":{"schema":{"type":"object","properties":{"totalTenants":{"type":"number"},"activeTenants":{"type":"number"},"suspendedTenants":{"type":"number"},"cancelledTenants":{"type":"number"},"totalUsers":{"type":"number"},"mrr":{"type":"number","description":"Σ monthly price (cents) of active subscriptions"},"arr":{"type":"number","description":"Annualised MRR (mrr × 12), cents"},"churnRate":{"type":"number","description":"30-day churn %: cancellations in window / subscriptions live at window start"},"planDistribution":{"type":"object","properties":{"starter":{"type":"number"},"growth":{"type":"number"},"enterprise":{"type":"number"}},"required":["starter","growth","enterprise"]},"recentSignups":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"plan":{"type":"string"},"status":{"type":"string"},"customDomain":{"type":"string","nullable":true},"stripeAccountId":{"type":"string","nullable":true},"stripeConnectStatus":{"type":"string"},"trialEndsAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","slug","plan","status","customDomain","stripeAccountId","stripeConnectStatus","trialEndsAt","createdAt","updatedAt"]}},"expiringTrials":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"plan":{"type":"string"},"status":{"type":"string"},"customDomain":{"type":"string","nullable":true},"stripeAccountId":{"type":"string","nullable":true},"stripeConnectStatus":{"type":"string"},"trialEndsAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","slug","plan","status","customDomain","stripeAccountId","stripeConnectStatus","trialEndsAt","createdAt","updatedAt"]}}},"required":["totalTenants","activeTenants","suspendedTenants","cancelledTenants","totalUsers","mrr","arr","churnRate","planDistribution","recentSignups","expiringTrials"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/platform/health":{"get":{"tags":["Platform"],"summary":"Platform health check (super-admin)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Platform subsystem health","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded","critical"]},"subsystems":{"type":"object","properties":{"platformDb":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]},"latencyMs":{"type":"number"}},"required":["status"]},"kv":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]}},"required":["status"]},"r2":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]}},"required":["status"]},"queues":{"type":"object","properties":{"provisioning":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]}},"required":["status"]},"email":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]}},"required":["status"]},"webhooks":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]}},"required":["status"]}},"required":["provisioning","email","webhooks"]},"stripe":{"type":"object","properties":{"status":{"type":"string","enum":["up","down","unknown"]}},"required":["status"]}},"required":["platformDb","kv","r2","queues","stripe"]}},"required":["status","subsystems"]}}}},"503":{"description":"Platform is degraded or critical","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded","critical"]},"subsystems":{"type":"object","properties":{"platformDb":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]},"latencyMs":{"type":"number"}},"required":["status"]},"kv":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]}},"required":["status"]},"r2":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]}},"required":["status"]},"queues":{"type":"object","properties":{"provisioning":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]}},"required":["status"]},"email":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]}},"required":["status"]},"webhooks":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]}},"required":["status"]}},"required":["provisioning","email","webhooks"]},"stripe":{"type":"object","properties":{"status":{"type":"string","enum":["up","down","unknown"]}},"required":["status"]}},"required":["platformDb","kv","r2","queues","stripe"]}},"required":["status","subsystems"]}}}}}}},"/v1/platform/metrics":{"get":{"tags":["Platform"],"summary":"Platform metrics (super-admin)","description":"Returns operational metrics including request counts, latency percentiles, tenant counts, DB health, and cache stats.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Platform operational metrics","content":{"application/json":{"schema":{"type":"object","properties":{"uptime_seconds":{"type":"number"},"requests":{"type":"object","properties":{"total":{"type":"number"},"by_status":{"type":"object","additionalProperties":{"type":"number"}}},"required":["total","by_status"]},"latency":{"type":"object","properties":{"p50_ms":{"type":"number"},"p95_ms":{"type":"number"},"p99_ms":{"type":"number"}},"required":["p50_ms","p95_ms","p99_ms"]},"tenants":{"type":"object","properties":{"total":{"type":"number"},"active":{"type":"number"},"trialing":{"type":"number"},"suspended":{"type":"number"}},"required":["total","active","trialing","suspended"]},"database":{"type":"object","properties":{"status":{"type":"string","enum":["up","down"]},"latency_ms":{"type":"number"}},"required":["status","latency_ms"]},"cache":{"type":"object","properties":{"hit_ratio":{"type":"number"}},"required":["hit_ratio"]},"queues":{"type":"object","properties":{"provisioning":{"type":"object","properties":{"status":{"type":"string"}},"required":["status"]},"email":{"type":"object","properties":{"status":{"type":"string"}},"required":["status"]},"webhook":{"type":"object","properties":{"status":{"type":"string"}},"required":["status"]}},"required":["provisioning","email","webhook"]}},"required":["uptime_seconds","requests","latency","tenants","database","cache","queues"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/platform/performance":{"get":{"tags":["Platform"],"summary":"Platform performance metrics vs PRD budgets","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Current performance metrics","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":{"type":"object","properties":{"current":{"type":"number"},"budget":{"type":"number"},"status":{"type":"string","enum":["ok","warning","critical"]}},"required":["current","budget","status"]}},"timestamp":{"type":"string"}},"required":["data","timestamp"]}}}}}}},"/v1/platform/users":{"get":{"tags":["Platform"],"summary":"List all users (super-admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"1","description":"Page number (default: 1)"},"required":false,"description":"Page number (default: 1)","name":"page","in":"query"},{"schema":{"type":"string","example":"25","description":"Items per page (max 100)"},"required":false,"description":"Items per page (max 100)","name":"limit","in":"query"},{"schema":{"type":"string","example":"-createdAt","description":"Sort field. Prefix - for desc. Fields: email, createdAt, updatedAt"},"required":false,"description":"Sort field. Prefix - for desc. Fields: email, createdAt, updatedAt","name":"sort","in":"query"},{"schema":{"type":"string","example":"id,email,name,role","description":"Fields to return (csv)"},"required":false,"description":"Fields to return (csv)","name":"fields","in":"query"},{"schema":{"type":"string","description":"Full-text search in: email, name"},"required":false,"description":"Full-text search in: email, name","name":"search","in":"query"}],"responses":{"200":{"description":"Paginated list of all platform users","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"name":{"type":"string","nullable":true},"role":{"type":"string"},"emailVerified":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","email","name","role","emailVerified","createdAt","updatedAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/platform/users/{id}":{"get":{"tags":["Platform"],"summary":"Get user details (super-admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"usr_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"User detail with tenant memberships","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"name":{"type":"string","nullable":true},"role":{"type":"string"},"emailVerified":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"tenantMemberships":{"type":"array","items":{"type":"object","properties":{"tenantId":{"type":"string"},"tenantName":{"type":"string"},"role":{"type":"string"}},"required":["tenantId","tenantName","role"]}}},"required":["id","email","name","role","emailVerified","createdAt","updatedAt","tenantMemberships"]}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Platform"],"summary":"Update a user (super-admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"usr_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"role":{"type":"string","enum":["superadmin","admin","member"]}}}}}},"responses":{"200":{"description":"User updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"name":{"type":"string","nullable":true},"role":{"type":"string"},"emailVerified":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","email","name","role","emailVerified","createdAt","updatedAt"]}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tenants":{"get":{"tags":["Tenants"],"summary":"List tenants","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","example":"store"},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","enum":["starter","growth","enterprise"]},"required":false,"name":"plan","in":"query"},{"schema":{"type":"string","enum":["active","suspended","cancelled"]},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"List of tenants","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"tnt_a1b2c3d4e5f6"},"name":{"type":"string","example":"My Store"},"slug":{"type":"string","example":"my-store"},"plan":{"type":"string","example":"free"},"status":{"type":"string","example":"active"},"customDomain":{"type":"string","nullable":true,"example":null},"region":{"type":"string","example":"us-east-1"},"primaryLocation":{"type":"string","nullable":true,"example":"iad"},"replicaLocations":{"type":"array","items":{"type":"string"},"example":["lhr"]},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","slug","plan","status","customDomain","createdAt","updatedAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"403":{"description":"Forbidden — superadmin access required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Tenants"],"summary":"Create a new tenant","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"My Store"},"slug":{"type":"string","minLength":2,"maxLength":63,"pattern":"^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$","example":"my-store"},"plan":{"type":"string","enum":["starter","growth","enterprise"],"default":"starter","example":"starter"},"region":{"type":"string","enum":["us-east-1","eu-west-1","apac-sg-1"],"example":"us-east-1","description":"Legacy/derived region bucket"},"primaryLocation":{"type":"string","pattern":"^[a-z]{2,12}$","example":"iad","description":"Turso primary location code (queried from region-options)"},"replicaLocations":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2,12}$"},"maxItems":20,"example":["lhr","fra"],"description":"Turso replica location codes (multi-zone)"}},"required":["name","slug"]}}}},"responses":{"201":{"description":"Tenant created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"tnt_a1b2c3d4e5f6"},"name":{"type":"string","example":"My Store"},"slug":{"type":"string","example":"my-store"},"plan":{"type":"string","example":"free"},"status":{"type":"string","example":"active"},"customDomain":{"type":"string","nullable":true,"example":null},"region":{"type":"string","example":"us-east-1"},"primaryLocation":{"type":"string","nullable":true,"example":"iad"},"replicaLocations":{"type":"array","items":{"type":"string"},"example":["lhr"]},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","slug","plan","status","customDomain","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Slug already in use","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tenants/region-options":{"get":{"tags":["Tenants"],"summary":"List Turso zones available for tenant DB placement","description":"Returns the live list of Turso locations (queried from the Platform API, KV-cached 24h) so a client can choose a primary + replica zones for its database — never a hardcoded list. Returns `[]` + `configured:false` when the Turso Platform API is not configured (local dev).","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Available zones","content":{"application/json":{"schema":{"type":"object","properties":{"configured":{"type":"boolean","description":"Whether the Turso Platform API is configured (zones can be provisioned). False in local dev."},"locations":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","example":"iad"},"description":{"type":"string","example":"Ashburn, Virginia (US)"}},"required":["code","description"]},"description":"Live list of Turso locations available for primary/replica placement."},"note":{"type":"string"}},"required":["configured","locations"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden — requires owner/admin or superadmin","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tenants/check-slug":{"get":{"tags":["Tenants"],"summary":"Check tenant slug availability","description":"Live availability check for the signup/onboarding flow. Validates the same format rules as POST /tenants (2-63 chars, lowercase alphanumeric + hyphens, no leading/trailing hyphen) and reports whether the slug is free.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"my-store","description":"Tenant slug candidate to check"},"required":true,"description":"Tenant slug candidate to check","name":"slug","in":"query"}],"responses":{"200":{"description":"Availability result","content":{"application/json":{"schema":{"type":"object","properties":{"available":{"type":"boolean","example":true}},"required":["available"]}}}},"400":{"description":"Invalid slug format","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tenants/{id}":{"get":{"tags":["Tenants"],"summary":"Get tenant details","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Tenant details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"tnt_a1b2c3d4e5f6"},"name":{"type":"string","example":"My Store"},"slug":{"type":"string","example":"my-store"},"plan":{"type":"string","example":"free"},"status":{"type":"string","example":"active"},"customDomain":{"type":"string","nullable":true,"example":null},"region":{"type":"string","example":"us-east-1"},"primaryLocation":{"type":"string","nullable":true,"example":"iad"},"replicaLocations":{"type":"array","items":{"type":"string"},"example":["lhr"]},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","slug","plan","status","customDomain","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden — user is not a member of this tenant","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Tenants"],"summary":"Update tenant details","description":"Updates a tenant. Only tenant owners or admins can update.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"My Updated Store","description":"Tenant name"},"slug":{"type":"string","minLength":2,"maxLength":63,"pattern":"^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$","example":"my-updated-store","description":"Tenant slug"},"plan":{"type":"string","enum":["starter","growth","enterprise"],"example":"starter","description":"Subscription plan"},"status":{"type":"string","enum":["active","suspended","cancelled"],"example":"suspended","description":"Tenant status"},"region":{"type":"string","enum":["us-east-1","eu-west-1","apac-sg-1"],"example":"us-east-1","description":"Legacy/derived region bucket"},"primaryLocation":{"type":"string","pattern":"^[a-z]{2,12}$","example":"iad","description":"Turso primary location code (queried from region-options)"},"replicaLocations":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2,12}$"},"maxItems":20,"example":["lhr","fra"],"description":"Turso replica location codes (multi-zone)"}}}}}},"responses":{"200":{"description":"Tenant updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"tnt_a1b2c3d4e5f6"},"name":{"type":"string","example":"My Store"},"slug":{"type":"string","example":"my-store"},"plan":{"type":"string","example":"free"},"status":{"type":"string","example":"active"},"customDomain":{"type":"string","nullable":true,"example":null},"region":{"type":"string","example":"us-east-1"},"primaryLocation":{"type":"string","nullable":true,"example":"iad"},"replicaLocations":{"type":"array","items":{"type":"string"},"example":["lhr"]},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","slug","plan","status","customDomain","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Slug already taken","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tenants/{id}/reprovision-zones":{"post":{"tags":["Tenants"],"summary":"Re-provision a tenant DB into its chosen zone (data-preserving move)","description":"Realizes a zone change for an EXISTING tenant: enqueues a job that forks the tenant DB into the chosen primary location (preserving data) and atomically cuts over db_url/region/group only on success. Turso has no trivial set-primary, so a plain PATCH only records the desired zone — this endpoint applies it. Owner/admin or superadmin only.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"primaryLocation":{"type":"string","pattern":"^[a-z]{2,12}$","example":"fra"},"replicaLocations":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2,12}$"},"maxItems":20,"example":["cdg"]}}}}}},"responses":{"202":{"description":"Re-provision queued","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["queued"]},"tenantId":{"type":"string"},"primaryLocation":{"type":"string","nullable":true},"replicaLocations":{"type":"array","items":{"type":"string"}},"note":{"type":"string"}},"required":["status","tenantId","primaryLocation","replicaLocations","note"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"503":{"description":"Provisioning queue unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tenants/{id}/provisioning":{"get":{"tags":["Tenants"],"summary":"Get tenant provisioning status","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Provisioning status and logs","content":{"application/json":{"schema":{"type":"object","properties":{"tenantId":{"type":"string","example":"tnt_a1b2c3d4e5f6"},"status":{"type":"string","enum":["pending","in_progress","complete","failed"],"example":"in_progress"},"currentStep":{"type":"string","example":"running_migrations"},"message":{"type":"string","nullable":true,"example":"Running database migrations"},"logs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"plog_a1b2c3"},"step":{"type":"string","example":"creating_db"},"status":{"type":"string","enum":["pending","in_progress","complete","failed"],"example":"complete"},"message":{"type":"string","nullable":true,"example":"Database created successfully"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","step","status","message","createdAt"]}}},"required":["tenantId","status","currentStep","message","logs"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"No provisioning record found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tenants/{id}/domain":{"post":{"tags":["Tenants"],"summary":"Configure custom domain","description":"Configures a custom domain for the tenant storefront. Triggers DNS verification and Cloudflare custom hostname creation.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string","minLength":4,"maxLength":253,"pattern":"^(?!-)[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*\\.[A-Za-z]{2,}$","example":"store.example.com"}},"required":["domain"]}}}},"responses":{"200":{"description":"Domain configured, pending verification","content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string","example":"store.example.com"},"status":{"type":"string","enum":["pending","active","failed"],"example":"pending"},"verificationRecord":{"type":"object","properties":{"type":{"type":"string","example":"CNAME"},"name":{"type":"string","example":"store.example.com"},"value":{"type":"string","example":"inai-verify.inaishop.com"}},"required":["type","name","value"]},"instructions":{"type":"string","example":"Add the CNAME record to your DNS provider to verify domain ownership."}},"required":["domain","status","verificationRecord","instructions"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Domain already in use by another tenant","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Invalid domain","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tenants/subscriptions":{"get":{"tags":["Subscriptions"],"summary":"List subscriptions","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","enum":["starter","growth","enterprise"]},"required":false,"name":"plan","in":"query"},{"schema":{"type":"string","enum":["active","past_due","cancelled","trialing"]},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"List of subscriptions","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"tenantName":{"type":"string"},"tenantSlug":{"type":"string"},"plan":{"type":"string"},"status":{"type":"string"},"currentPeriodStart":{"type":"string","nullable":true},"currentPeriodEnd":{"type":"string","nullable":true},"cancelledAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","tenantId","tenantName","tenantSlug","plan","status","currentPeriodStart","currentPeriodEnd","cancelledAt","createdAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"403":{"description":"Forbidden — superadmin access required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tenants/{id}/members":{"get":{"tags":["Tenants"],"summary":"List team members of a tenant","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"List of team members","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"tu_a1b2c3d4e5f6"},"userId":{"type":"string","example":"usr_a1b2c3d4e5f6"},"email":{"type":"string","example":"user@example.com"},"name":{"type":"string","nullable":true,"example":"John Doe"},"role":{"type":"string","example":"admin"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","userId","email","name","role","createdAt"]}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden — user is not a member of this tenant","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Tenants"],"summary":"Invite an existing platform user to the tenant","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"newmember@example.com"},"role":{"type":"string","enum":["admin","editor","viewer"],"example":"viewer"}},"required":["email","role"]}}}},"responses":{"201":{"description":"Member added successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"tu_a1b2c3d4e5f6"},"userId":{"type":"string","example":"usr_a1b2c3d4e5f6"},"email":{"type":"string","example":"newmember@example.com"},"name":{"type":"string","nullable":true,"example":"Jane Doe"},"role":{"type":"string","example":"member"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","userId","email","name","role","createdAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden — only owners and admins can invite members","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"User is already a member of this tenant","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tenants/{id}/members/{memberId}":{"patch":{"tags":["Tenants"],"summary":"Update a team member's role","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"example":"tu_a1b2c3d4e5f6"},"required":true,"name":"memberId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["admin","editor","viewer"],"example":"admin"}},"required":["role"]}}}},"responses":{"200":{"description":"Member role updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"tu_a1b2c3d4e5f6"},"userId":{"type":"string","example":"usr_a1b2c3d4e5f6"},"email":{"type":"string","example":"user@example.com"},"name":{"type":"string","nullable":true,"example":"John Doe"},"role":{"type":"string","example":"admin"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","userId","email","name","role","createdAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden — only owners can change roles","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Member not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Tenants"],"summary":"Remove a team member from the tenant","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"example":"tu_a1b2c3d4e5f6"},"required":true,"name":"memberId","in":"path"}],"responses":{"204":{"description":"Member removed successfully"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden — only owners and admins can remove members","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Member not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tenants/{id}/transfer-ownership":{"post":{"tags":["Tenants"],"summary":"Transfer tenant ownership to another member","description":"Only the current owner can transfer ownership. The old owner becomes an admin.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"tnt_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"newOwnerId":{"type":"string","minLength":1,"example":"usr_a1b2c3d4e5f6"}},"required":["newOwnerId"]}}}},"responses":{"200":{"description":"Ownership transferred","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Ownership transferred successfully"},"previousOwner":{"type":"object","properties":{"userId":{"type":"string"},"newRole":{"type":"string"}},"required":["userId","newRole"]},"newOwner":{"type":"object","properties":{"userId":{"type":"string"},"newRole":{"type":"string"}},"required":["userId","newRole"]}},"required":["message","previousOwner","newOwner"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Only the owner can transfer ownership","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant or member not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/stripe-connect/onboard":{"post":{"tags":["Stripe Connect"],"summary":"Start Stripe Connect onboarding","description":"Creates a Stripe Connect Express account for the tenant and returns the onboarding URL.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"returnUrl":{"type":"string","format":"uri","example":"https://admin.mystore.com/settings/payments"},"refreshUrl":{"type":"string","format":"uri","example":"https://admin.mystore.com/settings/payments/refresh"}},"required":["returnUrl","refreshUrl"]}}}},"responses":{"200":{"description":"Onboarding URL created","content":{"application/json":{"schema":{"type":"object","properties":{"onboardingUrl":{"type":"string","example":"https://connect.stripe.com/setup/s/..."},"accountId":{"type":"string","example":"acct_1234567890"}},"required":["onboardingUrl","accountId"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Connect account already active","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/stripe-connect/return":{"get":{"tags":["Stripe Connect"],"summary":"Handle Stripe Connect onboarding return","description":"Called after the user completes Stripe onboarding. Verifies account status and updates tenant.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Connect status updated","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["active","pending","restricted"],"example":"active"},"chargesEnabled":{"type":"boolean","example":true},"payoutsEnabled":{"type":"boolean","example":true}},"required":["status","chargesEnabled","payoutsEnabled"]}}}},"400":{"description":"No Connect account found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/stripe-connect/refresh":{"get":{"tags":["Stripe Connect"],"summary":"Refresh Stripe Connect onboarding link","description":"Generates a new Account Link if the previous one expired.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uri","example":"https://admin.mystore.com/settings/payments"},"required":true,"name":"returnUrl","in":"query"},{"schema":{"type":"string","format":"uri","example":"https://admin.mystore.com/settings/payments/refresh"},"required":true,"name":"refreshUrl","in":"query"}],"responses":{"200":{"description":"New onboarding link","content":{"application/json":{"schema":{"type":"object","properties":{"onboardingUrl":{"type":"string","example":"https://connect.stripe.com/setup/s/..."}},"required":["onboardingUrl"]}}}},"400":{"description":"No Connect account found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/stripe-connect/status":{"get":{"tags":["Stripe Connect"],"summary":"Get Stripe Connect status","description":"Returns the current Stripe Connect account ID and status for the tenant.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Connect status","content":{"application/json":{"schema":{"type":"object","properties":{"accountId":{"type":"string","nullable":true,"example":"acct_1234567890"},"status":{"type":"string","enum":["not_connected","pending","active","restricted"],"example":"active"}},"required":["accountId","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/stripe-connect/dashboard":{"post":{"tags":["Stripe Connect"],"summary":"Get Stripe Express dashboard login link","description":"Creates a login link to the Stripe Express dashboard for the connected account.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Dashboard login link","content":{"application/json":{"schema":{"type":"object","properties":{"dashboardUrl":{"type":"string","example":"https://connect.stripe.com/express/..."}},"required":["dashboardUrl"]}}}},"400":{"description":"No active Connect account","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/webhook":{"post":{"tags":["Billing"],"summary":"Platform Stripe webhook (SaaS subscriptions)","description":"Receives Stripe events for the PLATFORM SaaS billing of tenants (checkout completion, invoice paid/failed). Signature-verified, no auth. Drives the dunning state machine.","requestBody":{"required":true,"content":{"text/plain":{"schema":{"type":"string"}}}},"responses":{"200":{"description":"Webhook received","content":{"application/json":{"schema":{"type":"object","properties":{"received":{"type":"boolean"}},"required":["received"]}}}},"400":{"description":"Invalid signature or payload","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/plans":{"get":{"tags":["Billing"],"summary":"Public SaaS plan pricing","description":"Live per-plan pricing (amount in cents, currency, interval) for the marketing pricing page. Public — no auth. Amounts are fetched from Stripe and KV-cached for 1h; when Stripe is unreachable or unconfigured the route degrades to `pricesLive: false` with null amounts instead of erroring.","responses":{"200":{"description":"Plan pricing (live from Stripe when available, degraded fallback otherwise — never 500)","content":{"application/json":{"schema":{"type":"object","properties":{"plans":{"type":"array","items":{"type":"object","properties":{"tier":{"type":"string","enum":["starter","growth","enterprise"],"example":"starter"},"amount":{"type":"integer","nullable":true,"example":2900,"description":"Unit amount in cents. Null when live prices are unavailable (pricesLive: false)."},"currency":{"type":"string","example":"eur","description":"ISO 4217 lowercase, as Stripe reports it"},"interval":{"type":"string","enum":["month","year"],"example":"month"}},"required":["tier","amount","currency","interval"]}},"pricesLive":{"type":"boolean","description":"False when amounts could not be resolved live from Stripe (missing key, dev placeholders, Stripe error) — the fallback shape, never a 500."}},"required":["plans","pricesLive"]}}}}}}},"/v1/billing/subscription":{"get":{"tags":["Billing"],"summary":"Get current subscription","description":"Returns the current subscription details for the tenant.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Subscription details. When the tenant has no persisted subscription row (e.g. on a default/non-Stripe plan), a synthesized active subscription derived from the tenant plan is returned with `id: \"default\"`, null Stripe identifiers and a current monthly billing period (now → now+1 month), so the billing screen renders the current plan and a valid period instead of an error state or the Unix epoch.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"plan":{"type":"string","enum":["starter","growth","enterprise"]},"planName":{"type":"string","example":"Growth","description":"Human-readable plan name (title-cased); planName.toLowerCase() === plan"},"status":{"type":"string","enum":["active","past_due","cancelled","trialing"]},"stripeSubscriptionId":{"type":"string","nullable":true},"stripeCustomerId":{"type":"string","nullable":true},"currentPeriodStart":{"type":"string","nullable":true},"currentPeriodEnd":{"type":"string","nullable":true},"cancelledAt":{"type":"string","nullable":true},"dunningState":{"type":"string","enum":["none","retrying","grace","suspended"],"example":"none","description":"SUP-0 dunning state machine: none → retrying → grace → suspended."},"graceUntil":{"type":"integer","nullable":true,"example":null,"description":"Unix seconds — end of the grace period before suspension (null unless in grace)."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenantId","plan","planName","status","stripeSubscriptionId","stripeCustomerId","currentPeriodStart","currentPeriodEnd","cancelledAt","dunningState","graceUntil","createdAt","updatedAt"]}}}}}}},"/v1/billing/usage":{"get":{"tags":["Billing"],"summary":"Get current plan usage","description":"Returns usage counts for each resource compared against plan limits.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Usage details","content":{"application/json":{"schema":{"type":"object","properties":{"products":{"type":"object","properties":{"used":{"type":"number"},"limit":{"type":"number"}},"required":["used","limit"]},"customers":{"type":"object","properties":{"used":{"type":"number"},"limit":{"type":"number"}},"required":["used","limit"]},"orders":{"type":"object","properties":{"used":{"type":"number"},"limit":{"type":"number"}},"required":["used","limit"]},"pages":{"type":"object","properties":{"used":{"type":"number"},"limit":{"type":"number"}},"required":["used","limit"]},"discounts":{"type":"object","properties":{"used":{"type":"number"},"limit":{"type":"number"}},"required":["used","limit"]},"staff":{"type":"object","properties":{"used":{"type":"number"},"limit":{"type":"number","nullable":true}},"required":["used","limit"]}},"required":["products","customers","orders","pages","discounts","staff"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/upgrade":{"post":{"tags":["Billing"],"summary":"Create checkout session for plan upgrade","description":"Creates a Stripe Checkout Session for subscribing to or upgrading a plan.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string","enum":["starter","growth","enterprise"],"example":"growth"}},"required":["plan"]}}}},"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{"type":"object","properties":{"checkoutUrl":{"type":"string"},"sessionId":{"type":"string"}},"required":["checkoutUrl","sessionId"]}}}},"400":{"description":"Invalid plan or already on this plan","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/portal":{"post":{"tags":["Billing"],"summary":"Create Stripe Customer Portal session","description":"Creates a Stripe Customer Portal session so the tenant can manage their subscription, payment methods, and invoices.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Portal session created","content":{"application/json":{"schema":{"type":"object","properties":{"portalUrl":{"type":"string"}},"required":["portalUrl"]}}}},"400":{"description":"No Stripe customer found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/invoices":{"get":{"tags":["Billing"],"summary":"List invoices","description":"Returns a paginated list of invoices for the tenant. Syncs from Stripe if requested.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"example":25},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","enum":["true","false"],"default":"false","description":"Force sync from Stripe"},"required":false,"description":"Force sync from Stripe","name":"sync","in":"query"}],"responses":{"200":{"description":"Paginated invoices","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"subscriptionId":{"type":"string","nullable":true},"stripeInvoiceId":{"type":"string","nullable":true},"amountDue":{"type":"number"},"amountPaid":{"type":"number"},"currency":{"type":"string"},"status":{"type":"string","enum":["draft","open","paid","void","uncollectible"]},"paidAt":{"type":"string","nullable":true},"periodStart":{"type":"string","nullable":true},"periodEnd":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenantId","subscriptionId","stripeInvoiceId","amountDue","amountPaid","currency","status","paidAt","periodStart","periodEnd","createdAt","updatedAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/billing/subscriptions/:id":{"patch":{"tags":["Billing","Stripe"],"summary":"Update Stripe subscription (plan change)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"sub_ABC123"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"priceId":{"type":"string","minLength":1,"example":"price_XYZ"},"prorationBehavior":{"type":"string","enum":["create_prorations","none","always_invoice"]}},"required":["priceId"]}}}},"responses":{"200":{"description":"Subscription updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StripeSubscriptionUpdated"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/billing/subscriptions/:id/cancel":{"post":{"tags":["Billing","Stripe"],"summary":"Cancel Stripe subscription","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"sub_ABC123"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"cancelAtPeriodEnd":{"type":"boolean","example":true}}}}}},"responses":{"200":{"description":"Subscription cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StripeSubscriptionCancelled"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/billing/subscriptions/:id/pause":{"post":{"tags":["Billing","Stripe"],"summary":"Pause Stripe subscription collection","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"sub_ABC123"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Subscription paused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StripeSubscriptionPaused"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/billing/subscriptions/:id/resume":{"post":{"tags":["Billing","Stripe"],"summary":"Resume paused Stripe subscription","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"sub_ABC123"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Subscription resumed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StripeSubscriptionResumed"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/billing/subscriptions/:id/preview-proration":{"post":{"tags":["Billing","Stripe"],"summary":"Preview proration for plan change","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"sub_ABC123"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"newPriceId":{"type":"string","minLength":1,"example":"price_XYZ"}},"required":["newPriceId"]}}}},"responses":{"200":{"description":"Proration preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StripeProrationPreview"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/billing/paypal-subscriptions":{"post":{"tags":["Billing","PayPal"],"summary":"Create PayPal subscription (returns approval URL)","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"planId":{"type":"string","minLength":1,"example":"P-ABC123"},"customerEmail":{"type":"string","format":"email"},"startTime":{"type":"string","example":"2026-06-01T00:00:00Z"},"quantity":{"type":"string"},"returnUrl":{"type":"string","format":"uri","example":"https://admin.inaishop.com/billing/success"},"cancelUrl":{"type":"string","format":"uri","example":"https://admin.inaishop.com/billing/cancel"}},"required":["planId","returnUrl","cancelUrl"]}}}},"responses":{"201":{"description":"Subscription created — redirect user to approvalUrl","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalSubscriptionCreated"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"PayPal credentials not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/billing/paypal-subscriptions/:id/activate":{"post":{"tags":["Billing","PayPal"],"summary":"Activate (reactivate) suspended PayPal subscription","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"I-BW452GLLEP1G"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":128,"example":"Reactivating after payment resolution"}},"required":["reason"]}}}},"responses":{"204":{"description":"Subscription activated"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Credentials not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/billing/paypal-subscriptions/:id/cancel":{"post":{"tags":["Billing","PayPal"],"summary":"Cancel PayPal subscription","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"I-BW452GLLEP1G"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":128,"example":"Customer requested cancellation"}},"required":["reason"]}}}},"responses":{"204":{"description":"Subscription cancelled"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Credentials not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/billing/paypal-subscriptions/:id/suspend":{"post":{"tags":["Billing","PayPal"],"summary":"Suspend PayPal subscription","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"I-BW452GLLEP1G"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":128,"example":"Payment overdue"}},"required":["reason"]}}}},"responses":{"204":{"description":"Subscription suspended"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Credentials not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/billing/billing/paypal-subscriptions/:id/revise":{"post":{"tags":["Billing","PayPal"],"summary":"Revise PayPal subscription (plan switch or quantity change)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"I-BW452GLLEP1G"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"planId":{"type":"string","example":"P-NEW123"},"quantity":{"type":"string","example":"5"}}}}}},"responses":{"200":{"description":"Revision applied. If approvalUrl is non-null, redirect user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalReviseResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Credentials not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/_internal/replay":{"post":{"tags":["Event Store"],"summary":"Replay events for an aggregate type","description":"Admin-only endpoint to replay events from the event store. Used for projection rebuilds and debugging.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"aggregate_type":{"type":"string","minLength":1},"since":{"type":"integer"},"aggregate_id":{"type":"string"}},"required":["aggregate_type"]}}}},"responses":{"200":{"description":"Replay summary","content":{"application/json":{"schema":{"type":"object","properties":{"replayed":{"type":"integer"},"errors":{"type":"integer"},"aggregate_type":{"type":"string"}},"required":["replayed","errors","aggregate_type"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden — admin role required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/_internal/outbox/dead":{"get":{"tags":["Event Store"],"summary":"List dead-lettered outbox events (DLQ)","description":"Lists the events stuck in the dead-letter queue for the resolved tenant: event id, destination, attempt count, last error and timestamp. Tenant-scoped via the resolved tenant DB. Admin role required.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":500,"default":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Dead-letter rows","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"eventId":{"type":"string"},"destination":{"type":"string"},"attempts":{"type":"integer"},"lastAttemptAt":{"type":"integer","nullable":true},"error":{"type":"string","nullable":true}},"required":["eventId","destination","attempts"]}},"count":{"type":"integer"}},"required":["data","count"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden — admin role required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/_internal/outbox/stats":{"get":{"tags":["Event Store"],"summary":"Outbox health counts by status","description":"Returns the outbox row counts by status (pending / failed / delivered / dead) for the resolved tenant. Admin role required.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Status counts","content":{"application/json":{"schema":{"type":"object","properties":{"pending":{"type":"integer"},"failed":{"type":"integer"},"delivered":{"type":"integer"},"dead":{"type":"integer"}},"required":["pending","failed","delivered","dead"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden — admin role required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/_internal/outbox/replay":{"post":{"tags":["Event Store"],"summary":"Replay dead-lettered outbox events (granular, idempotent)","description":"Re-queues a SUBSET of dead-lettered outbox events by id (reset to pending, attempts=0). Idempotent: downstream consumers dedupe via `consumeOutboxOnce`, so a replayed event is applied exactly once even if the relay retries. Pass `preview: true` for a dry-run that describes the effect without mutating. Returns 404 when none of the requested ids are in this tenant's DLQ. Admin role required.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventIds":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":500},"preview":{"type":"boolean","default":false}},"required":["eventIds"]}}}},"responses":{"200":{"description":"Replay (or preview) summary","content":{"application/json":{"schema":{"type":"object","properties":{"preview":{"type":"boolean"},"matched":{"type":"array","items":{"type":"string"}},"unknown":{"type":"array","items":{"type":"string"}},"requeued":{"type":"integer"}},"required":["preview","matched","unknown","requeued"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden — admin role required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"None of the requested events are in the DLQ","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/admin/stream":{"get":{"tags":["Admin"],"summary":"Real-time admin event stream (Server-Sent Events)","description":"Server-Sent Events feed for the admin dashboard. Emits `event: order.event` frames (consumed by the order Timeline) and `event: notification.created` frames (consumed by the NotificationBell). Keep-alive comments every 25s; streams auto-close after 10 minutes — clients reconnect.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"SSE stream of admin events.","content":{"text/event-stream":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/storefront/cart/recover":{"get":{"tags":["Cart"],"summary":"Rehydrate an abandoned cart from a signed recovery token (cross-device)","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"token","in":"query"}],"responses":{"200":{"description":"Cart rehydrated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Cart"}}}},"401":{"description":"Invalid or tampered token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"404":{"description":"Cart no longer exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"410":{"description":"Cart already converted (purchase complete)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}}}}},"/v1/storefront/cart/capture-email":{"post":{"tags":["Cart"],"summary":"Capture a guest email on the active cart for abandoned-cart recovery","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"acceptsMarketing":{"type":"boolean","default":false}},"required":["email"]}}}},"responses":{"200":{"description":"Email captured; recovery token issued","content":{"application/json":{"schema":{"type":"object","properties":{"cartId":{"type":"string"},"recoveryToken":{"type":"string"}},"required":["cartId","recoveryToken"]}}}},"404":{"description":"No active cart found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}}}}},"/v1/storefront/cart":{"get":{"tags":["Cart"],"summary":"Get current cart","description":"Returns the active cart for the authenticated customer or guest session.","responses":{"200":{"description":"Cart retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Cart"}}}},"404":{"description":"No active cart found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}}}},"delete":{"tags":["Cart"],"summary":"Clear all items from cart","responses":{"200":{"description":"Cart cleared","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Cart"}}}},"404":{"description":"No active cart found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}}}}},"/v1/storefront/cart/calculate":{"get":{"tags":["Cart"],"summary":"Calculate cart totals with resolved pricing","description":"Returns per-line resolved prices (base/variant/tier) and totals. B2B tier prices apply when the customer belongs to a group; tax is zeroed for tax-exempt customer groups.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartCalculation"}}}},"404":{"description":"No cart found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartCalculationProblem"}}}}}}},"/v1/storefront/cart/items":{"post":{"tags":["Cart"],"summary":"Add item to cart","description":"Adds a product to the cart. Creates a new cart if none exists.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddToCart"}}}},"responses":{"200":{"description":"Item added to cart","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Cart"}}}},"400":{"description":"Product not found, inactive, or insufficient stock","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}}}}},"/v1/storefront/cart/items/{itemId}":{"patch":{"tags":["Cart"],"summary":"Update cart item quantity","parameters":[{"schema":{"type":"string"},"required":true,"name":"itemId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCartItem"}}}},"responses":{"200":{"description":"Cart item updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Cart"}}}},"400":{"description":"Insufficient stock","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"404":{"description":"Cart or item not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}}}},"delete":{"tags":["Cart"],"summary":"Remove item from cart","parameters":[{"schema":{"type":"string"},"required":true,"name":"itemId","in":"path"}],"responses":{"200":{"description":"Item removed from cart","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Cart"}}}},"404":{"description":"Cart or item not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}}}}},"/v1/storefront/cart/discount":{"post":{"tags":["Cart"],"summary":"Apply discount code to cart","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyCartDiscount"}}}},"responses":{"200":{"description":"Discount applied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Cart"}}}},"400":{"description":"Invalid or expired discount code","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"404":{"description":"No active cart found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}}}}},"/v1/storefront/cart/merge":{"post":{"tags":["Cart"],"summary":"Merge guest cart into authenticated customer cart","description":"After a guest logs in, merges their session-based cart items into the customer cart. Duplicate products have their quantities summed. The guest cart is deleted after merge.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MergeCartBody"}}}},"responses":{"200":{"description":"Cart merged successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MergeCartResponse"}}}},"401":{"description":"Customer not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartProblem"}}}}}}},"/v1/storefront/checkout-layout":{"get":{"tags":["Checkout"],"summary":"A/B-assigned checkout flow layout for the visitor","description":"Deterministic, server-side layout assignment from the optional `checkout_layout` experiment. No authentication required.","responses":{"200":{"description":"Assigned checkout layout","content":{"application/json":{"schema":{"type":"object","properties":{"layout":{"type":"string","enum":["wizard","onepage","accordion"]},"experimentId":{"type":"string","nullable":true},"variant":{"type":"string","nullable":true}},"required":["layout","experimentId","variant"]}}}}}}},"/v1/storefront/checkout-layout/convert":{"post":{"tags":["Checkout"],"summary":"Record a checkout-layout A/B conversion","description":"Best-effort, idempotent conversion tracking for the checkout-layout experiment. No authentication required.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"valueCents":{"type":"integer","minimum":0}}}}}},"responses":{"200":{"description":"Recorded (or no-op)","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}}}}},"/v1/storefront/checkout":{"post":{"tags":["Checkout"],"summary":"Create a checkout from the active cart","description":"Validates all cart items are in stock, snapshots prices, and creates a checkout session that expires in 30 minutes.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"guest@example.com","description":"Email for guest checkout"}}}}}},"responses":{"201":{"description":"Checkout created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"chk_abc123def456"},"status":{"type":"string","enum":["pending","address_set","shipping_selected","payment_pending","completed","expired"]},"cartId":{"type":"string"},"email":{"type":"string","nullable":true},"shippingAddress":{"type":"object","nullable":true,"properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"company":{"type":"string","nullable":true},"address1":{"type":"string"},"address2":{"type":"string","nullable":true},"city":{"type":"string"},"state":{"type":"string","nullable":true},"zip":{"type":"string"},"country":{"type":"string"},"phone":{"type":"string","nullable":true}},"required":["firstName","lastName","company","address1","address2","city","state","zip","country","phone"]},"shippingMethod":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"price":{"type":"integer"},"isPickup":{"type":"boolean"},"pickupProvider":{"type":"string","nullable":true,"enum":["packlink","sendcloud",null]}},"required":["id","name","type","price"]},"subtotal":{"type":"integer","example":5998},"shippingTotal":{"type":"integer","example":999},"taxTotal":{"type":"integer","example":495},"discountTotal":{"type":"integer","example":0},"total":{"type":"integer","example":7492},"currency":{"type":"string","example":"USD"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"productId":{"type":"string"},"variantId":{"type":"string","nullable":true},"name":{"type":"string"},"sku":{"type":"string","nullable":true},"price":{"type":"integer"},"quantity":{"type":"integer"},"total":{"type":"integer"}},"required":["id","productId","variantId","name","sku","price","quantity","total"]}},"availableShippingMethods":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"price":{"type":"integer"},"isPickup":{"type":"boolean"},"pickupProvider":{"type":"string","nullable":true,"enum":["packlink","sendcloud",null]}},"required":["id","name","type","price"]}},"pickupPoint":{"$ref":"#/components/schemas/PickupPoint"},"expiresAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","status","cartId","email","shippingAddress","shippingMethod","subtotal","shippingTotal","taxTotal","discountTotal","total","currency","items","expiresAt","createdAt"]}}}},"400":{"description":"Bad request — cart empty or items out of stock","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"No active cart found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Stock validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/checkout/payment-methods":{"get":{"tags":["Checkout","Payments"],"summary":"List the active payment methods for the storefront","parameters":[{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Order total in cents — filters out COD above its configured cap"},"required":false,"description":"Order total in cents — filters out COD above its configured cap","name":"amount","in":"query"}],"responses":{"200":{"description":"Active methods with render metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorefrontPaymentMethodsResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}}}}},"/v1/storefront/checkout/:id":{"get":{"tags":["Checkout"],"summary":"Get checkout state","description":"Returns the full checkout state including items, totals, address, and shipping method.","parameters":[{"schema":{"type":"string","minLength":1,"example":"chk_abc123def456"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Checkout details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"chk_abc123def456"},"status":{"type":"string","enum":["pending","address_set","shipping_selected","payment_pending","completed","expired"]},"cartId":{"type":"string"},"email":{"type":"string","nullable":true},"shippingAddress":{"type":"object","nullable":true,"properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"company":{"type":"string","nullable":true},"address1":{"type":"string"},"address2":{"type":"string","nullable":true},"city":{"type":"string"},"state":{"type":"string","nullable":true},"zip":{"type":"string"},"country":{"type":"string"},"phone":{"type":"string","nullable":true}},"required":["firstName","lastName","company","address1","address2","city","state","zip","country","phone"]},"shippingMethod":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"price":{"type":"integer"},"isPickup":{"type":"boolean"},"pickupProvider":{"type":"string","nullable":true,"enum":["packlink","sendcloud",null]}},"required":["id","name","type","price"]},"subtotal":{"type":"integer","example":5998},"shippingTotal":{"type":"integer","example":999},"taxTotal":{"type":"integer","example":495},"discountTotal":{"type":"integer","example":0},"total":{"type":"integer","example":7492},"currency":{"type":"string","example":"USD"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"productId":{"type":"string"},"variantId":{"type":"string","nullable":true},"name":{"type":"string"},"sku":{"type":"string","nullable":true},"price":{"type":"integer"},"quantity":{"type":"integer"},"total":{"type":"integer"}},"required":["id","productId","variantId","name","sku","price","quantity","total"]}},"availableShippingMethods":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"price":{"type":"integer"},"isPickup":{"type":"boolean"},"pickupProvider":{"type":"string","nullable":true,"enum":["packlink","sendcloud",null]}},"required":["id","name","type","price"]}},"pickupPoint":{"$ref":"#/components/schemas/PickupPoint"},"expiresAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","status","cartId","email","shippingAddress","shippingMethod","subtotal","shippingTotal","taxTotal","discountTotal","total","currency","items","expiresAt","createdAt"]}}}},"404":{"description":"Checkout not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/checkout/:id/address":{"patch":{"tags":["Checkout"],"summary":"Set shipping address","description":"Sets the shipping address, determines shipping zone, and returns available shipping methods.","parameters":[{"schema":{"type":"string","minLength":1,"example":"chk_abc123def456"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"addressId":{"type":"string","example":"addr_abc123","description":"Use a saved customer address instead of providing inline fields"},"firstName":{"type":"string","minLength":1,"example":"John"},"lastName":{"type":"string","minLength":1,"example":"Doe"},"company":{"type":"string","example":"Acme Inc"},"address1":{"type":"string","minLength":1,"example":"123 Main St"},"address2":{"type":"string","example":"Apt 4B"},"city":{"type":"string","minLength":1,"example":"New York"},"state":{"type":"string","example":"NY"},"zip":{"type":"string","minLength":1,"example":"10001"},"country":{"type":"string","minLength":2,"maxLength":3,"example":"US"},"phone":{"type":"string","example":"+1-555-0100"},"saveAddress":{"type":"boolean","example":true,"description":"Save this address for future use (requires authenticated customer)"}}}}}},"responses":{"200":{"description":"Address set, available shipping methods returned","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"chk_abc123def456"},"status":{"type":"string","enum":["pending","address_set","shipping_selected","payment_pending","completed","expired"]},"cartId":{"type":"string"},"email":{"type":"string","nullable":true},"shippingAddress":{"type":"object","nullable":true,"properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"company":{"type":"string","nullable":true},"address1":{"type":"string"},"address2":{"type":"string","nullable":true},"city":{"type":"string"},"state":{"type":"string","nullable":true},"zip":{"type":"string"},"country":{"type":"string"},"phone":{"type":"string","nullable":true}},"required":["firstName","lastName","company","address1","address2","city","state","zip","country","phone"]},"shippingMethod":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"price":{"type":"integer"},"isPickup":{"type":"boolean"},"pickupProvider":{"type":"string","nullable":true,"enum":["packlink","sendcloud",null]}},"required":["id","name","type","price"]},"subtotal":{"type":"integer","example":5998},"shippingTotal":{"type":"integer","example":999},"taxTotal":{"type":"integer","example":495},"discountTotal":{"type":"integer","example":0},"total":{"type":"integer","example":7492},"currency":{"type":"string","example":"USD"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"productId":{"type":"string"},"variantId":{"type":"string","nullable":true},"name":{"type":"string"},"sku":{"type":"string","nullable":true},"price":{"type":"integer"},"quantity":{"type":"integer"},"total":{"type":"integer"}},"required":["id","productId","variantId","name","sku","price","quantity","total"]}},"availableShippingMethods":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"price":{"type":"integer"},"isPickup":{"type":"boolean"},"pickupProvider":{"type":"string","nullable":true,"enum":["packlink","sendcloud",null]}},"required":["id","name","type","price"]}},"pickupPoint":{"$ref":"#/components/schemas/PickupPoint"},"expiresAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","status","cartId","email","shippingAddress","shippingMethod","subtotal","shippingTotal","taxTotal","discountTotal","total","currency","items","expiresAt","createdAt"]}}}},"400":{"description":"Bad request — invalid checkout state","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Checkout not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/checkout/:id/shipping":{"patch":{"tags":["Checkout"],"summary":"Select shipping method","description":"Selects a shipping method, calculates shipping cost and tax, updates totals.","parameters":[{"schema":{"type":"string","minLength":1,"example":"chk_abc123def456"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"shippingMethodId":{"type":"string","minLength":1,"example":"shm_abc123def456"},"pickupPoint":{"allOf":[{"$ref":"#/components/schemas/PickupPoint"},{"description":"Out-of-home pickup point — required when the shipping method is a pickup method"}]}},"required":["shippingMethodId"]}}}},"responses":{"200":{"description":"Shipping method selected, totals updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"chk_abc123def456"},"status":{"type":"string","enum":["pending","address_set","shipping_selected","payment_pending","completed","expired"]},"cartId":{"type":"string"},"email":{"type":"string","nullable":true},"shippingAddress":{"type":"object","nullable":true,"properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"company":{"type":"string","nullable":true},"address1":{"type":"string"},"address2":{"type":"string","nullable":true},"city":{"type":"string"},"state":{"type":"string","nullable":true},"zip":{"type":"string"},"country":{"type":"string"},"phone":{"type":"string","nullable":true}},"required":["firstName","lastName","company","address1","address2","city","state","zip","country","phone"]},"shippingMethod":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"price":{"type":"integer"},"isPickup":{"type":"boolean"},"pickupProvider":{"type":"string","nullable":true,"enum":["packlink","sendcloud",null]}},"required":["id","name","type","price"]},"subtotal":{"type":"integer","example":5998},"shippingTotal":{"type":"integer","example":999},"taxTotal":{"type":"integer","example":495},"discountTotal":{"type":"integer","example":0},"total":{"type":"integer","example":7492},"currency":{"type":"string","example":"USD"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"productId":{"type":"string"},"variantId":{"type":"string","nullable":true},"name":{"type":"string"},"sku":{"type":"string","nullable":true},"price":{"type":"integer"},"quantity":{"type":"integer"},"total":{"type":"integer"}},"required":["id","productId","variantId","name","sku","price","quantity","total"]}},"availableShippingMethods":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"price":{"type":"integer"},"isPickup":{"type":"boolean"},"pickupProvider":{"type":"string","nullable":true,"enum":["packlink","sendcloud",null]}},"required":["id","name","type","price"]}},"pickupPoint":{"$ref":"#/components/schemas/PickupPoint"},"expiresAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","status","cartId","email","shippingAddress","shippingMethod","subtotal","shippingTotal","taxTotal","discountTotal","total","currency","items","expiresAt","createdAt"]}}}},"400":{"description":"Bad request — invalid checkout state or shipping method","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Checkout or shipping method not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Unprocessable — pickup method selected without a pickup point","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/checkout/:id/payment":{"post":{"tags":["Checkout"],"summary":"Create payment intent for checkout","description":"Creates a Stripe PaymentIntent with the checkout total. Returns client_secret for frontend Stripe Elements.","parameters":[{"schema":{"type":"string","minLength":1,"example":"chk_abc123def456"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Payment intent created","content":{"application/json":{"schema":{"type":"object","properties":{"clientSecret":{"type":"string","example":"pi_3MtwBwLkdIwHu7ix_secret_abc123"},"paymentIntentId":{"type":"string","example":"pi_3MtwBwLkdIwHu7ix28a3tqPa"}},"required":["clientSecret","paymentIntentId"]}}}},"400":{"description":"Bad request — invalid checkout state","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Checkout not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Stripe credentials not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/checkout/:id/retry-payment":{"post":{"tags":["Checkout"],"summary":"Retry payment for checkout","description":"Retries a failed payment with a new payment method. Maximum 3 attempts per checkout.","parameters":[{"schema":{"type":"string","minLength":1,"example":"chk_abc123def456"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"paymentMethodId":{"type":"string","minLength":1,"example":"pm_card_visa","description":"New payment method ID. If omitted, retries with existing payment intent."}}}}}},"responses":{"200":{"description":"Payment retry initiated","content":{"application/json":{"schema":{"type":"object","properties":{"clientSecret":{"type":"string"},"paymentIntentId":{"type":"string"},"status":{"type":"string"},"attemptsRemaining":{"type":"integer"}},"required":["clientSecret","paymentIntentId","attemptsRemaining"]}}}},"400":{"description":"Bad request — invalid checkout state or max retries exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"402":{"description":"Payment failed","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Checkout not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/checkout/:id/confirm":{"post":{"tags":["Checkout"],"summary":"Confirm checkout and create order","description":"Verifies payment succeeded via Stripe API, creates the order, decrements stock, and converts the cart. Optionally creates a customer account for guest checkouts.","parameters":[{"schema":{"type":"string","minLength":1,"example":"chk_abc123def456"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"createAccount":{"type":"boolean","example":true,"description":"If true and guest checkout, create a customer account post-payment"},"password":{"type":"string","minLength":8,"example":"securepass123","description":"Password for the new customer account (required if createAccount is true)"}}}}}},"responses":{"200":{"description":"Order created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"order":{"type":"object","properties":{"id":{"type":"string"},"orderNumber":{"type":"string"},"status":{"type":"string"},"total":{"type":"integer"},"currency":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","orderNumber","status","total","currency","createdAt"]},"message":{"type":"string","example":"Order confirmed successfully"}},"required":["order","message"]}}}},"400":{"description":"Bad request — invalid checkout state","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"402":{"description":"Payment not completed","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Checkout not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/checkout/{id}/payments/paypal/create-order":{"post":{"tags":["Checkout","PayPal"],"summary":"Create a PayPal order for a checkout","description":"Returns the PayPal order id + approve URL. Customer is redirected to approveUrl to authorize.","parameters":[{"schema":{"type":"string","minLength":1,"example":"chk_abc123def456"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"returnUrl":{"type":"string","format":"uri"},"cancelUrl":{"type":"string","format":"uri"}},"required":["returnUrl","cancelUrl"]}}}},"responses":{"200":{"description":"Order created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalCreateOrderResponse"}}}},"400":{"description":"Checkout not in shipping_selected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}},"402":{"description":"PayPal API error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}},"404":{"description":"Checkout not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}},"422":{"description":"PayPal credentials not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}},"502":{"description":"PayPal returned an invalid response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}}}}},"/v1/storefront/checkout/{id}/payments/paypal/capture":{"post":{"tags":["Checkout","PayPal"],"summary":"Capture an approved PayPal order","description":"Captures funds and creates the local order if not already created.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"paypalOrderId":{"type":"string","minLength":1}},"required":["paypalOrderId"]}}}},"responses":{"200":{"description":"Captured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalCaptureResponse"}}}},"400":{"description":"Checkout not awaiting payment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}},"402":{"description":"Capture declined","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}},"404":{"description":"Checkout not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}},"409":{"description":"Already captured / order exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}},"422":{"description":"Credentials not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPalProblem"}}}}}}},"/v1/storefront/checkout/{id}/payments/redsys":{"post":{"tags":["Checkout","Redsys"],"summary":"Create a Redsys (TPV Virtual) redirect payment","description":"Returns the signed form fields (Ds_SignatureVersion/Ds_MerchantParameters/Ds_Signature) plus the SIS URL the storefront must auto-POST. method=bizum uses the Bizum pay method on the same TPV.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedsysCreatePaymentInput"}}}},"responses":{"200":{"description":"Redirect form created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedsysRedirectFormResponse"}}}},"400":{"description":"Invalid checkout state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"404":{"description":"Checkout not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"422":{"description":"Redsys not configured / unsupported currency","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}}}}},"/v1/storefront/checkout/{id}/payments/sequra":{"post":{"tags":["Checkout","SeQura"],"summary":"Start a SeQura BNPL solicitation","description":"Creates the SeQura order draft and returns the hosted form URL for the redirect/widget flow.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequraStartInput"}}}},"responses":{"200":{"description":"Solicitation started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequraStartResponse"}}}},"400":{"description":"Invalid checkout state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"402":{"description":"SeQura rejected the solicitation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"404":{"description":"Checkout not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"422":{"description":"SeQura not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}}}}},"/v1/storefront/checkout/{id}/manual-payment":{"post":{"tags":["Checkout","Payments"],"summary":"Place the order with an offline payment method (COD / bank transfer)","description":"Creates the order as 'pending_payment'. COD adds the configured surcharge; bank transfer returns IBAN + localized instructions.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManualPaymentInput"}}}},"responses":{"200":{"description":"Order created pending payment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManualPaymentResponse"}}}},"400":{"description":"Invalid checkout state / COD limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"404":{"description":"Checkout not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"409":{"description":"Checkout already completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"422":{"description":"Method not enabled for this tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}}}}},"/v1/storefront/checkout/{id}/apply-gift-card":{"post":{"tags":["Checkout"],"summary":"Apply a gift card to checkout — reserves balance until confirm","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","minLength":1}},"required":["code"]}}}},"responses":{"200":{"description":"Gift card applied","content":{"application/json":{"schema":{"type":"object","properties":{"giftCardId":{"type":"string"},"reservedAmount":{"type":"integer"},"checkoutTotal":{"type":"integer"},"currency":{"type":"string"}},"required":["giftCardId","reservedAmount","checkoutTotal","currency"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/checkout/{id}/remove-gift-card/{giftCardId}":{"delete":{"tags":["Checkout"],"summary":"Remove applied gift card from checkout — releases reserved balance","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"giftCardId","in":"path"}],"responses":{"200":{"description":"Gift card removed","content":{"application/json":{"schema":{"type":"object","properties":{"checkoutTotal":{"type":"integer"},"currency":{"type":"string"}},"required":["checkoutTotal","currency"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/checkout/{id}/apply-loyalty-points":{"post":{"tags":["Checkout"],"summary":"Apply loyalty points as a discount at checkout","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"points":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["points"]}}}},"responses":{"200":{"description":"Points applied","content":{"application/json":{"schema":{"type":"object","properties":{"pointsApplied":{"type":"integer"},"discountCents":{"type":"integer"},"checkoutTotal":{"type":"integer"},"pointsBalance":{"type":"integer"}},"required":["pointsApplied","discountCents","checkoutTotal","pointsBalance"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/checkout/{id}/remove-loyalty-points":{"delete":{"tags":["Checkout"],"summary":"Remove loyalty points discount from checkout","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Points removed","content":{"application/json":{"schema":{"type":"object","properties":{"checkoutTotal":{"type":"integer"}},"required":["checkoutTotal"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/pickup-points":{"get":{"tags":["Shipping","Storefront"],"summary":"List out-of-home pickup points near a postal code","description":"Normalised pickup/dropoff points from the tenant's active shipping aggregators (Sendcloud service points, Packlink dropoffs). Cached per (country, postal code) for 24h.","parameters":[{"schema":{"type":"string","minLength":2,"maxLength":16,"example":"28013"},"required":true,"name":"postal_code","in":"query"},{"schema":{"type":"string","minLength":2,"maxLength":2,"example":"ES","description":"ISO 3166-1 alpha-2"},"required":true,"description":"ISO 3166-1 alpha-2","name":"country","in":"query"},{"schema":{"type":"string","enum":["packlink","sendcloud"],"example":"sendcloud"},"required":false,"name":"provider","in":"query"}],"responses":{"200":{"description":"Normalised pickup points (possibly empty when no aggregator account is configured)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PickupPointWithHours"}}},"required":["data"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}},"502":{"description":"All configured providers failed","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/profile":{"get":{"tags":["Storefront"],"summary":"Get customer profile","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Customer profile","content":{"application/json":{"schema":{"type":"object","properties":{"customer":{"type":"object","properties":{"id":{"type":"string","example":"cst_01abc"},"email":{"type":"string","example":"customer@example.com"},"firstName":{"type":"string","nullable":true,"example":"Jane"},"lastName":{"type":"string","nullable":true,"example":"Doe"},"phone":{"type":"string","nullable":true,"example":"+1234567890"},"acceptsMarketing":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","email","firstName","lastName","phone","acceptsMarketing","createdAt"]}},"required":["customer"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Storefront"],"summary":"Update customer profile","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":255,"example":"Jane"},"lastName":{"type":"string","minLength":1,"maxLength":255,"example":"Doe"},"phone":{"type":"string","maxLength":50,"example":"+1234567890"},"email":{"type":"string","maxLength":255,"format":"email","example":"new@example.com"},"acceptsMarketing":{"type":"boolean","example":true}}}}}},"responses":{"200":{"description":"Profile updated","content":{"application/json":{"schema":{"type":"object","properties":{"customer":{"type":"object","properties":{"id":{"type":"string","example":"cst_01abc"},"email":{"type":"string","example":"customer@example.com"},"firstName":{"type":"string","nullable":true,"example":"Jane"},"lastName":{"type":"string","nullable":true,"example":"Doe"},"phone":{"type":"string","nullable":true,"example":"+1234567890"},"acceptsMarketing":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","email","firstName","lastName","phone","acceptsMarketing","createdAt"]}},"required":["customer"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/orders":{"get":{"tags":["Storefront"],"summary":"List customer orders","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","default":"1","example":"1"},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","default":"25","example":"25"},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Paginated list of customer orders","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"orderNumber":{"type":"string","nullable":true},"status":{"type":"string"},"total":{"type":"number"},"subtotal":{"type":"number"},"shippingTotal":{"type":"number"},"taxTotal":{"type":"number"},"discountTotal":{"type":"number"},"currency":{"type":"string"},"createdAt":{"type":"string"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"sku":{"type":"string","nullable":true},"price":{"type":"number"},"quantity":{"type":"number"},"total":{"type":"number"}},"required":["id","name","sku","price","quantity","total"]}}},"required":["id","orderNumber","status","total","subtotal","shippingTotal","taxTotal","discountTotal","currency","createdAt","items"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/export-data":{"get":{"tags":["Storefront"],"summary":"Export customer data (GDPR)","description":"Exports all customer data as a JSON file for GDPR data portability.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Customer data export","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{"nullable":true}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/account":{"delete":{"tags":["Storefront"],"summary":"Delete customer account (GDPR)","description":"Anonymizes orders and shipping addresses, deletes personal data, addresses, tokens, carts, checkouts, newsletter subscriptions, and segment memberships. Orders are kept for fiscal compliance.","security":[{"bearerAuth":[]}],"responses":{"204":{"description":"Account deleted and data anonymized"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/payment-methods/setup-intent":{"post":{"tags":["Payment Methods"],"summary":"Create a SetupIntent to vault a card","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"SetupIntent client secret","content":{"application/json":{"schema":{"type":"object","properties":{"clientSecret":{"type":"string"}},"required":["clientSecret"]}}}},"401":{"description":"Auth required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Stripe not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"502":{"description":"Stripe error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/payment-methods":{"get":{"tags":["Payment Methods"],"summary":"List the customer's saved cards (tokenized crumbs only)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Saved cards","content":{"application/json":{"schema":{"type":"object","properties":{"paymentMethods":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"brand":{"type":"string"},"last4":{"type":"string"},"expMonth":{"type":"integer"},"expYear":{"type":"integer"}},"required":["id","brand","last4","expMonth","expYear"]}}},"required":["paymentMethods"]}}}},"401":{"description":"Auth required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/payment-methods/{id}":{"delete":{"tags":["Payment Methods"],"summary":"Forget a saved card","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Detached","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}},"401":{"description":"Auth required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Not the owner","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Stripe not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"502":{"description":"Stripe error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/payment-methods/charge":{"post":{"tags":["Payment Methods"],"summary":"One-tap charge an order with a saved card","description":"Creates + confirms an off-session PaymentIntent against a saved, tokenized payment method for an order the authenticated customer owns. The amount is taken from the order, never the request.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"orderId":{"type":"string","minLength":1},"paymentMethodId":{"type":"string","minLength":1}},"required":["orderId","paymentMethodId"]}}}},"responses":{"200":{"description":"Payment outcome (succeeded | requires_action | declined)","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"status":{"type":"string","enum":["succeeded"]},"paymentIntentId":{"type":"string"},"orderId":{"type":"string"}},"required":["status","paymentIntentId","orderId"]},{"type":"object","properties":{"status":{"type":"string","enum":["requires_action"]},"paymentIntentId":{"type":"string"},"clientSecret":{"type":"string"},"orderId":{"type":"string"}},"required":["status","paymentIntentId","clientSecret","orderId"]},{"type":"object","properties":{"status":{"type":"string","enum":["declined"]},"declineMessage":{"type":"string"},"code":{"type":"string"},"orderId":{"type":"string"}},"required":["status","declineMessage","orderId"]}]}}}},"401":{"description":"Auth required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Order or payment method not owned by the customer","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Order already paid","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Order not payable / Stripe not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"502":{"description":"Stripe error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/legal/acceptances":{"post":{"tags":["Legal"],"summary":"Record acceptance of a legal document (checkout T&C evidence)","description":"Persists evidence that the shopper accepted a legal document (LSSI-CE / consumer protection). The client IP is NEVER stored raw — only a salted SHA-256 hash (GDPR data minimisation).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"string","minLength":1,"maxLength":64,"default":"checkout_terms"},"checkoutId":{"type":"string","minLength":1,"maxLength":128},"orderId":{"type":"string","minLength":1,"maxLength":128},"customerId":{"type":"string","minLength":1,"maxLength":128},"docSlug":{"type":"string","minLength":1,"maxLength":128},"docVersion":{"type":"string","minLength":1,"maxLength":64}},"required":["docSlug","docVersion"]}}}},"responses":{"201":{"description":"Acceptance recorded","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"scope":{"type":"string"},"checkoutId":{"type":"string","nullable":true},"orderId":{"type":"string","nullable":true},"customerId":{"type":"string","nullable":true},"docSlug":{"type":"string"},"docVersion":{"type":"string"},"acceptedAt":{"type":"number"},"ipHash":{"type":"string","nullable":true},"userAgent":{"type":"string","nullable":true}},"required":["id","scope","checkoutId","orderId","customerId","docSlug","docVersion","acceptedAt","ipHash","userAgent"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/consent":{"post":{"tags":["Consent"],"summary":"Set consent preferences","description":"Creates or updates consent record for the customer or session.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"categories":{"type":"object","properties":{"necessary":{"type":"boolean","example":true},"analytics":{"type":"boolean","example":false},"marketing":{"type":"boolean","example":false},"preferences":{"type":"boolean","example":true}},"required":["necessary","analytics","marketing","preferences"]},"version":{"type":"string","example":"1.0"}},"required":["categories"]}}}},"responses":{"200":{"description":"Consent recorded","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"customerId":{"type":"string","nullable":true},"sessionId":{"type":"string","nullable":true},"categories":{"type":"object","additionalProperties":{"type":"boolean"}},"version":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","customerId","sessionId","categories","version","createdAt","updatedAt"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"get":{"tags":["Consent"],"summary":"Get consent record","description":"Returns the current consent record for the customer or session.","responses":{"200":{"description":"Consent record found","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"customerId":{"type":"string","nullable":true},"sessionId":{"type":"string","nullable":true},"categories":{"type":"object","additionalProperties":{"type":"boolean"}},"version":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","customerId","sessionId","categories","version","createdAt","updatedAt"]}}}},"404":{"description":"No consent record found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/consent/config":{"get":{"tags":["Consent"],"summary":"Get cookie consent configuration","description":"Returns the available cookie categories and their descriptions.","responses":{"200":{"description":"Cookie categories configuration","content":{"application/json":{"schema":{"type":"object","properties":{"categories":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"required":{"type":"boolean"}},"required":["key","name","description","required"]}}},"required":["categories"]}}}}}}},"/v1/storefront/consent/{sessionId}":{"get":{"tags":["Legal"],"summary":"Get stored cookie-consent preferences for a session","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"sessionId","in":"path"}],"responses":{"200":{"description":"Stored consent preferences","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"sessionId":{"type":"string"},"customerId":{"type":"string","nullable":true},"analytics":{"type":"boolean"},"marketing":{"type":"boolean"},"functional":{"type":"boolean"},"decidedAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","sessionId","customerId","analytics","marketing","functional","decidedAt","updatedAt"]}}}},"404":{"description":"No consent recorded for this session","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/b2b/account":{"get":{"tags":["B2B","Storefront"],"summary":"Get current customer's B2B account","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bAccount"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"No B2B account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/quotes":{"get":{"tags":["B2B","Quotes","Storefront"],"summary":"List quotes for current customer","parameters":[{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"$ref":"#/components/schemas/QuoteStatus"},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorefrontQuoteList"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"post":{"tags":["B2B","Quotes","Storefront"],"summary":"Create a quote (storefront)","description":"Creates a quote in `draft` status. Customer must own the linked B2B account.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateQuote"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"Bad request — invalid product/variant or expiresAt in past","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Not the account owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/quotes/{id}":{"get":{"tags":["B2B","Quotes","Storefront"],"summary":"Get a quote by id","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden — not the requester or approver","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"patch":{"tags":["B2B","Quotes","Storefront"],"summary":"Update a draft quote (storefront)","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string","minLength":1},"variantId":{"type":"string","minLength":1},"qty":{"type":"integer","minimum":1},"unitPrice":{"type":"integer","minimum":0},"note":{"type":"string","maxLength":500}},"required":["productId","qty"]},"minItems":1,"maxItems":200},"customerNote":{"type":"string","maxLength":2000},"expiresAt":{"type":"string","format":"date-time"},"discountTotal":{"type":"integer","minimum":0},"shippingTotal":{"type":"integer","minimum":0}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden — not owner or not editable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/quotes/{id}/revisions":{"get":{"tags":["B2B","Quotes","Storefront"],"summary":"Quote negotiation history","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRevisionList"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Not the owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/quotes/{id}/counter":{"post":{"tags":["B2B","Quotes","Storefront"],"summary":"Counter a merchant offer (buyer)","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CounterQuote"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"Invalid items","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Not the owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"409":{"description":"Quote not in negotiation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/quotes/{id}/submit":{"post":{"tags":["B2B","Quotes","Storefront"],"summary":"Submit a quote for review","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"Bad transition or empty items","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/quotes/{id}/convert":{"post":{"tags":["B2B","Quotes","Storefront"],"summary":"Convert an approved quote into an order","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertQuote"}}}},"responses":{"201":{"description":"Order created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertQuoteResponse"}}}},"400":{"description":"Quote not approved / expired / missing PO number","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"402":{"description":"Insufficient credit (PO terms)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"409":{"description":"Quote already converted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/orders/on-account":{"post":{"tags":["B2B","Orders","Storefront"],"summary":"Place an on-account (net terms) order","description":"Creates an order on the company account without immediate payment. The order total is checked against the company credit limit (existing balance + new order <= limit). Stock is decremented and a due date is set from the account payment terms.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOnAccountOrder"}}}},"responses":{"201":{"description":"Order created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnAccountOrderResponse"}}}},"400":{"description":"Bad request — empty/invalid items","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"402":{"description":"Insufficient credit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden — not the account owner or account not active","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/purchase-orders":{"get":{"tags":["B2B","PurchaseOrders","Storefront"],"summary":"List PO for current customer's accounts","parameters":[{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"$ref":"#/components/schemas/PurchaseOrderStatus"},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorefrontPurchaseOrderList"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"post":{"tags":["B2B","PurchaseOrders","Storefront"],"summary":"Upload a purchase order and link to an existing order","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePurchaseOrder"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrder"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden — order not in customer scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"409":{"description":"PO number already used","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/approval-requests":{"get":{"tags":["B2B","ApprovalRequests","Storefront"],"summary":"List pending approval requests for current approver","parameters":[{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"$ref":"#/components/schemas/ApprovalRequestStatus"},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalRequestList"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/approval-requests/{id}/decisions":{"get":{"tags":["B2B","ApprovalRequests","Storefront"],"summary":"Decision history for an approval request","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalDecisionHistory"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Not an approver","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/approval-requests/{id}/approve":{"post":{"tags":["B2B","ApprovalRequests","Storefront"],"summary":"Approve an approval request","description":"Records a multi-level approval decision. Approve advances the level; the final level finalises the request and applies downstream side-effects.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalDecision"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalRequest"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Not an approver / over approval limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"409":{"description":"Invalid transition / already decided / expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/approval-requests/{id}/reject":{"post":{"tags":["B2B","ApprovalRequests","Storefront"],"summary":"Reject an approval request","description":"Records a multi-level approval decision. Approve advances the level; the final level finalises the request and applies downstream side-effects.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalDecision"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalRequest"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Not an approver / over approval limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"409":{"description":"Invalid transition / already decided / expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/quick-order/validate":{"post":{"tags":["B2B","QuickOrder","Storefront"],"summary":"Resolve + price a bulk quick-order list by SKU","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuickOrderValidate"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuickOrderResult"}}}},"400":{"description":"No items provided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/context":{"get":{"tags":["B2B","Storefront"],"summary":"Resolve the current customer's B2B context (company, membership, account, pricing)","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/B2bStorefrontContext"}},"required":["data"]}}}},"401":{"description":"Auth required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/company":{"get":{"tags":["B2B","Companies","Storefront"],"summary":"Get the current member's company","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Company"},"membership":{"$ref":"#/components/schemas/CompanyUser"}},"required":["data","membership"]}}}},"401":{"description":"Auth required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"No company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/company/users":{"get":{"tags":["B2B","Companies","Storefront"],"summary":"List company users (admin only)","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CompanyUser"}}},"required":["data"]}}}},"401":{"description":"Auth required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Not a company admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/company/users/{userId}":{"patch":{"tags":["B2B","Companies","Storefront"],"summary":"Update a company user (admin only)","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"userId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCompanyUserBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CompanyUser"}},"required":["data"]}}}},"401":{"description":"Auth","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"delete":{"tags":["B2B","Companies","Storefront"],"summary":"Remove a company user (admin removes others; anyone removes self)","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"userId","in":"path"}],"responses":{"204":{"description":"Removed"},"401":{"description":"Auth","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"409":{"description":"Last admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/requisition-lists":{"get":{"tags":["B2B","RequisitionLists","Storefront"],"summary":"List my company's requisition lists","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RequisitionList"}}},"required":["data"]}}}},"401":{"description":"Auth","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"No company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"post":{"tags":["B2B","RequisitionLists","Storefront"],"summary":"Create a requisition list","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200}},"required":["name"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RequisitionList"}},"required":["data"]}}}},"401":{"description":"Auth","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"No company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/requisition-lists/{id}":{"get":{"tags":["B2B","RequisitionLists","Storefront"],"summary":"Get a requisition list with priced items","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/RequisitionList"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"product_id":{"type":"string"},"variant_id":{"type":"string","nullable":true},"quantity":{"type":"integer"},"unit_price_cents":{"type":"integer"},"line_total_cents":{"type":"integer"},"price_source":{"type":"string","enum":["price_list","variant","base"]}},"required":["product_id","variant_id","quantity","unit_price_cents","line_total_cents","price_source"]}},"subtotal_cents":{"type":"integer"}},"required":["items","subtotal_cents"]}]}},"required":["data"]}}}},"401":{"description":"Auth","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"patch":{"tags":["B2B","RequisitionLists","Storefront"],"summary":"Rename a requisition list","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRequisitionListBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RequisitionList"}},"required":["data"]}}}},"401":{"description":"Auth","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"delete":{"tags":["B2B","RequisitionLists","Storefront"],"summary":"Delete a requisition list","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Auth","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/requisition-lists/{id}/items":{"post":{"tags":["B2B","RequisitionLists","Storefront"],"summary":"Add an item to a requisition list","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"product_id":{"type":"string","minLength":1},"variant_id":{"type":"string","nullable":true},"quantity":{"type":"integer","minimum":0,"exclusiveMinimum":true,"default":1}},"required":["product_id"]}}}},"responses":{"201":{"description":"Added","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}},"required":["data"]}}}},"401":{"description":"Auth","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/b2b/requisition-lists/{id}/items/{itemId}":{"delete":{"tags":["B2B","RequisitionLists","Storefront"],"summary":"Remove an item from a requisition list","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"itemId","in":"path"}],"responses":{"204":{"description":"Removed"},"401":{"description":"Auth","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/storefront/orders/{orderId}/returns":{"post":{"tags":["Returns","Storefront"],"summary":"Create a return for your own order","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"orderId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"orderItemId":{"type":"string","minLength":1},"quantity":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["orderItemId","quantity"]},"minItems":1},"customerNote":{"type":"string","maxLength":2000},"refundMethod":{"type":"string","enum":["original_payment","store_credit"]}},"required":["items"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"returnNumber":{"type":"string"},"orderId":{"type":"string"},"status":{"type":"string"},"refundAmount":{"type":"integer"},"shippingLabelUrl":{"type":"string","nullable":true},"trackingNumber":{"type":"string","nullable":true}},"required":["id","returnNumber","orderId","status","refundAmount","shippingLabelUrl","trackingNumber"]}},"required":["data"]}}}},"400":{"description":"Not returnable","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Auth","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Not your order","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Item already in a return","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Quantity","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/returns/{id}":{"get":{"tags":["Returns","Storefront"],"summary":"Get your return","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"returnNumber":{"type":"string"},"orderId":{"type":"string"},"status":{"type":"string"},"refundAmount":{"type":"integer"},"shippingLabelUrl":{"type":"string","nullable":true},"trackingNumber":{"type":"string","nullable":true}},"required":["id","returnNumber","orderId","status","refundAmount","shippingLabelUrl","trackingNumber"]}},"required":["data"]}}}},"401":{"description":"Auth","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Not yours","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/returns/{id}/label":{"post":{"tags":["Returns","Storefront"],"summary":"Generate a prepaid return shipping label","description":"Buys a reverse label (customer → return warehouse) via the tenant's active carrier account (Shippo, or Packlink PRO / Sendcloud). Optionally accepts a JSON body { dropoffPoint } with an OOH point (SUP-1 / N17) — persisted on the return history and used to route the label through the matching aggregator.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Label","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"labelUrl":{"type":"string"},"trackingNumber":{"type":"string"},"carrier":{"type":"string"},"amountCents":{"type":"integer"},"currency":{"type":"string"}},"required":["labelUrl","trackingNumber","carrier","amountCents","currency"]}},"required":["data"]}}}},"400":{"description":"Missing address / warehouse / carrier","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Auth","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Not yours","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Not approved","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Invalid dropoffPoint","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"502":{"description":"Carrier error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/v1/markets/resolve":{"get":{"tags":["Markets"],"summary":"Resolve the active market","parameters":[{"schema":{"type":"string","minLength":2,"maxLength":2,"example":"FR"},"required":false,"name":"country","in":"query"},{"schema":{"type":"string","minLength":3,"maxLength":3,"example":"EUR"},"required":false,"name":"currency","in":"query"},{"schema":{"type":"string"},"required":false,"name":"handle","in":"query"}],"responses":{"200":{"description":"Resolved market","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveMarketResponse"}}}},"404":{"description":"No market configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketsProblem"}}}}}}},"/v1/v1/markets/resolve-price":{"get":{"tags":["Markets"],"summary":"Resolve a presentment price for a market","description":"Resolves the active market (explicit id/handle, country, currency, or headers) and converts a base price into the market presentment currency with adjustment, rounding and tax behaviour.","parameters":[{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Base price in cents (tenant base currency)","example":10000},"required":false,"description":"Base price in cents (tenant base currency)","name":"amount","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Optional base compare-at price in cents","example":12000},"required":false,"description":"Optional base compare-at price in cents","name":"compareAt","in":"query"},{"schema":{"type":"string","description":"Resolve against this market id"},"required":false,"description":"Resolve against this market id","name":"marketId","in":"query"},{"schema":{"type":"string","description":"Resolve against this market handle"},"required":false,"description":"Resolve against this market handle","name":"marketHandle","in":"query"},{"schema":{"type":"string","minLength":2,"maxLength":2,"description":"Detect market by country","example":"FR"},"required":false,"description":"Detect market by country","name":"country","in":"query"},{"schema":{"type":"string","minLength":3,"maxLength":3,"description":"Detect market by presentment currency","example":"EUR"},"required":false,"description":"Detect market by presentment currency","name":"currency","in":"query"}],"responses":{"200":{"description":"Resolved presentment price","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolvePriceResponse"}}}},"404":{"description":"No market configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketsProblem"}}}}}}},"/v1/storefront/products":{"get":{"tags":["Storefront"],"summary":"List public products (storefront)","description":"Public, tenant-scoped product listing for the storefront. Defaults to active products. Mirrors GET /v1/products item shape + Wave 33 price resolution.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","example":"eyJ0Ijoi...","description":"Signed keyset cursor (O(1) deep pagination). Overrides page when present."},"required":false,"description":"Signed keyset cursor (O(1) deep pagination). Overrides page when present.","name":"cursor","in":"query"},{"schema":{"type":"string","example":"shirt"},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","enum":["active","draft","archived"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","example":"cat_01"},"required":false,"name":"category_id","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"example":1000,"description":"Minimum price in cents"},"required":false,"description":"Minimum price in cents","name":"min_price","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"example":5000,"description":"Maximum price in cents"},"required":false,"description":"Maximum price in cents","name":"max_price","in":"query"},{"schema":{"type":"string","minLength":3,"maxLength":3,"example":"EUR","description":"ISO 4217 code for display price resolution"},"required":false,"description":"ISO 4217 code for display price resolution","name":"display_currency","in":"query"}],"responses":{"200":{"description":"List of public products","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"T-Shirt"},"slug":{"type":"string","example":"t-shirt"},"content":{"type":"string","nullable":true,"example":"A great t-shirt"},"status":{"type":"string","enum":["active","draft","archived"],"example":"active"},"type":{"type":"string","enum":["simple","configurable","bundle","grouped","virtual","downloadable","gift_card","subscription"],"example":"simple","description":"Product type. Digital types (virtual/downloadable/gift_card/subscription) trigger post-payment fulfilment."},"price":{"type":"integer","minimum":0,"example":2999,"description":"Price in cents"},"compareAtPrice":{"type":"integer","nullable":true,"minimum":0,"example":3999},"sku":{"type":"string","nullable":true,"example":"TSH-001"},"stock":{"type":"integer","minimum":0,"example":100},"categoryId":{"type":"string","nullable":true,"example":"cat_01"},"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"ISO 4217 currency code of the resolved display price"},"basePrice":{"type":"integer","minimum":0,"example":2999,"description":"Base price in tenant currency (cents). Wave 33."},"baseCurrency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"Tenant base currency. Wave 33."},"priceSource":{"type":"string","enum":["explicit","converted","base"],"example":"explicit","description":"How the display price was resolved. Wave 33."},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"category":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"],"description":"Product category summary"},"image":{"type":"object","nullable":true,"properties":{"url":{"type":"string"},"alt":{"type":"string","nullable":true},"thumbnailUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp","description":"150px WebP thumbnail (pre-gen R2 URL; cdn-cgi fallback or null when not yet generated)"},"mediumUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_medium.webp","description":"400px WebP medium (pre-gen R2 URL; cdn-cgi fallback or null when not yet generated)"},"largeUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_large.webp","description":"800px WebP large (pre-gen R2 URL; cdn-cgi fallback or null when not yet generated)"},"variants":{"type":"object","nullable":true,"properties":{"thumbnail":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"150px (square) WebP + AVIF"},"medium":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"400px WebP + AVIF"},"large":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"800px WebP + AVIF"},"xlarge":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_xlarge.webp"}},"required":["webp"],"description":"1280px retina WebP (no AVIF, cost bound)"}},"required":["thumbnail","medium","large","xlarge"],"description":"Pre-generated R2 variant URLs (webp+avif per size + webp-only xlarge). Null/absent until generated."},"variantsGeneratedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z","description":"When the pre-gen R2 derivatives were generated (null/absent = not yet; cdn-cgi fallback)."}},"required":["url","alt"],"description":"Primary product image"},"variantCount":{"type":"integer","example":3,"description":"Number of variants"},"requiresAgeVerification":{"type":"boolean","example":false,"description":"SUP-0: 18+ age-verification gate flag for the storefront."}},"required":["id","name","slug","content","status","type","price","compareAtPrice","sku","stock","categoryId","currency","createdAt","updatedAt","category","image","variantCount","requiresAgeVerification"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"},"nextCursor":{"type":"string","nullable":true,"example":"eyJ0Ijoi...","description":"Signed cursor for the next page (null = last page)."}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/products/{slug}":{"get":{"tags":["Storefront"],"summary":"Get a public product by slug (storefront)","description":"Public, tenant-scoped product detail by slug (or id) for the storefront PDP. Returns variants, images, category, and Wave 33 resolved price. Only active products are returned.","parameters":[{"schema":{"type":"string","minLength":1,"example":"bluetooth-speaker"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","minLength":3,"maxLength":3,"example":"EUR","description":"ISO 4217 code for display price resolution. Wave 33."},"required":false,"description":"ISO 4217 code for display price resolution. Wave 33.","name":"display_currency","in":"query"}],"responses":{"200":{"description":"Product detail with variants, images, and category","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"T-Shirt"},"slug":{"type":"string","example":"t-shirt"},"content":{"type":"string","nullable":true,"example":"A great t-shirt"},"status":{"type":"string","enum":["active","draft","archived"],"example":"active"},"type":{"type":"string","enum":["simple","configurable","bundle","grouped","virtual","downloadable","gift_card","subscription"],"example":"simple","description":"Product type. Digital types (virtual/downloadable/gift_card/subscription) trigger post-payment fulfilment."},"price":{"type":"integer","minimum":0,"example":2999,"description":"Price in cents"},"compareAtPrice":{"type":"integer","nullable":true,"minimum":0,"example":3999},"sku":{"type":"string","nullable":true,"example":"TSH-001"},"stock":{"type":"integer","minimum":0,"example":100},"categoryId":{"type":"string","nullable":true,"example":"cat_01"},"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"ISO 4217 currency code of the resolved display price"},"basePrice":{"type":"integer","minimum":0,"example":2999,"description":"Base price in tenant currency (cents). Wave 33."},"baseCurrency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"Tenant base currency. Wave 33."},"priceSource":{"type":"string","enum":["explicit","converted","base"],"example":"explicit","description":"How the display price was resolved. Wave 33."},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"var_01"},"productId":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","nullable":true,"minimum":0,"example":3499,"description":"Override price in cents"},"stock":{"type":"integer","minimum":0,"example":25},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"attributes":{"type":"array","items":{"type":"object","properties":{"attributeName":{"type":"string","example":"Color"},"attributeValue":{"type":"string","example":"Blue"}},"required":["attributeName","attributeValue"]},"description":"Variant attribute values"}},"required":["id","productId","name","sku","price","stock","position","createdAt","updatedAt","attributes"]},"description":"Product variants with attributes"},"images":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"img_01"},"productId":{"type":"string","example":"prod_01"},"variantId":{"type":"string","nullable":true,"example":null},"url":{"type":"string","example":"https://cdn.example.com/tshirt.jpg"},"thumbnailUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp","description":"150px WebP thumbnail (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"mediumUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_medium.webp","description":"400px WebP medium (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"largeUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_large.webp","description":"800px WebP large (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"variants":{"type":"object","nullable":true,"properties":{"thumbnail":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"150px (square) WebP + AVIF"},"medium":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"400px WebP + AVIF"},"large":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"800px WebP + AVIF"},"xlarge":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_xlarge.webp"}},"required":["webp"],"description":"1280px retina WebP (no AVIF, cost bound)"}},"required":["thumbnail","medium","large","xlarge"],"description":"Pre-generated R2 variant URLs (webp + avif per size). Null/absent until generated; legacy thumbnail/medium/large URLs then carry the cdn-cgi fallback."},"variantsGeneratedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z","description":"When the 6 pre-gen R2 derivatives were generated (null/absent = not yet; using cdn-cgi fallback)."},"alt":{"type":"string","nullable":true,"example":"T-Shirt front view"},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","productId","variantId","url","thumbnailUrl","mediumUrl","largeUrl","alt","position","createdAt","updatedAt"]},"description":"Product images"},"category":{"type":"object","nullable":true,"properties":{"id":{"type":"string","example":"cat_01"},"name":{"type":"string","example":"Clothing"},"slug":{"type":"string","example":"clothing"},"parentId":{"type":"string","nullable":true,"example":null},"description":{"type":"string","nullable":true,"example":"All clothing items"},"imageUrl":{"type":"string","nullable":true,"example":null},"position":{"type":"integer","example":0}},"required":["id","name","slug","parentId","description","imageUrl","position"],"description":"Legacy single category (deprecated — use categories[])."},"categories":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"cat_01"},"name":{"type":"string","example":"Clothing"},"slug":{"type":"string","example":"clothing"},"parentId":{"type":"string","nullable":true,"example":null},"description":{"type":"string","nullable":true,"example":"All clothing items"},"imageUrl":{"type":"string","nullable":true,"example":null},"position":{"type":"integer","example":0}},"required":["id","name","slug","parentId","description","imageUrl","position"]},"description":"All category associations (N:N)."},"configurableAttributes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"ca_01"},"productId":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"color"},"label":{"type":"string","example":"Color"},"values":{"type":"array","items":{"type":"string"},"example":["Red","Blue","Green"],"description":"Possible attribute values"},"position":{"type":"integer","example":0}},"required":["id","productId","name","label","values","position"]},"description":"Product-level attribute definitions"},"greenClaims":{"$ref":"#/components/schemas/GreenClaimsGateSummary"},"requiresAgeVerification":{"type":"boolean","example":false,"description":"SUP-0: 18+ age-verification gate flag for the storefront."}},"required":["id","name","slug","content","status","type","price","compareAtPrice","sku","stock","categoryId","currency","createdAt","updatedAt","variants","images","category","requiresAgeVerification"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/seo-redirects/resolve":{"get":{"tags":["Catalog","Storefront"],"summary":"Resolve a migrated/manual SEO redirect by exact source path","description":"Point-read of the tenant seo_redirects table (populated by the store migrator and manual entries). Returns the redirect target and HTTP status, or 404 when no redirect exists for the path.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":2048,"pattern":"^\\/","example":"/123-vestido-flores.html"},"required":true,"name":"path","in":"query"}],"responses":{"200":{"description":"Redirect found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeoRedirectResolution"}}}},"404":{"description":"No redirect registered for this path"},"422":{"description":"Invalid query"}}}},"/v1/storefront/theme":{"get":{"tags":["Storefront","Settings"],"summary":"Get tenant theme tokens (public)","description":"Returns the persisted theme tokens for the current tenant. Public endpoint used by the storefront SSR to inject the theme inline. Resolves the tenant from `X-Tenant-ID` header or the subdomain. Includes `theme_version` so callers can build a stable cache key.","responses":{"200":{"description":"Theme tokens","content":{"application/json":{"schema":{"type":"object","properties":{"theme":{"$ref":"#/components/schemas/ThemeTokens"},"isDefault":{"type":"boolean","example":false},"theme_version":{"type":"integer","minimum":0,"example":1716120000000}},"required":["theme","isDefault","theme_version"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}}}}},"/v1/storefront/theme/preview-session/{token}":{"get":{"tags":["Storefront","Settings"],"summary":"Resolve a theme-preview snapshot (public)","description":"Returns the draft theme tokens stored for a preview session. Public endpoint consumed SERVER-SIDE by the storefront `/preview/theme` route — the opaque token is the credential (read-only theme tokens, no PII). The tenant resolved from the request must match the tenant that created the session. Expired/unknown tokens → 404.","parameters":[{"schema":{"type":"string","minLength":16,"maxLength":64,"example":"2kD1x9uYpQnLg4bZfW0Hqw"},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"Draft theme tokens","content":{"application/json":{"schema":{"type":"object","properties":{"theme":{"$ref":"#/components/schemas/ThemeTokens"},"expiresAt":{"type":"string","example":"2026-07-08T12:15:00.000Z"}},"required":["theme","expiresAt"]}}}},"404":{"description":"Session not found, expired, or belongs to another tenant","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"503":{"description":"Preview-session store unavailable (no KV binding)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}}}}},"/v1/storefront/exporta":{"get":{"tags":["Storefront","Settings"],"summary":"Get Exporta settings (public storefront read)","description":"Public endpoint used by the storefront SSR/BFF to resolve which locales the store serves, which display currencies the switcher offers, and how to render taxes. Tenant resolved from `X-Tenant-ID` / subdomain. Cached 5 minutes.","responses":{"200":{"description":"Exporta settings","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ExportaSettings"}},"required":["data"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/storefront/products/{id}/reviews":{"get":{"tags":["Reviews","Storefront"],"summary":"List approved reviews for a product (public)","description":"Public, approved-only, paginated list of reviews for a product. Ordered by most recent.","parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Approved reviews","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListReviewsResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}}}},"post":{"tags":["Reviews","Storefront"],"summary":"Submit a product review (verified purchasers only)","description":"Authenticated customers who have a paid order containing the product may submit a review. The review is created with status=pending for moderation and verifiedPurchase=true. Customers without a qualifying paid order receive 403.","parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReview"}}}},"responses":{"201":{"description":"Review created (pending moderation)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Review"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}},"403":{"description":"Not a verified purchaser","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}},"409":{"description":"Customer already reviewed this product","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}}}}},"/v1/storefront/products/{id}/reviews/summary":{"get":{"tags":["Reviews","Storefront"],"summary":"Aggregate rating summary for a product (public)","description":"Returns count + average + per-star breakdown over APPROVED reviews. Consumed by the storefront PDP to emit a real Schema.org AggregateRating and by ProductCard to show the rating. Average is 0 when there are no approved reviews.","parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Rating summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewSummary"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}}}}},"/v1/storefront/contact":{"post":{"tags":["Storefront","Contact"],"summary":"Submit a contact-form inquiry","description":"Public endpoint (guest + customer) for the storefront contact form. Persists the inquiry in the tenant DB and best-effort enqueues a notification email to the tenant support inbox. Never fails the request when email infrastructure is absent.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitContact"}}}},"responses":{"201":{"description":"Inquiry received","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactReceived"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactProblem"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactProblem"}}}}}}},"/v1/audit-logs":{"get":{"tags":["Audit Logs"],"summary":"List audit log entries with filtering + pagination","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"actor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"action","in":"query"},{"schema":{"type":"string"},"required":false,"name":"resource","in":"query"},{"schema":{"type":"string","enum":["info","warn","critical"]},"required":false,"name":"severity","in":"query"},{"schema":{"type":"string"},"required":false,"name":"date_from","in":"query"},{"schema":{"type":"string"},"required":false,"name":"date_to","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ip","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"required":false,"name":"search","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Paginated list of audit log entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLogList"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/audit-logs/export":{"get":{"tags":["Audit Logs"],"summary":"Export audit logs as CSV or JSON","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"actor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"action","in":"query"},{"schema":{"type":"string"},"required":false,"name":"resource","in":"query"},{"schema":{"type":"string","enum":["info","warn","critical"]},"required":false,"name":"severity","in":"query"},{"schema":{"type":"string"},"required":false,"name":"date_from","in":"query"},{"schema":{"type":"string"},"required":false,"name":"date_to","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ip","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","enum":["csv","json"],"default":"csv"},"required":false,"name":"format","in":"query"}],"responses":{"200":{"description":"Streamed CSV or JSON","content":{"text/csv":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/audit-logs/stream":{"get":{"tags":["Audit Logs"],"summary":"Real-time stream of audit log events (Server-Sent Events)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["info","warn","critical"]},"required":false,"name":"severity","in":"query"},{"schema":{"type":"string"},"required":false,"name":"action","in":"query"},{"schema":{"type":"string"},"required":false,"name":"resource","in":"query"}],"responses":{"200":{"description":"SSE stream — emits `event: audit` frames with audit log JSON.","content":{"text/event-stream":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/alert-rules":{"get":{"tags":["Alert Rules"],"summary":"List alert rules","description":"Returns all alert rules configured for the current tenant.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Alert rules list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRuleList"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Alert Rules"],"summary":"Create alert rule","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAlertRuleBody"}}}},"responses":{"201":{"description":"Alert rule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRule"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/alert-rules/{id}":{"patch":{"tags":["Alert Rules"],"summary":"Update alert rule","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"alr_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAlertRuleBody"}}}},"responses":{"200":{"description":"Alert rule updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRule"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Alert Rules"],"summary":"Delete alert rule","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"alr_a1b2c3d4e5f6"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/legal/acceptances":{"get":{"tags":["Legal"],"summary":"List recorded legal acceptances (admin)","description":"Paginated evidence log of accepted legal documents. Filterable by order or checkout. Lazily back-fills `order_id` from confirmed checkouts before listing.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"order_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"checkout_id","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Paginated acceptances","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"scope":{"type":"string"},"checkoutId":{"type":"string","nullable":true},"orderId":{"type":"string","nullable":true},"customerId":{"type":"string","nullable":true},"docSlug":{"type":"string"},"docVersion":{"type":"string"},"acceptedAt":{"type":"number"},"ipHash":{"type":"string","nullable":true},"userAgent":{"type":"string","nullable":true}},"required":["id","scope","checkoutId","orderId","customerId","docSlug","docVersion","acceptedAt","ipHash","userAgent"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings/legal/generate":{"post":{"tags":["Legal"],"summary":"Generate / refresh the Spanish legal CMS pages for the tenant","description":"Creates or updates the 4 legal pages (aviso-legal, privacidad, cookies, devoluciones) with LSSI-CE / RGPD / consumer-law compliant Spanish templates, interpolating the merchant data. Idempotent: re-running updates the existing pages in place (matched by slug) without duplicates. Persistence mirrors the pages module (sanitized HTML, unique slug, published status).","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"razon_social":{"type":"string","minLength":2,"maxLength":200},"cif":{"type":"string","minLength":8,"maxLength":20},"domicilio":{"type":"string","minLength":5,"maxLength":300},"email":{"type":"string","format":"email"},"telefono":{"type":"string","minLength":5,"maxLength":30},"registro_mercantil":{"type":"string","minLength":2,"maxLength":300},"version":{"type":"string","minLength":1,"maxLength":32}},"required":["razon_social","cif","domicilio","email"]}}}},"responses":{"200":{"description":"Pages generated/updated","content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"string"},"pages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"action":{"type":"string","enum":["created","updated"]}},"required":["id","slug","title","action"]}}},"required":["version","pages"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/saved-reports":{"get":{"tags":["Saved Reports"],"summary":"List saved reports","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"per_page","in":"query"},{"schema":{"type":"string","enum":["order_stats","product_stats","customer_ltv","inventory","custom"]},"required":false,"name":"report_type","in":"query"}],"responses":{"200":{"description":"List of saved reports","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SavedReport"}},"total":{"type":"integer"},"page":{"type":"integer"},"per_page":{"type":"integer"}},"required":["data","total","page","per_page"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Saved Reports"],"summary":"Create a saved report","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200,"example":"Monthly Revenue"},"description":{"type":"string","maxLength":500,"example":"Revenue by day for the last month"},"report_type":{"type":"string","enum":["order_stats","product_stats","customer_ltv","inventory","custom"],"example":"order_stats"},"filters":{"type":"object","additionalProperties":{"nullable":true},"example":{"status":"completed"}},"columns":{"type":"array","items":{"type":"string"},"example":["date","revenue_cents"]},"format":{"type":"string","enum":["csv","json","xlsx","pdf"],"default":"csv"},"is_shared":{"type":"integer","minimum":0,"maximum":1,"default":0}},"required":["name","report_type"]}}}},"responses":{"201":{"description":"Report created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SavedReport"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/saved-reports/:id":{"patch":{"tags":["Saved Reports"],"summary":"Update a saved report","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200,"example":"Monthly Revenue"},"description":{"type":"string","maxLength":500,"example":"Revenue by day for the last month"},"report_type":{"type":"string","enum":["order_stats","product_stats","customer_ltv","inventory","custom"],"example":"order_stats"},"filters":{"type":"object","additionalProperties":{"nullable":true},"example":{"status":"completed"}},"columns":{"type":"array","items":{"type":"string"},"example":["date","revenue_cents"]},"format":{"type":"string","enum":["csv","json","xlsx","pdf"],"default":"csv"},"is_shared":{"type":"integer","minimum":0,"maximum":1,"default":0}}}}}},"responses":{"200":{"description":"Report updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SavedReport"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Saved Reports"],"summary":"Delete a saved report","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/saved-reports/:id/execute":{"post":{"tags":["Saved Reports"],"summary":"Execute a saved report (async)","description":"Enqueues report execution. Returns execution ID immediately; poll /executions/:execId for status.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"202":{"description":"Execution accepted","content":{"application/json":{"schema":{"type":"object","properties":{"execution_id":{"type":"string"},"status":{"type":"string","enum":["pending"]}},"required":["execution_id","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/saved-reports/:id/executions":{"get":{"tags":["Saved Reports"],"summary":"List executions for a report","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"per_page","in":"query"},{"schema":{"type":"string","enum":["pending","running","completed","failed"]},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"List of executions","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ReportExecution"}},"total":{"type":"integer"},"page":{"type":"integer"},"per_page":{"type":"integer"}},"required":["data","total","page","per_page"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Report not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/saved-reports/:id/executions/:execId":{"get":{"tags":["Saved Reports"],"summary":"Get a single execution","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"execId","in":"path"}],"responses":{"200":{"description":"Execution detail","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ReportExecution"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/saved-reports/:id/schedule":{"get":{"tags":["Saved Reports"],"summary":"Get schedule for a report","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Schedule","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ReportSchedule"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Report not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"put":{"tags":["Saved Reports"],"summary":"Create or update schedule for a report","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"cron":{"type":"string","minLength":1,"example":"0 9 * * 1"},"recipients":{"type":"array","items":{"type":"string","format":"email"},"minItems":1,"example":["owner@store.com"]},"is_active":{"type":"integer","minimum":0,"maximum":1,"default":1}},"required":["cron","recipients"]}}}},"responses":{"200":{"description":"Schedule upserted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ReportSchedule"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Report not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Saved Reports"],"summary":"Delete schedule for a report","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/products/:productId/metafields":{"get":{"tags":["Product Metafields"],"summary":"List product metafields","description":"Lists custom metafields for a product. RBAC: read (staff).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"productId","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9_.-]+$","description":"Filter to a single namespace","example":"specs"},"required":false,"description":"Filter to a single namespace","name":"namespace","in":"query"}],"responses":{"200":{"description":"Metafields","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Metafield"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Owner not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"put":{"tags":["Product Metafields"],"summary":"Upsert a product metafield","description":"Creates or updates a single metafield keyed by (namespace, key). Idempotent on the unique (owner, namespace, key) index. RBAC: write (staff).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"productId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"namespace":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9_.-]+$","example":"specs"},"key":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9_.-]+$","example":"material"},"value":{"type":"string","nullable":true,"example":"aluminium"},"type":{"type":"string","enum":["string","integer","number","boolean","json","date","url","color","money","rich_text"],"default":"string"}},"required":["namespace","key"]}}}},"responses":{"200":{"description":"Metafield upserted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Metafield"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Owner not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/:productId/metafields/bulk":{"post":{"tags":["Product Metafields"],"summary":"Bulk-upsert product metafields","description":"Sets many metafields at once (up to 250). RBAC: write (staff).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"productId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"metafields":{"type":"array","items":{"type":"object","properties":{"namespace":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9_.-]+$"},"key":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9_.-]+$"},"value":{"type":"string","nullable":true},"type":{"type":"string","enum":["string","integer","number","boolean","json","date","url","color","money","rich_text"],"default":"string"}},"required":["namespace","key"]},"minItems":1,"maxItems":250}},"required":["metafields"]}}}},"responses":{"200":{"description":"Metafields upserted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Metafield"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Owner not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/:productId/metafields/:namespace/:key":{"delete":{"tags":["Product Metafields"],"summary":"Delete a product metafield","description":"Deletes a single metafield by (namespace, key). RBAC: write (staff).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"productId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"namespace","in":"path"},{"schema":{"type":"string"},"required":true,"name":"key","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/:customerId/metafields":{"get":{"tags":["Customer Metafields"],"summary":"List customer metafields","description":"Lists custom metafields for a customer. RBAC: read (staff).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"customerId","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9_.-]+$","description":"Filter to a single namespace","example":"specs"},"required":false,"description":"Filter to a single namespace","name":"namespace","in":"query"}],"responses":{"200":{"description":"Metafields","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Metafield"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Owner not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"put":{"tags":["Customer Metafields"],"summary":"Upsert a customer metafield","description":"Creates or updates a single metafield keyed by (namespace, key). Idempotent on the unique (owner, namespace, key) index. RBAC: write (staff).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"customerId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"namespace":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9_.-]+$","example":"specs"},"key":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9_.-]+$","example":"material"},"value":{"type":"string","nullable":true,"example":"aluminium"},"type":{"type":"string","enum":["string","integer","number","boolean","json","date","url","color","money","rich_text"],"default":"string"}},"required":["namespace","key"]}}}},"responses":{"200":{"description":"Metafield upserted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Metafield"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Owner not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/:customerId/metafields/bulk":{"post":{"tags":["Customer Metafields"],"summary":"Bulk-upsert customer metafields","description":"Sets many metafields at once (up to 250). RBAC: write (staff).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"customerId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"metafields":{"type":"array","items":{"type":"object","properties":{"namespace":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9_.-]+$"},"key":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9_.-]+$"},"value":{"type":"string","nullable":true},"type":{"type":"string","enum":["string","integer","number","boolean","json","date","url","color","money","rich_text"],"default":"string"}},"required":["namespace","key"]},"minItems":1,"maxItems":250}},"required":["metafields"]}}}},"responses":{"200":{"description":"Metafields upserted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Metafield"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Owner not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/:customerId/metafields/:namespace/:key":{"delete":{"tags":["Customer Metafields"],"summary":"Delete a customer metafield","description":"Deletes a single metafield by (namespace, key). RBAC: write (staff).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"customerId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"namespace","in":"path"},{"schema":{"type":"string"},"required":true,"name":"key","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/export":{"get":{"tags":["Products"],"summary":"Export products as CSV","description":"Export products with optional filters. Returns a CSV file download.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["active","draft","archived"],"description":"Filter by product status"},"required":false,"description":"Filter by product status","name":"status","in":"query"},{"schema":{"type":"string","description":"Filter by category ID"},"required":false,"description":"Filter by category ID","name":"categoryId","in":"query"},{"schema":{"type":"string","enum":["csv"],"default":"csv","description":"Export format"},"required":false,"description":"Export format","name":"format","in":"query"}],"responses":{"200":{"description":"CSV file"},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products":{"get":{"tags":["Products"],"summary":"List products","parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","example":"eyJ0Ijoi...","description":"Signed keyset cursor (O(1) deep pagination). Overrides page when present."},"required":false,"description":"Signed keyset cursor (O(1) deep pagination). Overrides page when present.","name":"cursor","in":"query"},{"schema":{"type":"string","example":"shirt"},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","enum":["active","draft","archived"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","example":"cat_01"},"required":false,"name":"category_id","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"example":1000,"description":"Minimum price in cents"},"required":false,"description":"Minimum price in cents","name":"min_price","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"example":5000,"description":"Maximum price in cents"},"required":false,"description":"Maximum price in cents","name":"max_price","in":"query"},{"schema":{"type":"string","minLength":3,"maxLength":3,"example":"EUR","description":"ISO 4217 code for display price resolution"},"required":false,"description":"ISO 4217 code for display price resolution","name":"display_currency","in":"query"}],"responses":{"200":{"description":"List of products","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"T-Shirt"},"slug":{"type":"string","example":"t-shirt"},"content":{"type":"string","nullable":true,"example":"A great t-shirt"},"status":{"type":"string","enum":["active","draft","archived"],"example":"active"},"type":{"type":"string","enum":["simple","configurable","bundle","grouped","virtual","downloadable","gift_card","subscription"],"example":"simple","description":"Product type. Digital types (virtual/downloadable/gift_card/subscription) trigger post-payment fulfilment."},"price":{"type":"integer","minimum":0,"example":2999,"description":"Price in cents"},"compareAtPrice":{"type":"integer","nullable":true,"minimum":0,"example":3999},"sku":{"type":"string","nullable":true,"example":"TSH-001"},"stock":{"type":"integer","minimum":0,"example":100},"categoryId":{"type":"string","nullable":true,"example":"cat_01"},"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"ISO 4217 currency code of the resolved display price"},"basePrice":{"type":"integer","minimum":0,"example":2999,"description":"Base price in tenant currency (cents). Wave 33."},"baseCurrency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"Tenant base currency. Wave 33."},"priceSource":{"type":"string","enum":["explicit","converted","base"],"example":"explicit","description":"How the display price was resolved. Wave 33."},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"category":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"],"description":"Product category summary"},"image":{"type":"object","nullable":true,"properties":{"url":{"type":"string"},"alt":{"type":"string","nullable":true},"thumbnailUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp","description":"150px WebP thumbnail (pre-gen R2 URL; cdn-cgi fallback or null when not yet generated)"},"mediumUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_medium.webp","description":"400px WebP medium (pre-gen R2 URL; cdn-cgi fallback or null when not yet generated)"},"largeUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_large.webp","description":"800px WebP large (pre-gen R2 URL; cdn-cgi fallback or null when not yet generated)"},"variants":{"type":"object","nullable":true,"properties":{"thumbnail":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"150px (square) WebP + AVIF"},"medium":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"400px WebP + AVIF"},"large":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"800px WebP + AVIF"},"xlarge":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_xlarge.webp"}},"required":["webp"],"description":"1280px retina WebP (no AVIF, cost bound)"}},"required":["thumbnail","medium","large","xlarge"],"description":"Pre-generated R2 variant URLs (webp+avif per size + webp-only xlarge). Null/absent until generated."},"variantsGeneratedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z","description":"When the pre-gen R2 derivatives were generated (null/absent = not yet; cdn-cgi fallback)."}},"required":["url","alt"],"description":"Primary product image"},"variantCount":{"type":"integer","example":3,"description":"Number of variants"}},"required":["id","name","slug","content","status","type","price","compareAtPrice","sku","stock","categoryId","currency","createdAt","updatedAt","category","image","variantCount"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"},"nextCursor":{"type":"string","nullable":true,"example":"eyJ0Ijoi...","description":"Signed cursor for the next page (null = last page)."}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"400":{"description":"Bad request (e.g. invalid/tampered cursor)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Products"],"summary":"Create a product","description":"Creates a new product with optional variants and tags. Validates against plan limits.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"T-Shirt"},"slug":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[a-z0-9-]+$","example":"t-shirt","description":"URL slug (auto-generated from name if omitted)"},"content":{"type":"string","example":"A great t-shirt"},"status":{"type":"string","enum":["active","draft","archived"],"default":"draft","example":"draft"},"type":{"type":"string","enum":["simple","configurable","bundle","grouped","virtual","downloadable","gift_card","subscription"],"default":"simple","example":"simple","description":"Product type (8 supported, incl. digital types)."},"price":{"type":"integer","minimum":0,"example":2999},"compareAtPrice":{"type":"integer","minimum":0,"example":3999},"sku":{"type":"string","example":"TSH-001"},"stock":{"type":"integer","minimum":0,"default":0,"example":100},"weight":{"type":"integer","minimum":0,"example":500,"description":"Weight in weight_unit"},"weightUnit":{"type":"string","enum":["g","kg","lb","oz"],"default":"g","example":"g"},"lowStockThreshold":{"type":"integer","minimum":0,"default":5,"example":5},"backorderEnabled":{"type":"boolean","default":false,"example":false},"categoryId":{"type":"string","example":"cat_01"},"categoryIds":{"type":"array","items":{"type":"string"},"description":"Category IDs for M:N assignment"},"variants":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Large / Blue"},"sku":{"type":"string","example":"TSH-001-L-BL"},"price":{"type":"integer","minimum":0,"example":3499,"description":"Override price in cents"},"stock":{"type":"integer","minimum":0,"default":0,"example":25},"position":{"type":"integer","minimum":0,"default":0,"example":0},"attributes":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Color"},"value":{"type":"string","minLength":1,"maxLength":255,"example":"Blue"}},"required":["name","value"]},"description":"Variant attributes"}},"required":["name"]},"description":"Product variants to create"},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"description":"Product tags"},"dppGtin":{"type":"string","nullable":true,"pattern":"^\\d{8}$|^\\d{12}$|^\\d{13}$|^\\d{14}$","example":"04006381333931","description":"GS1 GTIN-8/12/13/14 (digits only). N8."},"dppMaterials":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","nullable":true},"percentage":{"type":"number","nullable":true},"recyclable":{"type":"boolean","nullable":true},"recycled":{"type":"boolean","nullable":true}},"additionalProperties":{"nullable":true}}},{"type":"string"},{"nullable":true}],"example":[{"name":"Organic cotton","percentage":100,"recyclable":true}],"description":"Material composition. Array or JSON string; stored as JSON text. N8."},"dppRecyclability":{"type":"string","nullable":true,"example":"100","description":"Recyclability description or score. N8."},"dppRepairabilityScore":{"type":"integer","nullable":true,"minimum":0,"maximum":100,"example":72,"description":"EU repairability index score (0–100). N8."},"dppCarbonFootprintGrams":{"type":"integer","nullable":true,"minimum":0,"example":3200,"description":"Carbon footprint in grams CO2e (cradle-to-gate). N8."},"dppCertifications":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"string"},{"nullable":true}],"example":["GOTS","EU Ecolabel"],"description":"Certifications. Array of strings or JSON string; stored as JSON text. N8."},"dppCountryOfAssembly":{"type":"string","nullable":true,"pattern":"^[A-Za-z]{2}$","example":"PT","description":"ISO 3166-1 alpha-2 country of final assembly. N8."}},"required":["name","price"]}}}},"responses":{"201":{"description":"Product created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"T-Shirt"},"slug":{"type":"string","example":"t-shirt"},"content":{"type":"string","nullable":true,"example":"A great t-shirt"},"status":{"type":"string","enum":["active","draft","archived"],"example":"active"},"type":{"type":"string","enum":["simple","configurable","bundle","grouped","virtual","downloadable","gift_card","subscription"],"example":"simple","description":"Product type. Digital types (virtual/downloadable/gift_card/subscription) trigger post-payment fulfilment."},"price":{"type":"integer","minimum":0,"example":2999,"description":"Price in cents"},"compareAtPrice":{"type":"integer","nullable":true,"minimum":0,"example":3999},"sku":{"type":"string","nullable":true,"example":"TSH-001"},"stock":{"type":"integer","minimum":0,"example":100},"categoryId":{"type":"string","nullable":true,"example":"cat_01"},"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"ISO 4217 currency code of the resolved display price"},"basePrice":{"type":"integer","minimum":0,"example":2999,"description":"Base price in tenant currency (cents). Wave 33."},"baseCurrency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"Tenant base currency. Wave 33."},"priceSource":{"type":"string","enum":["explicit","converted","base"],"example":"explicit","description":"How the display price was resolved. Wave 33."},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"var_01"},"productId":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","nullable":true,"minimum":0,"example":3499,"description":"Override price in cents"},"stock":{"type":"integer","minimum":0,"example":25},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"attributes":{"type":"array","items":{"type":"object","properties":{"attributeName":{"type":"string","example":"Color"},"attributeValue":{"type":"string","example":"Blue"}},"required":["attributeName","attributeValue"]},"description":"Variant attribute values"}},"required":["id","productId","name","sku","price","stock","position","createdAt","updatedAt","attributes"]},"description":"Product variants with attributes"},"images":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"img_01"},"productId":{"type":"string","example":"prod_01"},"variantId":{"type":"string","nullable":true,"example":null},"url":{"type":"string","example":"https://cdn.example.com/tshirt.jpg"},"thumbnailUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp","description":"150px WebP thumbnail (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"mediumUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_medium.webp","description":"400px WebP medium (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"largeUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_large.webp","description":"800px WebP large (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"variants":{"type":"object","nullable":true,"properties":{"thumbnail":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"150px (square) WebP + AVIF"},"medium":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"400px WebP + AVIF"},"large":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"800px WebP + AVIF"},"xlarge":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_xlarge.webp"}},"required":["webp"],"description":"1280px retina WebP (no AVIF, cost bound)"}},"required":["thumbnail","medium","large","xlarge"],"description":"Pre-generated R2 variant URLs (webp + avif per size). Null/absent until generated; legacy thumbnail/medium/large URLs then carry the cdn-cgi fallback."},"variantsGeneratedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z","description":"When the 6 pre-gen R2 derivatives were generated (null/absent = not yet; using cdn-cgi fallback)."},"alt":{"type":"string","nullable":true,"example":"T-Shirt front view"},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","productId","variantId","url","thumbnailUrl","mediumUrl","largeUrl","alt","position","createdAt","updatedAt"]},"description":"Product images"},"category":{"type":"object","nullable":true,"properties":{"id":{"type":"string","example":"cat_01"},"name":{"type":"string","example":"Clothing"},"slug":{"type":"string","example":"clothing"},"parentId":{"type":"string","nullable":true,"example":null},"description":{"type":"string","nullable":true,"example":"All clothing items"},"imageUrl":{"type":"string","nullable":true,"example":null},"position":{"type":"integer","example":0}},"required":["id","name","slug","parentId","description","imageUrl","position"],"description":"Legacy single category (deprecated — use categories[])."},"categories":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"cat_01"},"name":{"type":"string","example":"Clothing"},"slug":{"type":"string","example":"clothing"},"parentId":{"type":"string","nullable":true,"example":null},"description":{"type":"string","nullable":true,"example":"All clothing items"},"imageUrl":{"type":"string","nullable":true,"example":null},"position":{"type":"integer","example":0}},"required":["id","name","slug","parentId","description","imageUrl","position"]},"description":"All category associations (N:N)."},"configurableAttributes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"ca_01"},"productId":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"color"},"label":{"type":"string","example":"Color"},"values":{"type":"array","items":{"type":"string"},"example":["Red","Blue","Green"],"description":"Possible attribute values"},"position":{"type":"integer","example":0}},"required":["id","productId","name","label","values","position"]},"description":"Product-level attribute definitions"},"greenClaims":{"$ref":"#/components/schemas/GreenClaimsGateSummary"}},"required":["id","name","slug","content","status","type","price","compareAtPrice","sku","stock","categoryId","currency","createdAt","updatedAt","variants","images","category"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Plan limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error, or unsubstantiated green claims when publishing with compliance.green_claims_mode=enforce (type: green-claims-unsubstantiated)","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},{"$ref":"#/components/schemas/GreenClaimsProblem"}]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{id}":{"get":{"tags":["Products"],"summary":"Get product by ID or slug","description":"Returns full product details including variants, images, and category. Accepts product ID (prod_xxx) or slug.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":3,"maxLength":3,"example":"EUR","description":"ISO 4217 code for display price resolution. Wave 33."},"required":false,"description":"ISO 4217 code for display price resolution. Wave 33.","name":"display_currency","in":"query"}],"responses":{"200":{"description":"Product details with variants, images, and category","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"T-Shirt"},"slug":{"type":"string","example":"t-shirt"},"content":{"type":"string","nullable":true,"example":"A great t-shirt"},"status":{"type":"string","enum":["active","draft","archived"],"example":"active"},"type":{"type":"string","enum":["simple","configurable","bundle","grouped","virtual","downloadable","gift_card","subscription"],"example":"simple","description":"Product type. Digital types (virtual/downloadable/gift_card/subscription) trigger post-payment fulfilment."},"price":{"type":"integer","minimum":0,"example":2999,"description":"Price in cents"},"compareAtPrice":{"type":"integer","nullable":true,"minimum":0,"example":3999},"sku":{"type":"string","nullable":true,"example":"TSH-001"},"stock":{"type":"integer","minimum":0,"example":100},"categoryId":{"type":"string","nullable":true,"example":"cat_01"},"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"ISO 4217 currency code of the resolved display price"},"basePrice":{"type":"integer","minimum":0,"example":2999,"description":"Base price in tenant currency (cents). Wave 33."},"baseCurrency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"Tenant base currency. Wave 33."},"priceSource":{"type":"string","enum":["explicit","converted","base"],"example":"explicit","description":"How the display price was resolved. Wave 33."},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"var_01"},"productId":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","nullable":true,"minimum":0,"example":3499,"description":"Override price in cents"},"stock":{"type":"integer","minimum":0,"example":25},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"attributes":{"type":"array","items":{"type":"object","properties":{"attributeName":{"type":"string","example":"Color"},"attributeValue":{"type":"string","example":"Blue"}},"required":["attributeName","attributeValue"]},"description":"Variant attribute values"}},"required":["id","productId","name","sku","price","stock","position","createdAt","updatedAt","attributes"]},"description":"Product variants with attributes"},"images":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"img_01"},"productId":{"type":"string","example":"prod_01"},"variantId":{"type":"string","nullable":true,"example":null},"url":{"type":"string","example":"https://cdn.example.com/tshirt.jpg"},"thumbnailUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp","description":"150px WebP thumbnail (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"mediumUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_medium.webp","description":"400px WebP medium (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"largeUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_large.webp","description":"800px WebP large (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"variants":{"type":"object","nullable":true,"properties":{"thumbnail":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"150px (square) WebP + AVIF"},"medium":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"400px WebP + AVIF"},"large":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"800px WebP + AVIF"},"xlarge":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_xlarge.webp"}},"required":["webp"],"description":"1280px retina WebP (no AVIF, cost bound)"}},"required":["thumbnail","medium","large","xlarge"],"description":"Pre-generated R2 variant URLs (webp + avif per size). Null/absent until generated; legacy thumbnail/medium/large URLs then carry the cdn-cgi fallback."},"variantsGeneratedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z","description":"When the 6 pre-gen R2 derivatives were generated (null/absent = not yet; using cdn-cgi fallback)."},"alt":{"type":"string","nullable":true,"example":"T-Shirt front view"},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","productId","variantId","url","thumbnailUrl","mediumUrl","largeUrl","alt","position","createdAt","updatedAt"]},"description":"Product images"},"category":{"type":"object","nullable":true,"properties":{"id":{"type":"string","example":"cat_01"},"name":{"type":"string","example":"Clothing"},"slug":{"type":"string","example":"clothing"},"parentId":{"type":"string","nullable":true,"example":null},"description":{"type":"string","nullable":true,"example":"All clothing items"},"imageUrl":{"type":"string","nullable":true,"example":null},"position":{"type":"integer","example":0}},"required":["id","name","slug","parentId","description","imageUrl","position"],"description":"Legacy single category (deprecated — use categories[])."},"categories":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"cat_01"},"name":{"type":"string","example":"Clothing"},"slug":{"type":"string","example":"clothing"},"parentId":{"type":"string","nullable":true,"example":null},"description":{"type":"string","nullable":true,"example":"All clothing items"},"imageUrl":{"type":"string","nullable":true,"example":null},"position":{"type":"integer","example":0}},"required":["id","name","slug","parentId","description","imageUrl","position"]},"description":"All category associations (N:N)."},"configurableAttributes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"ca_01"},"productId":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"color"},"label":{"type":"string","example":"Color"},"values":{"type":"array","items":{"type":"string"},"example":["Red","Blue","Green"],"description":"Possible attribute values"},"position":{"type":"integer","example":0}},"required":["id","productId","name","label","values","position"]},"description":"Product-level attribute definitions"},"greenClaims":{"$ref":"#/components/schemas/GreenClaimsGateSummary"}},"required":["id","name","slug","content","status","type","price","compareAtPrice","sku","stock","categoryId","currency","createdAt","updatedAt","variants","images","category"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Products"],"summary":"Update a product","description":"Partially updates a product. Only provided fields are changed. Triggers search index update if name, content, or price changed.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"T-Shirt"},"slug":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[a-z0-9-]+$","example":"t-shirt"},"content":{"type":"string","example":"A great t-shirt"},"status":{"type":"string","enum":["active","draft","archived"],"example":"active"},"type":{"type":"string","enum":["simple","configurable","bundle","grouped","virtual","downloadable","gift_card","subscription"],"example":"simple","description":"Product type (8 supported, incl. digital types)."},"price":{"type":"integer","minimum":0,"example":2999},"compareAtPrice":{"type":"integer","nullable":true,"minimum":0,"example":3999},"sku":{"type":"string","nullable":true,"example":"TSH-001"},"stock":{"type":"integer","minimum":0,"example":100},"weight":{"type":"integer","nullable":true,"minimum":0,"example":500},"weightUnit":{"type":"string","enum":["g","kg","lb","oz"],"example":"g"},"lowStockThreshold":{"type":"integer","minimum":0,"example":5},"backorderEnabled":{"type":"boolean","example":false},"categoryId":{"type":"string","nullable":true,"example":"cat_01"},"categoryIds":{"type":"array","items":{"type":"string"},"description":"Category IDs for M:N assignment"},"dppGtin":{"type":"string","nullable":true,"pattern":"^\\d{8}$|^\\d{12}$|^\\d{13}$|^\\d{14}$","example":"04006381333931","description":"GS1 GTIN-8/12/13/14 (digits only). N8."},"dppMaterials":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","nullable":true},"percentage":{"type":"number","nullable":true},"recyclable":{"type":"boolean","nullable":true},"recycled":{"type":"boolean","nullable":true}},"additionalProperties":{"nullable":true}}},{"type":"string"},{"nullable":true}],"example":[{"name":"Organic cotton","percentage":100,"recyclable":true}],"description":"Material composition. Array or JSON string; stored as JSON text. N8."},"dppRecyclability":{"type":"string","nullable":true,"example":"100","description":"Recyclability description or score. N8."},"dppRepairabilityScore":{"type":"integer","nullable":true,"minimum":0,"maximum":100,"example":72,"description":"EU repairability index score (0–100). N8."},"dppCarbonFootprintGrams":{"type":"integer","nullable":true,"minimum":0,"example":3200,"description":"Carbon footprint in grams CO2e (cradle-to-gate). N8."},"dppCertifications":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"string"},{"nullable":true}],"example":["GOTS","EU Ecolabel"],"description":"Certifications. Array of strings or JSON string; stored as JSON text. N8."},"dppCountryOfAssembly":{"type":"string","nullable":true,"pattern":"^[A-Za-z]{2}$","example":"PT","description":"ISO 3166-1 alpha-2 country of final assembly. N8."}}}}}},"responses":{"200":{"description":"Product updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"T-Shirt"},"slug":{"type":"string","example":"t-shirt"},"content":{"type":"string","nullable":true,"example":"A great t-shirt"},"status":{"type":"string","enum":["active","draft","archived"],"example":"active"},"type":{"type":"string","enum":["simple","configurable","bundle","grouped","virtual","downloadable","gift_card","subscription"],"example":"simple","description":"Product type. Digital types (virtual/downloadable/gift_card/subscription) trigger post-payment fulfilment."},"price":{"type":"integer","minimum":0,"example":2999,"description":"Price in cents"},"compareAtPrice":{"type":"integer","nullable":true,"minimum":0,"example":3999},"sku":{"type":"string","nullable":true,"example":"TSH-001"},"stock":{"type":"integer","minimum":0,"example":100},"categoryId":{"type":"string","nullable":true,"example":"cat_01"},"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"ISO 4217 currency code of the resolved display price"},"basePrice":{"type":"integer","minimum":0,"example":2999,"description":"Base price in tenant currency (cents). Wave 33."},"baseCurrency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"Tenant base currency. Wave 33."},"priceSource":{"type":"string","enum":["explicit","converted","base"],"example":"explicit","description":"How the display price was resolved. Wave 33."},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"var_01"},"productId":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","nullable":true,"minimum":0,"example":3499,"description":"Override price in cents"},"stock":{"type":"integer","minimum":0,"example":25},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"attributes":{"type":"array","items":{"type":"object","properties":{"attributeName":{"type":"string","example":"Color"},"attributeValue":{"type":"string","example":"Blue"}},"required":["attributeName","attributeValue"]},"description":"Variant attribute values"}},"required":["id","productId","name","sku","price","stock","position","createdAt","updatedAt","attributes"]},"description":"Product variants with attributes"},"images":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"img_01"},"productId":{"type":"string","example":"prod_01"},"variantId":{"type":"string","nullable":true,"example":null},"url":{"type":"string","example":"https://cdn.example.com/tshirt.jpg"},"thumbnailUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp","description":"150px WebP thumbnail (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"mediumUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_medium.webp","description":"400px WebP medium (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"largeUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_large.webp","description":"800px WebP large (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"variants":{"type":"object","nullable":true,"properties":{"thumbnail":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"150px (square) WebP + AVIF"},"medium":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"400px WebP + AVIF"},"large":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"800px WebP + AVIF"},"xlarge":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_xlarge.webp"}},"required":["webp"],"description":"1280px retina WebP (no AVIF, cost bound)"}},"required":["thumbnail","medium","large","xlarge"],"description":"Pre-generated R2 variant URLs (webp + avif per size). Null/absent until generated; legacy thumbnail/medium/large URLs then carry the cdn-cgi fallback."},"variantsGeneratedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z","description":"When the 6 pre-gen R2 derivatives were generated (null/absent = not yet; using cdn-cgi fallback)."},"alt":{"type":"string","nullable":true,"example":"T-Shirt front view"},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","productId","variantId","url","thumbnailUrl","mediumUrl","largeUrl","alt","position","createdAt","updatedAt"]},"description":"Product images"},"category":{"type":"object","nullable":true,"properties":{"id":{"type":"string","example":"cat_01"},"name":{"type":"string","example":"Clothing"},"slug":{"type":"string","example":"clothing"},"parentId":{"type":"string","nullable":true,"example":null},"description":{"type":"string","nullable":true,"example":"All clothing items"},"imageUrl":{"type":"string","nullable":true,"example":null},"position":{"type":"integer","example":0}},"required":["id","name","slug","parentId","description","imageUrl","position"],"description":"Legacy single category (deprecated — use categories[])."},"categories":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"cat_01"},"name":{"type":"string","example":"Clothing"},"slug":{"type":"string","example":"clothing"},"parentId":{"type":"string","nullable":true,"example":null},"description":{"type":"string","nullable":true,"example":"All clothing items"},"imageUrl":{"type":"string","nullable":true,"example":null},"position":{"type":"integer","example":0}},"required":["id","name","slug","parentId","description","imageUrl","position"]},"description":"All category associations (N:N)."},"configurableAttributes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"ca_01"},"productId":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"color"},"label":{"type":"string","example":"Color"},"values":{"type":"array","items":{"type":"string"},"example":["Red","Blue","Green"],"description":"Possible attribute values"},"position":{"type":"integer","example":0}},"required":["id","productId","name","label","values","position"]},"description":"Product-level attribute definitions"},"greenClaims":{"$ref":"#/components/schemas/GreenClaimsGateSummary"}},"required":["id","name","slug","content","status","type","price","compareAtPrice","sku","stock","categoryId","currency","createdAt","updatedAt","variants","images","category"]}}}},"400":{"description":"Bad request (duplicate slug)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error, or unsubstantiated green claims when the resulting status is active with compliance.green_claims_mode=enforce (type: green-claims-unsubstantiated)","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},{"$ref":"#/components/schemas/GreenClaimsProblem"}]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Products"],"summary":"Delete a product","description":"Soft-deletes a product by setting its status to archived. Returns 409 if the product has active (non-completed, non-cancelled) orders.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Product deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Product has active orders","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/bulk-status":{"post":{"tags":["Products"],"summary":"Bulk update product status","description":"Updates the status of multiple products at once. All product IDs must belong to the current tenant.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":100,"example":["prod_01","prod_02"]},"status":{"type":"string","enum":["active","draft","archived"],"example":"active","description":"New status for the products"}},"required":["ids","status"]}}}},"responses":{"200":{"description":"Products updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"updated":{"type":"integer","minimum":0,"example":5,"description":"Number of products updated"},"greenClaims":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string"},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/GreenClaimWarning"}}},"required":["productId","warnings"]},"description":"Green-claims lint summary (warn mode, activation only): products whose copy makes environmental claims not substantiated by their DPP."}},"required":["updated"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error, or unsubstantiated green claims when activating with compliance.green_claims_mode=enforce (type: green-claims-unsubstantiated; no product is updated)","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},{"$ref":"#/components/schemas/GreenClaimsProblem"}]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{productId}/variants":{"post":{"tags":["Products"],"summary":"Create a product variant","description":"Adds a new variant to an existing product. Validates SKU uniqueness within the tenant.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"productId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Large / Blue"},"sku":{"type":"string","example":"TSH-001-L-BL"},"price":{"type":"integer","minimum":0,"example":3499,"description":"Override price in cents"},"stock":{"type":"integer","minimum":0,"default":0,"example":25},"position":{"type":"integer","minimum":0,"default":0,"example":0},"attributes":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Color"},"value":{"type":"string","minLength":1,"maxLength":255,"example":"Blue"}},"required":["name","value"]},"description":"Variant attributes"}},"required":["name"]}}}},"responses":{"201":{"description":"Variant created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"var_01"},"productId":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","nullable":true,"minimum":0,"example":3499,"description":"Override price in cents"},"stock":{"type":"integer","minimum":0,"example":25},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"attributes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"va_01"},"variantId":{"type":"string","example":"var_01"},"attributeName":{"type":"string","example":"Color"},"attributeValue":{"type":"string","example":"Blue"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","variantId","attributeName","attributeValue","createdAt","updatedAt"]},"description":"Variant attributes"}},"required":["id","productId","name","sku","price","stock","position","createdAt","updatedAt","attributes"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Duplicate SKU","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{productId}/variants/{variantId}":{"patch":{"tags":["Products"],"summary":"Update a product variant","description":"Updates an existing variant's price, stock, attributes, or other fields.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"productId","in":"path"},{"schema":{"type":"string","minLength":1,"example":"var_01"},"required":true,"name":"variantId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","nullable":true,"minimum":0,"example":3499,"description":"Override price in cents"},"stock":{"type":"integer","minimum":0,"example":25},"position":{"type":"integer","minimum":0,"example":0},"attributes":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Color"},"value":{"type":"string","minLength":1,"maxLength":255,"example":"Blue"}},"required":["name","value"]},"description":"Replace variant attributes"}}}}}},"responses":{"200":{"description":"Variant updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"var_01"},"productId":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","nullable":true,"minimum":0,"example":3499,"description":"Override price in cents"},"stock":{"type":"integer","minimum":0,"example":25},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"attributes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"va_01"},"variantId":{"type":"string","example":"var_01"},"attributeName":{"type":"string","example":"Color"},"attributeValue":{"type":"string","example":"Blue"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","variantId","attributeName","attributeValue","createdAt","updatedAt"]},"description":"Variant attributes"}},"required":["id","productId","name","sku","price","stock","position","createdAt","updatedAt","attributes"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product or variant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Duplicate SKU","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Products"],"summary":"Delete a product variant","description":"Removes a variant from a product. Cannot delete if it is the only variant.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"productId","in":"path"},{"schema":{"type":"string","minLength":1,"example":"var_01"},"required":true,"name":"variantId","in":"path"}],"responses":{"204":{"description":"Variant deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product or variant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Cannot delete the only variant","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{productId}/images":{"post":{"tags":["Products"],"summary":"Upload product image","description":"Uploads an image to R2 and associates it with the product.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"productId","in":"path"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"},"alt":{"type":"string","example":"Product front view"}}}}}},"responses":{"201":{"description":"Image uploaded","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"img_01"},"productId":{"type":"string","example":"prod_01"},"variantId":{"type":"string","nullable":true,"example":null},"url":{"type":"string","example":"https://cdn.example.com/tshirt.jpg"},"thumbnailUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp","description":"150px WebP thumbnail (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"mediumUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_medium.webp","description":"400px WebP medium (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"largeUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_large.webp","description":"800px WebP large (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"variants":{"type":"object","nullable":true,"properties":{"thumbnail":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"150px (square) WebP + AVIF"},"medium":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"400px WebP + AVIF"},"large":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"800px WebP + AVIF"},"xlarge":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_xlarge.webp"}},"required":["webp"],"description":"1280px retina WebP (no AVIF, cost bound)"}},"required":["thumbnail","medium","large","xlarge"],"description":"Pre-generated R2 variant URLs (webp + avif per size). Null/absent until generated; legacy thumbnail/medium/large URLs then carry the cdn-cgi fallback."},"variantsGeneratedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z","description":"When the 6 pre-gen R2 derivatives were generated (null/absent = not yet; using cdn-cgi fallback)."},"alt":{"type":"string","nullable":true,"example":"T-Shirt front view"},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","productId","variantId","url","thumbnailUrl","mediumUrl","largeUrl","alt","position","createdAt","updatedAt"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{productId}/images/reorder":{"patch":{"tags":["Products"],"summary":"Reorder product images","description":"Updates the display order of product images based on the ordered array of image IDs.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"productId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"imageIds":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"example":["img_01","img_02","img_03"],"description":"Ordered array of image IDs — index becomes new position"}},"required":["imageIds"]}}}},"responses":{"200":{"description":"Images reordered successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"reordered":{"type":"integer","example":3}},"required":["success","reordered"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Image IDs do not match expected set","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{productId}/images/{imageId}":{"delete":{"tags":["Products"],"summary":"Delete product image","description":"Removes an image from R2 storage and the database, then reorders remaining images.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"productId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"imageId","in":"path"}],"responses":{"204":{"description":"Image deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product or image not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{productId}/bundle-items":{"get":{"tags":["Products"],"summary":"List bundle items","description":"Returns all items in a bundle product, ordered by position.","parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"productId","in":"path"}],"responses":{"200":{"description":"List of bundle items","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"bundleProductId":{"type":"string"},"productId":{"type":"string"},"productName":{"type":"string"},"productPrice":{"type":"number"},"quantity":{"type":"number"},"position":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","bundleProductId","productId","productName","productPrice","quantity","position","createdAt","updatedAt"]}}},"required":["data"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Products"],"summary":"Add a bundle item","description":"Adds a product to a bundle. The parent product must be of type \"bundle\".","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"productId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"productId":{"type":"string","minLength":1,"description":"ID of the product to add to the bundle","example":"prod_02"},"quantity":{"type":"integer","minimum":1,"default":1,"description":"Quantity of this product in the bundle","example":1}},"required":["productId"]}}}},"responses":{"201":{"description":"Bundle item created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"bundleProductId":{"type":"string"},"productId":{"type":"string"},"productName":{"type":"string"},"productPrice":{"type":"number"},"quantity":{"type":"number"},"position":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","bundleProductId","productId","productName","productPrice","quantity","position","createdAt","updatedAt"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Duplicate product in bundle","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{productId}/bundle-items/{bundleItemId}":{"patch":{"tags":["Products"],"summary":"Update a bundle item","description":"Updates the quantity or position of a bundle item.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"productId","in":"path"},{"schema":{"type":"string","minLength":1,"example":"bi_01"},"required":true,"name":"bundleItemId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"quantity":{"type":"integer","minimum":1,"description":"Quantity of this product in the bundle","example":2},"position":{"type":"integer","minimum":0,"description":"Display position within the bundle","example":1}}}}}},"responses":{"200":{"description":"Bundle item updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"bundleProductId":{"type":"string"},"productId":{"type":"string"},"productName":{"type":"string"},"productPrice":{"type":"number"},"quantity":{"type":"number"},"position":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","bundleProductId","productId","productName","productPrice","quantity","position","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product or bundle item not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Products"],"summary":"Delete a bundle item","description":"Removes a product from a bundle.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"productId","in":"path"},{"schema":{"type":"string","minLength":1,"example":"bi_01"},"required":true,"name":"bundleItemId","in":"path"}],"responses":{"204":{"description":"Bundle item deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product or bundle item not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{id}/duplicate":{"post":{"tags":["Products"],"summary":"Duplicate a product","description":"Creates a deep copy of a product including variants, attributes, images, tags, and related records. The copy is set to draft status with zeroed stock.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"id","in":"path"}],"responses":{"201":{"description":"Product duplicated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"T-Shirt"},"slug":{"type":"string","example":"t-shirt"},"content":{"type":"string","nullable":true,"example":"A great t-shirt"},"status":{"type":"string","enum":["active","draft","archived"],"example":"active"},"type":{"type":"string","enum":["simple","configurable","bundle","grouped","virtual","downloadable","gift_card","subscription"],"example":"simple","description":"Product type. Digital types (virtual/downloadable/gift_card/subscription) trigger post-payment fulfilment."},"price":{"type":"integer","minimum":0,"example":2999,"description":"Price in cents"},"compareAtPrice":{"type":"integer","nullable":true,"minimum":0,"example":3999},"sku":{"type":"string","nullable":true,"example":"TSH-001"},"stock":{"type":"integer","minimum":0,"example":100},"categoryId":{"type":"string","nullable":true,"example":"cat_01"},"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"ISO 4217 currency code of the resolved display price"},"basePrice":{"type":"integer","minimum":0,"example":2999,"description":"Base price in tenant currency (cents). Wave 33."},"baseCurrency":{"type":"string","minLength":3,"maxLength":3,"example":"USD","description":"Tenant base currency. Wave 33."},"priceSource":{"type":"string","enum":["explicit","converted","base"],"example":"explicit","description":"How the display price was resolved. Wave 33."},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"var_01"},"productId":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","nullable":true,"minimum":0,"example":3499,"description":"Override price in cents"},"stock":{"type":"integer","minimum":0,"example":25},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"attributes":{"type":"array","items":{"type":"object","properties":{"attributeName":{"type":"string","example":"Color"},"attributeValue":{"type":"string","example":"Blue"}},"required":["attributeName","attributeValue"]},"description":"Variant attribute values"}},"required":["id","productId","name","sku","price","stock","position","createdAt","updatedAt","attributes"]},"description":"Product variants with attributes"},"images":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"img_01"},"productId":{"type":"string","example":"prod_01"},"variantId":{"type":"string","nullable":true,"example":null},"url":{"type":"string","example":"https://cdn.example.com/tshirt.jpg"},"thumbnailUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp","description":"150px WebP thumbnail (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"mediumUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_medium.webp","description":"400px WebP medium (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"largeUrl":{"type":"string","nullable":true,"example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_large.webp","description":"800px WebP large (pre-gen R2 URL; cdn-cgi transform URL when not yet generated)"},"variants":{"type":"object","nullable":true,"properties":{"thumbnail":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"150px (square) WebP + AVIF"},"medium":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"400px WebP + AVIF"},"large":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.webp"},"avif":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_thumb.avif"}},"required":["webp","avif"],"description":"800px WebP + AVIF"},"xlarge":{"type":"object","properties":{"webp":{"type":"string","example":"https://cdn.inaishop.com/tenant/products/prod_01/img_01_xlarge.webp"}},"required":["webp"],"description":"1280px retina WebP (no AVIF, cost bound)"}},"required":["thumbnail","medium","large","xlarge"],"description":"Pre-generated R2 variant URLs (webp + avif per size). Null/absent until generated; legacy thumbnail/medium/large URLs then carry the cdn-cgi fallback."},"variantsGeneratedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z","description":"When the 6 pre-gen R2 derivatives were generated (null/absent = not yet; using cdn-cgi fallback)."},"alt":{"type":"string","nullable":true,"example":"T-Shirt front view"},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","productId","variantId","url","thumbnailUrl","mediumUrl","largeUrl","alt","position","createdAt","updatedAt"]},"description":"Product images"},"category":{"type":"object","nullable":true,"properties":{"id":{"type":"string","example":"cat_01"},"name":{"type":"string","example":"Clothing"},"slug":{"type":"string","example":"clothing"},"parentId":{"type":"string","nullable":true,"example":null},"description":{"type":"string","nullable":true,"example":"All clothing items"},"imageUrl":{"type":"string","nullable":true,"example":null},"position":{"type":"integer","example":0}},"required":["id","name","slug","parentId","description","imageUrl","position"],"description":"Legacy single category (deprecated — use categories[])."},"categories":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"cat_01"},"name":{"type":"string","example":"Clothing"},"slug":{"type":"string","example":"clothing"},"parentId":{"type":"string","nullable":true,"example":null},"description":{"type":"string","nullable":true,"example":"All clothing items"},"imageUrl":{"type":"string","nullable":true,"example":null},"position":{"type":"integer","example":0}},"required":["id","name","slug","parentId","description","imageUrl","position"]},"description":"All category associations (N:N)."},"configurableAttributes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"ca_01"},"productId":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"color"},"label":{"type":"string","example":"Color"},"values":{"type":"array","items":{"type":"string"},"example":["Red","Blue","Green"],"description":"Possible attribute values"},"position":{"type":"integer","example":0}},"required":["id","productId","name","label","values","position"]},"description":"Product-level attribute definitions"},"greenClaims":{"$ref":"#/components/schemas/GreenClaimsGateSummary"}},"required":["id","name","slug","content","status","type","price","compareAtPrice","sku","stock","categoryId","currency","createdAt","updatedAt","variants","images","category"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{id}/stock-history":{"get":{"tags":["Products"],"summary":"Get stock movement history","description":"Returns paginated stock movement history for a product, filterable by type and date range.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prod_01"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["sale","return","adjustment","import","cancellation"],"example":"sale","description":"Filter by movement type"},"required":false,"description":"Filter by movement type","name":"type","in":"query"},{"schema":{"type":"string","example":"2026-01-01","description":"Start date (ISO format)"},"required":false,"description":"Start date (ISO format)","name":"from","in":"query"},{"schema":{"type":"string","example":"2026-12-31","description":"End date (ISO format)"},"required":false,"description":"End date (ISO format)","name":"to","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Stock movement history","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"productId":{"type":"string"},"variantId":{"type":"string","nullable":true},"type":{"type":"string","enum":["sale","return","adjustment","import","cancellation"]},"quantity":{"type":"integer"},"previousStock":{"type":"integer"},"newStock":{"type":"integer"},"orderId":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","productId","variantId","type","quantity","previousStock","newStock","orderId","note","createdAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{id}/prices":{"get":{"tags":["Products","Multi-currency"],"summary":"List explicit prices for a product","description":"Returns all explicit currency prices for a product. Use ?variantId= to scope to a specific variant.","parameters":[{"schema":{"type":"string","example":"prod_01"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","example":"var_01","description":"Filter by variant ID"},"required":false,"description":"Filter by variant ID","name":"variantId","in":"query"}],"responses":{"200":{"description":"List of product prices","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"pp_01"},"productId":{"type":"string","nullable":true,"example":"prod_01"},"variantId":{"type":"string","nullable":true,"example":null},"currency":{"type":"string","minLength":3,"maxLength":3,"example":"EUR"},"price":{"type":"integer","example":2750,"description":"Price in cents"},"compareAtPrice":{"type":"integer","nullable":true,"example":3200},"createdAt":{"type":"number","example":1700000000},"updatedAt":{"type":"number","example":1700000000}},"required":["id","productId","variantId","currency","price","compareAtPrice","createdAt","updatedAt"]}}},"required":["data"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"put":{"tags":["Products","Multi-currency"],"summary":"Set (upsert) an explicit price for a product","description":"Upserts an explicit price entry for the given product and currency. Requires products.write permission.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"prod_01"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3,"example":"EUR","description":"ISO 4217 currency code"},"price":{"type":"integer","minimum":0,"example":2750,"description":"Price in cents"},"compareAtPrice":{"type":"integer","minimum":0,"example":3200},"variantId":{"type":"string","example":"var_01","description":"Set to scope to a variant"}},"required":["currency","price"]}}}},"responses":{"200":{"description":"Price upserted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"productId":{"type":"string","nullable":true},"variantId":{"type":"string","nullable":true},"currency":{"type":"string"},"price":{"type":"integer"},"compareAtPrice":{"type":"integer","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","productId","variantId","currency","price","compareAtPrice","createdAt","updatedAt"]}},"required":["data"]}}}},"400":{"description":"Invalid currency","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{id}/prices/{currency}":{"delete":{"tags":["Products","Multi-currency"],"summary":"Delete an explicit price for a product","description":"Deletes the explicit price entry for the given product and currency. Use ?variantId= to scope to a variant.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"prod_01"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":3,"maxLength":3,"example":"EUR"},"required":true,"name":"currency","in":"path"},{"schema":{"type":"string","example":"var_01"},"required":false,"name":"variantId","in":"query"}],"responses":{"204":{"description":"Price deleted"},"404":{"description":"Price not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{id}/prices/bulk":{"post":{"tags":["Products","Multi-currency"],"summary":"Bulk upsert prices for a product","description":"Upserts up to 200 explicit price entries for the given product in one request.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"prod_01"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"prices":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3,"example":"EUR"},"price":{"type":"integer","minimum":0,"example":2750},"compareAtPrice":{"type":"integer","minimum":0,"example":3200},"variantId":{"type":"string","example":"var_01"}},"required":["currency","price"]},"minItems":1,"maxItems":200}},"required":["prices"]}}}},"responses":{"200":{"description":"Bulk upsert result","content":{"application/json":{"schema":{"type":"object","properties":{"inserted":{"type":"integer"},"updated":{"type":"integer"},"errors":{"type":"array","items":{"type":"object","properties":{"index":{"type":"number"},"detail":{"type":"string"}},"required":["index","detail"]}}},"required":["inserted","updated","errors"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/prices/bulk-import":{"post":{"tags":["Products","Multi-currency"],"summary":"Bulk import product prices from CSV","description":"Accepts a multipart CSV with columns: product_sku, variant_sku, currency, price, compare_at_price. Upserts all rows.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"CSV file"}},"required":["file"]}}}},"responses":{"200":{"description":"Import result","content":{"application/json":{"schema":{"type":"object","properties":{"imported":{"type":"integer"},"updated":{"type":"integer"},"errors":{"type":"array","items":{"type":"object","properties":{"row":{"type":"integer"},"detail":{"type":"string"}},"required":["row","detail"]}}},"required":["imported","updated","errors"]}}}},"400":{"description":"Invalid CSV","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation errors","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/images/backfill-variants":{"post":{"tags":["Products"],"summary":"Backfill pre-generated image variants (queue-driven)","description":"Enqueues one IMAGE_VARIANTS_QUEUE message per addressable product image that has not yet had its 6 pre-gen R2 derivatives generated. The queue consumer does the encoding asynchronously. External/non-R2 images are marked terminal and excluded. Idempotent + resumable — call repeatedly until `remaining` is 0.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":500,"default":100,"example":100,"description":"Max images to claim + enqueue per call (1–500). Generation runs in the queue consumer (NOT this request), so the batch can be large — call repeatedly until `remaining` is 0."},"required":false,"description":"Max images to claim + enqueue per call (1–500). Generation runs in the queue consumer (NOT this request), so the batch can be large — call repeatedly until `remaining` is 0.","name":"limit","in":"query"}],"responses":{"200":{"description":"Batch claimed + enqueued","content":{"application/json":{"schema":{"type":"object","properties":{"enqueued":{"type":"integer","example":100,"description":"Addressable images enqueued for async variant generation this batch (one message each)."},"markedTerminal":{"type":"integer","example":3,"description":"Images marked permanently unavailable (external/non-R2 URL) — excluded from future claims + remaining."},"remaining":{"type":"integer","example":1240,"description":"Eligible images still pending generation after this batch (excludes generated + terminal rows)."}},"required":["enqueued","markedTerminal","remaining"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{id}/dpp":{"get":{"tags":["Products"],"summary":"Digital Product Passport (DPP)","description":"Public, tenant-scoped EU Digital Product Passport for a product (GTIN, materials, recyclability, repairability, carbon footprint, certifications, origin/assembly, HS code). Designed to be served behind a QR code. Only active products are returned.","parameters":[{"schema":{"type":"string","example":"prod_01"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Digital Product Passport","content":{"application/json":{"schema":{"type":"object","properties":{"productId":{"type":"string","example":"prod_01"},"name":{"type":"string","example":"Organic Cotton Tee"},"slug":{"type":"string","example":"organic-cotton-tee"},"sku":{"type":"string","nullable":true,"example":"TEE-ORG-M"},"gtin":{"type":"string","nullable":true,"example":"04006381333931"},"materials":{"type":"array","nullable":true,"items":{"type":"object","properties":{"name":{"type":"string","nullable":true},"percentage":{"type":"number","nullable":true},"recyclable":{"type":"boolean","nullable":true},"recycled":{"type":"boolean","nullable":true}},"additionalProperties":{"nullable":true}},"example":[{"name":"Organic cotton","percentage":100,"recyclable":true}]},"recyclability":{"type":"string","nullable":true,"example":"Widely recyclable (score 95)"},"repairabilityScore":{"type":"integer","nullable":true,"example":72},"carbonFootprintGrams":{"type":"integer","nullable":true,"example":3200,"description":"Grams CO2e (cradle-to-gate)"},"certifications":{"type":"array","nullable":true,"items":{"type":"string"},"example":["GOTS","EU Ecolabel"]},"countryOfOrigin":{"type":"string","nullable":true,"example":"PT","description":"ISO 3166-1 alpha-2"},"countryOfAssembly":{"type":"string","nullable":true,"example":"PT","description":"ISO 3166-1 alpha-2"},"hsCode":{"type":"string","nullable":true,"example":"6109100010","description":"Harmonized System commodity code"},"completeness":{"type":"object","properties":{"score":{"type":"integer","minimum":0,"maximum":100,"example":78,"description":"Percentage of DPP fields filled"},"filled":{"type":"array","items":{"type":"string"},"example":["gtin","materials","countryOfOrigin"]},"missing":{"type":"array","items":{"type":"string"},"example":["carbonFootprintGrams","certifications"]}},"required":["score","filled","missing"],"description":"How complete this passport is (0-100 + per-field breakdown)."}},"required":["productId","name","slug","sku","gtin","materials","recyclability","repairabilityScore","carbonFootprintGrams","certifications","countryOfOrigin","countryOfAssembly","hsCode","completeness"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{id}/dpp-qr":{"get":{"tags":["Products"],"summary":"Digital Product Passport QR code (SVG)","description":"SVG QR code pointing at the product's public storefront passport URL (/products/{slug}/passport on the tenant domain). Admin-only (read permission) — intended for packaging artwork and the product editor preview.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"prod_01"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"SVG QR code for the public passport URL","content":{"image/svg+xml":{"schema":{"type":"string","example":"<svg …>"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/products/{id}/green-claims":{"post":{"tags":["Products"],"summary":"Validate green claims (EU Green Claims / ECGT)","description":"Scans product copy for environmental claims (eco-friendly, sustainable, 100% recyclable, carbon neutral, biodegradable, etc.) and flags any not substantiated by the product DPP. Admin-only.","parameters":[{"schema":{"type":"string","example":"prod_01"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"copy":{"type":"string","example":"Our 100% recyclable, carbon neutral, eco-friendly tee.","description":"Marketing copy to validate. Defaults to the product name + content when omitted."},"dpp":{"$ref":"#/components/schemas/GreenClaimsDppOverride"}}}}}},"responses":{"200":{"description":"Validation result","content":{"application/json":{"schema":{"type":"object","properties":{"productId":{"type":"string"},"compliant":{"type":"boolean","description":"True when no unsupported claim was found."},"detectedClaims":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"phrase":{"type":"string"},"supported":{"type":"boolean"}},"required":["kind","phrase","supported"]}},"warnings":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"phrase":{"type":"string"},"severity":{"type":"string","enum":["error","warning"]},"message":{"type":"string"},"evidenceNeeded":{"type":"string"},"suggestion":{"type":"string"}},"required":["kind","phrase","severity","message","evidenceNeeded","suggestion"]}}},"required":["productId","compliant","detectedClaims","warnings"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/stats":{"get":{"tags":["Orders"],"summary":"Get order statistics","description":"Returns aggregated order statistics for the dashboard with period-over-period trends. With `expanded=true`, also returns conversionRate/topProduct (from the product_stats_monthly CQRS read-model), refundRate (order_stats_daily) and cartAbandonmentRate (behavioral events).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["today","week","month","year","7d","30d","90d","12m"],"default":"month","example":"month","description":"Time period for stats aggregation (calendar or rolling window)"},"required":false,"description":"Time period for stats aggregation (calendar or rolling window)","name":"period","in":"query"},{"schema":{"type":"string","enum":["true","false"],"example":"true","description":"When true, adds the expanded dashboard KPIs (customerCount, conversionRate, refundRate, topProduct, cartAbandonmentRate) computed from the CQRS read-models + behavioral events."},"required":false,"description":"When true, adds the expanded dashboard KPIs (customerCount, conversionRate, refundRate, topProduct, cartAbandonmentRate) computed from the CQRS read-models + behavioral events.","name":"expanded","in":"query"}],"responses":{"200":{"description":"Order statistics","content":{"application/json":{"schema":{"type":"object","properties":{"totalRevenue":{"type":"integer","example":125000,"description":"Total revenue in cents for the period"},"orderCount":{"type":"integer","example":42,"description":"Number of orders in the period"},"averageOrderValue":{"type":"integer","example":2976,"description":"Average order value in cents"},"previousRevenue":{"type":"integer","example":100000,"description":"Total revenue in cents for the previous period"},"previousOrderCount":{"type":"integer","example":35,"description":"Number of orders in the previous period"},"previousAverageOrderValue":{"type":"integer","example":2857,"description":"Average order value in cents for the previous period"},"revenueTrend":{"type":"number","example":25,"description":"Percentage change in revenue vs previous period"},"orderCountTrend":{"type":"number","example":20,"description":"Percentage change in order count vs previous period"},"averageOrderValueTrend":{"type":"number","example":4.17,"description":"Percentage change in AOV vs previous period"},"customerCount":{"type":"integer","example":120,"description":"Total customers (expanded only)"},"conversionRate":{"type":"number","example":12.5,"description":"View→order conversion %, from the product_stats_monthly read-model (expanded only)"},"refundRate":{"type":"number","example":1.8,"description":"Refunds/orders %, from the order_stats_daily read-model (expanded only)"},"topProduct":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"revenue":{"type":"integer"},"quantity":{"type":"integer"}},"required":["id","name","revenue","quantity"],"description":"Best-selling product for the period, from product_stats_monthly (expanded only)"},"cartAbandonmentRate":{"type":"number","example":65.2,"description":"CartAdded→OrderPlaced abandonment %, from behavioral events (expanded only)"}},"required":["totalRevenue","orderCount","averageOrderValue","previousRevenue","previousOrderCount","previousAverageOrderValue","revenueTrend","orderCountTrend","averageOrderValueTrend"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/stats/by-status":{"get":{"tags":["Orders"],"summary":"Get order counts grouped by status","description":"Returns the current order distribution by status for the dashboard \"Orders by status\" chart. Sourced directly from the tenant orders table (no analytics engine dependency).","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Orders grouped by status with counts and share-of-total.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string"},"count":{"type":"number"},"percentage":{"type":"number"}},"required":["status","count","percentage"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/stats/top-products":{"get":{"tags":["Orders"],"summary":"Get top-selling products by revenue","description":"Returns the top products by revenue for the dashboard \"Top products\" chart, aggregated from order_items over the requested period. Excludes cancelled / refunded / failed orders. Sourced directly from the tenant DB.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["today","week","month","year","all"],"default":"month"},"required":false,"name":"period","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":5},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Top products by revenue.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"revenue":{"type":"number"},"quantity":{"type":"number"},"image":{"type":"string","nullable":true}},"required":["id","name","revenue","quantity","image"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/timeseries":{"get":{"tags":["Orders"],"summary":"Get order time-series data","description":"Returns daily revenue and order count data for a given period.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["7d","30d","90d"],"default":"30d","example":"30d","description":"Time period for time-series data"},"required":false,"description":"Time period for time-series data","name":"period","in":"query"}],"responses":{"200":{"description":"Order time-series data","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","example":"2025-01-15","description":"Date in YYYY-MM-DD format"},"revenue":{"type":"integer","example":12500,"description":"Revenue in cents"},"orderCount":{"type":"integer","example":5,"description":"Number of orders"}},"required":["date","revenue","orderCount"]}},"period":{"type":"string"}},"required":["data","period"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders":{"get":{"tags":["Orders"],"summary":"List orders","description":"Returns paginated orders for the current tenant with optional filtering by status, date range, and customer.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","example":"eyJ0Ijoi...","description":"Signed keyset cursor (O(1) deep pagination). Overrides page when present."},"required":false,"description":"Signed keyset cursor (O(1) deep pagination). Overrides page when present.","name":"cursor","in":"query"},{"schema":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"],"example":"pending"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","example":"2025-01-01","description":"Filter orders created on or after this date (YYYY-MM-DD)"},"required":false,"description":"Filter orders created on or after this date (YYYY-MM-DD)","name":"dateFrom","in":"query"},{"schema":{"type":"string","example":"2025-12-31","description":"Filter orders created on or before this date (YYYY-MM-DD)"},"required":false,"description":"Filter orders created on or before this date (YYYY-MM-DD)","name":"dateTo","in":"query"},{"schema":{"type":"string","example":"cust_01","description":"Filter by customer ID"},"required":false,"description":"Filter by customer ID","name":"customerId","in":"query"},{"schema":{"type":"string","example":"john","description":"Search by customer name or email"},"required":false,"description":"Search by customer name or email","name":"customerSearch","in":"query"}],"responses":{"200":{"description":"Paginated list of orders","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"ord_01"},"customerId":{"type":"string","nullable":true,"example":"cust_01"},"customerName":{"type":"string","nullable":true,"example":"John Doe"},"customerEmail":{"type":"string","nullable":true,"example":"john@example.com"},"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"],"example":"pending"},"total":{"type":"integer","example":6498},"currency":{"type":"string","example":"USD"},"paymentStatus":{"type":"string","nullable":true,"enum":["pending","processing","succeeded","failed","cancelled","refunded",null],"example":"pending"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","customerId","customerName","customerEmail","status","total","currency","paymentStatus","createdAt","updatedAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"},"nextCursor":{"type":"string","nullable":true,"example":"eyJ0Ijoi...","description":"Signed cursor for the next page (null = last page)."}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"400":{"description":"Bad request (e.g. invalid/tampered cursor)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Orders"],"summary":"Create an order","description":"Creates a new order with line items. Verifies inventory and calculates totals.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"customerId":{"type":"string","example":"cust_01"},"items":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string","minLength":1,"example":"prod_01"},"variantId":{"type":"string","example":"var_01"},"quantity":{"type":"integer","minimum":1,"example":2}},"required":["productId","quantity"]},"minItems":1,"description":"Order line items"},"shippingAddress":{"type":"object","properties":{"firstName":{"type":"string","example":"John"},"lastName":{"type":"string","example":"Doe"},"company":{"type":"string","example":null},"address1":{"type":"string","minLength":1,"example":"123 Main St"},"address2":{"type":"string","example":"Apt 4"},"city":{"type":"string","minLength":1,"example":"Austin"},"state":{"type":"string","example":"TX"},"zip":{"type":"string","minLength":1,"example":"78701"},"country":{"type":"string","minLength":1,"example":"US"},"phone":{"type":"string","example":"+1-555-0100"}},"required":["address1","city","zip","country"],"description":"Shipping address"},"notes":{"type":"string","example":"Please wrap as gift"},"shippingTotal":{"type":"integer","minimum":0,"example":500,"description":"Shipping charge in cents (admin-set)"},"discountTotal":{"type":"integer","minimum":0,"example":0,"description":"Discount amount in cents (admin-set)"},"currency":{"type":"string","example":"USD"}},"required":["items"]}}}},"responses":{"201":{"description":"Order created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"ord_01"},"customerId":{"type":"string","nullable":true,"example":"cust_01"},"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"],"example":"pending"},"total":{"type":"integer","example":6498,"description":"Total in cents"},"subtotal":{"type":"integer","example":5998,"description":"Subtotal in cents"},"shippingTotal":{"type":"integer","example":500,"description":"Shipping in cents"},"taxTotal":{"type":"integer","example":0,"description":"Tax in cents"},"discountTotal":{"type":"integer","example":0,"description":"Discount in cents"},"currency":{"type":"string","example":"USD"},"notes":{"type":"string","nullable":true,"example":null},"trackingCarrier":{"type":"string","nullable":true,"example":"UPS"},"trackingNumber":{"type":"string","nullable":true,"example":"1Z999AA10123456784"},"paymentIntentId":{"type":"string","nullable":true,"example":"pi_3MtwBwLkdIwHu7ix28a3tqPa"},"paymentStatus":{"type":"string","nullable":true,"enum":["pending","processing","succeeded","failed","cancelled","refunded",null],"example":"pending"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"oi_01"},"orderId":{"type":"string","example":"ord_01"},"productId":{"type":"string","nullable":true,"example":"prod_01"},"variantId":{"type":"string","nullable":true,"example":"var_01"},"name":{"type":"string","example":"T-Shirt - Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","example":2999,"description":"Unit price in cents"},"quantity":{"type":"integer","example":2},"total":{"type":"integer","example":5998,"description":"Line total in cents"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","productId","variantId","name","sku","price","quantity","total","createdAt","updatedAt"]},"description":"Order line items"},"shippingAddress":{"type":"object","nullable":true,"properties":{"id":{"type":"string","example":"osa_01"},"orderId":{"type":"string","example":"ord_01"},"firstName":{"type":"string","nullable":true,"example":"John"},"lastName":{"type":"string","nullable":true,"example":"Doe"},"company":{"type":"string","nullable":true,"example":null},"address1":{"type":"string","example":"123 Main St"},"address2":{"type":"string","nullable":true,"example":"Apt 4"},"city":{"type":"string","example":"Austin"},"state":{"type":"string","nullable":true,"example":"TX"},"zip":{"type":"string","example":"78701"},"country":{"type":"string","example":"US"},"phone":{"type":"string","nullable":true,"example":"+1-555-0100"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","firstName","lastName","company","address1","address2","city","state","zip","country","phone","createdAt","updatedAt"],"description":"Shipping address"}},"required":["id","customerId","status","total","subtotal","shippingTotal","taxTotal","discountTotal","currency","notes","trackingCarrier","trackingNumber","paymentIntentId","paymentStatus","createdAt","updatedAt","items","shippingAddress"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error (e.g. insufficient inventory)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/{id}/events":{"get":{"tags":["Orders"],"summary":"Get event-sourced timeline for an order","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Order event timeline","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"timestamp":{"type":"number"},"actor":{"type":"object","properties":{"type":{"type":"string","enum":["customer","user","system"]},"id":{"type":"string","nullable":true},"name":{"type":"string","nullable":true}},"required":["type","id"]},"payload":{"type":"object","additionalProperties":{"nullable":true}}},"required":["id","type","timestamp","actor","payload"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/{id}":{"get":{"tags":["Orders"],"summary":"Get order detail","description":"Returns full order details including line items, customer info, and shipping address.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"ord_01"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Full order details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"ord_01"},"customerId":{"type":"string","nullable":true,"example":"cust_01"},"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"],"example":"pending"},"total":{"type":"integer","example":6498,"description":"Total in cents"},"subtotal":{"type":"integer","example":5998,"description":"Subtotal in cents"},"shippingTotal":{"type":"integer","example":500,"description":"Shipping in cents"},"taxTotal":{"type":"integer","example":0,"description":"Tax in cents"},"discountTotal":{"type":"integer","example":0,"description":"Discount in cents"},"currency":{"type":"string","example":"USD"},"notes":{"type":"string","nullable":true,"example":null},"trackingCarrier":{"type":"string","nullable":true,"example":"UPS"},"trackingNumber":{"type":"string","nullable":true,"example":"1Z999AA10123456784"},"paymentIntentId":{"type":"string","nullable":true,"example":"pi_3MtwBwLkdIwHu7ix28a3tqPa"},"paymentStatus":{"type":"string","nullable":true,"enum":["pending","processing","succeeded","failed","cancelled","refunded",null],"example":"pending"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"oi_01"},"orderId":{"type":"string","example":"ord_01"},"productId":{"type":"string","nullable":true,"example":"prod_01"},"variantId":{"type":"string","nullable":true,"example":"var_01"},"name":{"type":"string","example":"T-Shirt - Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","example":2999,"description":"Unit price in cents"},"quantity":{"type":"integer","example":2},"total":{"type":"integer","example":5998,"description":"Line total in cents"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","productId","variantId","name","sku","price","quantity","total","createdAt","updatedAt"]},"description":"Order line items"},"shippingAddress":{"type":"object","nullable":true,"properties":{"id":{"type":"string","example":"osa_01"},"orderId":{"type":"string","example":"ord_01"},"firstName":{"type":"string","nullable":true,"example":"John"},"lastName":{"type":"string","nullable":true,"example":"Doe"},"company":{"type":"string","nullable":true,"example":null},"address1":{"type":"string","example":"123 Main St"},"address2":{"type":"string","nullable":true,"example":"Apt 4"},"city":{"type":"string","example":"Austin"},"state":{"type":"string","nullable":true,"example":"TX"},"zip":{"type":"string","example":"78701"},"country":{"type":"string","example":"US"},"phone":{"type":"string","nullable":true,"example":"+1-555-0100"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","firstName","lastName","company","address1","address2","city","state","zip","country","phone","createdAt","updatedAt"],"description":"Shipping address"},"customer":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true}},"required":["id","email","firstName","lastName"],"description":"Customer details"},"statusHistory":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"osh_01"},"orderId":{"type":"string","example":"ord_01"},"fromStatus":{"type":"string","nullable":true,"example":"pending"},"toStatus":{"type":"string","example":"confirmed"},"note":{"type":"string","nullable":true,"example":"Order confirmed"},"changedBy":{"type":"string","nullable":true,"example":"usr_01"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","fromStatus","toStatus","note","changedBy","createdAt"]},"description":"Order status change history"},"orderNotes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"on_01"},"orderId":{"type":"string","example":"ord_01"},"content":{"type":"string","example":"Customer requested gift wrapping"},"userId":{"type":"string","nullable":true,"example":"usr_01"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","content","userId","createdAt"]},"description":"Order notes"}},"required":["id","customerId","status","total","subtotal","shippingTotal","taxTotal","discountTotal","currency","notes","trackingCarrier","trackingNumber","paymentIntentId","paymentStatus","createdAt","updatedAt","items","shippingAddress","customer","statusHistory","orderNotes"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/{id}/tracking":{"patch":{"tags":["Orders"],"summary":"Update order shipping tracking","description":"Updates the shipping carrier and tracking number for an order.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"carrier":{"type":"string","minLength":1,"maxLength":100,"example":"UPS"},"trackingNumber":{"type":"string","minLength":1,"maxLength":255,"example":"1Z999AA10123456784"}},"required":["carrier","trackingNumber"]}}}},"responses":{"200":{"description":"Tracking updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"ord_01"},"customerId":{"type":"string","nullable":true,"example":"cust_01"},"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"],"example":"pending"},"total":{"type":"integer","example":6498,"description":"Total in cents"},"subtotal":{"type":"integer","example":5998,"description":"Subtotal in cents"},"shippingTotal":{"type":"integer","example":500,"description":"Shipping in cents"},"taxTotal":{"type":"integer","example":0,"description":"Tax in cents"},"discountTotal":{"type":"integer","example":0,"description":"Discount in cents"},"currency":{"type":"string","example":"USD"},"notes":{"type":"string","nullable":true,"example":null},"trackingCarrier":{"type":"string","nullable":true,"example":"UPS"},"trackingNumber":{"type":"string","nullable":true,"example":"1Z999AA10123456784"},"paymentIntentId":{"type":"string","nullable":true,"example":"pi_3MtwBwLkdIwHu7ix28a3tqPa"},"paymentStatus":{"type":"string","nullable":true,"enum":["pending","processing","succeeded","failed","cancelled","refunded",null],"example":"pending"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","customerId","status","total","subtotal","shippingTotal","taxTotal","discountTotal","currency","notes","trackingCarrier","trackingNumber","paymentIntentId","paymentStatus","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/{id}/status":{"patch":{"tags":["Orders"],"summary":"Update order status","description":"Transitions an order to a new status. Only valid transitions are allowed.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"],"example":"confirmed","description":"The new status to transition the order to."},"note":{"type":"string","maxLength":500,"example":"Order confirmed and ready for processing","description":"Optional note for the status change."}},"required":["status"]}}}},"responses":{"200":{"description":"Status updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"ord_01"},"customerId":{"type":"string","nullable":true,"example":"cust_01"},"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"],"example":"pending"},"total":{"type":"integer","example":6498,"description":"Total in cents"},"subtotal":{"type":"integer","example":5998,"description":"Subtotal in cents"},"shippingTotal":{"type":"integer","example":500,"description":"Shipping in cents"},"taxTotal":{"type":"integer","example":0,"description":"Tax in cents"},"discountTotal":{"type":"integer","example":0,"description":"Discount in cents"},"currency":{"type":"string","example":"USD"},"notes":{"type":"string","nullable":true,"example":null},"trackingCarrier":{"type":"string","nullable":true,"example":"UPS"},"trackingNumber":{"type":"string","nullable":true,"example":"1Z999AA10123456784"},"paymentIntentId":{"type":"string","nullable":true,"example":"pi_3MtwBwLkdIwHu7ix28a3tqPa"},"paymentStatus":{"type":"string","nullable":true,"enum":["pending","processing","succeeded","failed","cancelled","refunded",null],"example":"pending"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","customerId","status","total","subtotal","shippingTotal","taxTotal","discountTotal","currency","notes","trackingCarrier","trackingNumber","paymentIntentId","paymentStatus","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedTransitions":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedTransitions":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}},"422":{"description":"Invalid status transition","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedTransitions":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedTransitions":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}}}}},"/v1/orders/{id}/notes":{"post":{"tags":["Orders"],"summary":"Add a note to an order","description":"Creates a new note on the specified order with author attribution.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","minLength":1,"maxLength":2000,"example":"Customer requested gift wrapping"}},"required":["content"]}}}},"responses":{"201":{"description":"Note created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"on_01"},"orderId":{"type":"string","example":"ord_01"},"content":{"type":"string","example":"Customer requested gift wrapping"},"userId":{"type":"string","nullable":true,"example":"usr_01"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","content","userId","createdAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/{id}/refund":{"post":{"tags":["Orders"],"summary":"Refund an order","description":"Processes a full or partial refund for an order. Initiates a Stripe refund if a payment intent exists.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"ord_01a2b3c4d5e6"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"type":"integer","minimum":1,"example":2500,"description":"Refund amount in cents. Omit for full refund."},"reason":{"type":"string","maxLength":500,"example":"Customer requested return","description":"Reason for the refund."}}}}}},"responses":{"200":{"description":"Refund processed","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"ref_01a2b3c4d5e6"},"orderId":{"type":"string","example":"ord_01"},"stripeRefundId":{"type":"string","nullable":true,"example":"re_3MtwBwLkdIwHu7ix28a3tqPa"},"amount":{"type":"integer","example":2500,"description":"Refunded amount in cents"},"reason":{"type":"string","nullable":true,"example":"Customer requested return"},"status":{"type":"string","enum":["pending","succeeded","failed"],"example":"succeeded"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","stripeRefundId","amount","reason","status","createdAt"]}}}},"400":{"description":"Order cannot be refunded","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Stripe credentials not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/{id}/cancel":{"post":{"tags":["Orders"],"summary":"Cancel an order","description":"Cancels an order, restores stock, and issues a Stripe refund if a payment exists.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"ord_01a2b3c4d5e6"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","maxLength":500,"example":"Customer requested cancellation","description":"Reason for cancelling the order."}}}}}},"responses":{"200":{"description":"Order cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"ord_01"},"customerId":{"type":"string","nullable":true,"example":"cust_01"},"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"],"example":"pending"},"total":{"type":"integer","example":6498,"description":"Total in cents"},"subtotal":{"type":"integer","example":5998,"description":"Subtotal in cents"},"shippingTotal":{"type":"integer","example":500,"description":"Shipping in cents"},"taxTotal":{"type":"integer","example":0,"description":"Tax in cents"},"discountTotal":{"type":"integer","example":0,"description":"Discount in cents"},"currency":{"type":"string","example":"USD"},"notes":{"type":"string","nullable":true,"example":null},"trackingCarrier":{"type":"string","nullable":true,"example":"UPS"},"trackingNumber":{"type":"string","nullable":true,"example":"1Z999AA10123456784"},"paymentIntentId":{"type":"string","nullable":true,"example":"pi_3MtwBwLkdIwHu7ix28a3tqPa"},"paymentStatus":{"type":"string","nullable":true,"enum":["pending","processing","succeeded","failed","cancelled","refunded",null],"example":"pending"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"oi_01"},"orderId":{"type":"string","example":"ord_01"},"productId":{"type":"string","nullable":true,"example":"prod_01"},"variantId":{"type":"string","nullable":true,"example":"var_01"},"name":{"type":"string","example":"T-Shirt - Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","example":2999,"description":"Unit price in cents"},"quantity":{"type":"integer","example":2},"total":{"type":"integer","example":5998,"description":"Line total in cents"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","productId","variantId","name","sku","price","quantity","total","createdAt","updatedAt"]},"description":"Order line items"},"shippingAddress":{"type":"object","nullable":true,"properties":{"id":{"type":"string","example":"osa_01"},"orderId":{"type":"string","example":"ord_01"},"firstName":{"type":"string","nullable":true,"example":"John"},"lastName":{"type":"string","nullable":true,"example":"Doe"},"company":{"type":"string","nullable":true,"example":null},"address1":{"type":"string","example":"123 Main St"},"address2":{"type":"string","nullable":true,"example":"Apt 4"},"city":{"type":"string","example":"Austin"},"state":{"type":"string","nullable":true,"example":"TX"},"zip":{"type":"string","example":"78701"},"country":{"type":"string","example":"US"},"phone":{"type":"string","nullable":true,"example":"+1-555-0100"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","firstName","lastName","company","address1","address2","city","state","zip","country","phone","createdAt","updatedAt"],"description":"Shipping address"}},"required":["id","customerId","status","total","subtotal","shippingTotal","taxTotal","discountTotal","currency","notes","trackingCarrier","trackingNumber","paymentIntentId","paymentStatus","createdAt","updatedAt","items","shippingAddress"]}}}},"400":{"description":"Order cannot be cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Stripe credentials not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/{id}/items":{"post":{"tags":["Orders"],"summary":"Add a line item to a pre-fulfillment order","description":"Adds a line item, reserves stock, recomputes subtotal + tax + total, and records an audit entry. Rejected once the order is shipped/delivered/cancelled/refunded.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddOrderItem"}}}},"responses":{"200":{"description":"Item added; order recomputed","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"ord_01"},"customerId":{"type":"string","nullable":true,"example":"cust_01"},"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"],"example":"pending"},"total":{"type":"integer","example":6498,"description":"Total in cents"},"subtotal":{"type":"integer","example":5998,"description":"Subtotal in cents"},"shippingTotal":{"type":"integer","example":500,"description":"Shipping in cents"},"taxTotal":{"type":"integer","example":0,"description":"Tax in cents"},"discountTotal":{"type":"integer","example":0,"description":"Discount in cents"},"currency":{"type":"string","example":"USD"},"notes":{"type":"string","nullable":true,"example":null},"trackingCarrier":{"type":"string","nullable":true,"example":"UPS"},"trackingNumber":{"type":"string","nullable":true,"example":"1Z999AA10123456784"},"paymentIntentId":{"type":"string","nullable":true,"example":"pi_3MtwBwLkdIwHu7ix28a3tqPa"},"paymentStatus":{"type":"string","nullable":true,"enum":["pending","processing","succeeded","failed","cancelled","refunded",null],"example":"pending"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"oi_01"},"orderId":{"type":"string","example":"ord_01"},"productId":{"type":"string","nullable":true,"example":"prod_01"},"variantId":{"type":"string","nullable":true,"example":"var_01"},"name":{"type":"string","example":"T-Shirt - Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","example":2999,"description":"Unit price in cents"},"quantity":{"type":"integer","example":2},"total":{"type":"integer","example":5998,"description":"Line total in cents"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","productId","variantId","name","sku","price","quantity","total","createdAt","updatedAt"]},"description":"Order line items"},"shippingAddress":{"type":"object","nullable":true,"properties":{"id":{"type":"string","example":"osa_01"},"orderId":{"type":"string","example":"ord_01"},"firstName":{"type":"string","nullable":true,"example":"John"},"lastName":{"type":"string","nullable":true,"example":"Doe"},"company":{"type":"string","nullable":true,"example":null},"address1":{"type":"string","example":"123 Main St"},"address2":{"type":"string","nullable":true,"example":"Apt 4"},"city":{"type":"string","example":"Austin"},"state":{"type":"string","nullable":true,"example":"TX"},"zip":{"type":"string","example":"78701"},"country":{"type":"string","example":"US"},"phone":{"type":"string","nullable":true,"example":"+1-555-0100"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","firstName","lastName","company","address1","address2","city","state","zip","country","phone","createdAt","updatedAt"],"description":"Shipping address"}},"required":["id","customerId","status","total","subtotal","shippingTotal","taxTotal","discountTotal","currency","notes","trackingCarrier","trackingNumber","paymentIntentId","paymentStatus","createdAt","updatedAt","items","shippingAddress"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedStatuses":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}},"404":{"description":"Order/product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedStatuses":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}},"409":{"description":"Order not editable / insufficient stock","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedStatuses":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedStatuses":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedStatuses":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}}}}},"/v1/orders/{id}/items/{itemId}":{"patch":{"tags":["Orders"],"summary":"Change the quantity of a line item on a pre-fulfillment order","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"itemId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOrderItem"}}}},"responses":{"200":{"description":"Item updated; order recomputed","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"ord_01"},"customerId":{"type":"string","nullable":true,"example":"cust_01"},"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"],"example":"pending"},"total":{"type":"integer","example":6498,"description":"Total in cents"},"subtotal":{"type":"integer","example":5998,"description":"Subtotal in cents"},"shippingTotal":{"type":"integer","example":500,"description":"Shipping in cents"},"taxTotal":{"type":"integer","example":0,"description":"Tax in cents"},"discountTotal":{"type":"integer","example":0,"description":"Discount in cents"},"currency":{"type":"string","example":"USD"},"notes":{"type":"string","nullable":true,"example":null},"trackingCarrier":{"type":"string","nullable":true,"example":"UPS"},"trackingNumber":{"type":"string","nullable":true,"example":"1Z999AA10123456784"},"paymentIntentId":{"type":"string","nullable":true,"example":"pi_3MtwBwLkdIwHu7ix28a3tqPa"},"paymentStatus":{"type":"string","nullable":true,"enum":["pending","processing","succeeded","failed","cancelled","refunded",null],"example":"pending"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"oi_01"},"orderId":{"type":"string","example":"ord_01"},"productId":{"type":"string","nullable":true,"example":"prod_01"},"variantId":{"type":"string","nullable":true,"example":"var_01"},"name":{"type":"string","example":"T-Shirt - Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","example":2999,"description":"Unit price in cents"},"quantity":{"type":"integer","example":2},"total":{"type":"integer","example":5998,"description":"Line total in cents"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","productId","variantId","name","sku","price","quantity","total","createdAt","updatedAt"]},"description":"Order line items"},"shippingAddress":{"type":"object","nullable":true,"properties":{"id":{"type":"string","example":"osa_01"},"orderId":{"type":"string","example":"ord_01"},"firstName":{"type":"string","nullable":true,"example":"John"},"lastName":{"type":"string","nullable":true,"example":"Doe"},"company":{"type":"string","nullable":true,"example":null},"address1":{"type":"string","example":"123 Main St"},"address2":{"type":"string","nullable":true,"example":"Apt 4"},"city":{"type":"string","example":"Austin"},"state":{"type":"string","nullable":true,"example":"TX"},"zip":{"type":"string","example":"78701"},"country":{"type":"string","example":"US"},"phone":{"type":"string","nullable":true,"example":"+1-555-0100"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","firstName","lastName","company","address1","address2","city","state","zip","country","phone","createdAt","updatedAt"],"description":"Shipping address"}},"required":["id","customerId","status","total","subtotal","shippingTotal","taxTotal","discountTotal","currency","notes","trackingCarrier","trackingNumber","paymentIntentId","paymentStatus","createdAt","updatedAt","items","shippingAddress"]}}}},"404":{"description":"Order/item not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedStatuses":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}},"409":{"description":"Order not editable / insufficient stock","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedStatuses":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedStatuses":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedStatuses":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Orders"],"summary":"Remove a line item from a pre-fulfillment order","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"itemId","in":"path"}],"responses":{"200":{"description":"Item removed; order recomputed","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"ord_01"},"customerId":{"type":"string","nullable":true,"example":"cust_01"},"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"],"example":"pending"},"total":{"type":"integer","example":6498,"description":"Total in cents"},"subtotal":{"type":"integer","example":5998,"description":"Subtotal in cents"},"shippingTotal":{"type":"integer","example":500,"description":"Shipping in cents"},"taxTotal":{"type":"integer","example":0,"description":"Tax in cents"},"discountTotal":{"type":"integer","example":0,"description":"Discount in cents"},"currency":{"type":"string","example":"USD"},"notes":{"type":"string","nullable":true,"example":null},"trackingCarrier":{"type":"string","nullable":true,"example":"UPS"},"trackingNumber":{"type":"string","nullable":true,"example":"1Z999AA10123456784"},"paymentIntentId":{"type":"string","nullable":true,"example":"pi_3MtwBwLkdIwHu7ix28a3tqPa"},"paymentStatus":{"type":"string","nullable":true,"enum":["pending","processing","succeeded","failed","cancelled","refunded",null],"example":"pending"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"oi_01"},"orderId":{"type":"string","example":"ord_01"},"productId":{"type":"string","nullable":true,"example":"prod_01"},"variantId":{"type":"string","nullable":true,"example":"var_01"},"name":{"type":"string","example":"T-Shirt - Large / Blue"},"sku":{"type":"string","nullable":true,"example":"TSH-001-L-BL"},"price":{"type":"integer","example":2999,"description":"Unit price in cents"},"quantity":{"type":"integer","example":2},"total":{"type":"integer","example":5998,"description":"Line total in cents"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","productId","variantId","name","sku","price","quantity","total","createdAt","updatedAt"]},"description":"Order line items"},"shippingAddress":{"type":"object","nullable":true,"properties":{"id":{"type":"string","example":"osa_01"},"orderId":{"type":"string","example":"ord_01"},"firstName":{"type":"string","nullable":true,"example":"John"},"lastName":{"type":"string","nullable":true,"example":"Doe"},"company":{"type":"string","nullable":true,"example":null},"address1":{"type":"string","example":"123 Main St"},"address2":{"type":"string","nullable":true,"example":"Apt 4"},"city":{"type":"string","example":"Austin"},"state":{"type":"string","nullable":true,"example":"TX"},"zip":{"type":"string","example":"78701"},"country":{"type":"string","example":"US"},"phone":{"type":"string","nullable":true,"example":"+1-555-0100"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","orderId","firstName","lastName","company","address1","address2","city","state","zip","country","phone","createdAt","updatedAt"],"description":"Shipping address"}},"required":["id","customerId","status","total","subtotal","shippingTotal","taxTotal","discountTotal","currency","notes","trackingCarrier","trackingNumber","paymentIntentId","paymentStatus","createdAt","updatedAt","items","shippingAddress"]}}}},"404":{"description":"Order/item not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedStatuses":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}},"409":{"description":"Order not editable / last item","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedStatuses":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"allowedStatuses":{"type":"array","items":{"type":"string"}}},"required":["type","title","status"]}}}}}}},"/v1/customers":{"get":{"tags":["Customers"],"summary":"List customers","description":"Returns a paginated list of customers with order count and total spend.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","example":"eyJ0Ijoi...","description":"Signed keyset cursor (O(1) deep pagination). Overrides page when present."},"required":false,"description":"Signed keyset cursor (O(1) deep pagination). Overrides page when present.","name":"cursor","in":"query"},{"schema":{"type":"string","example":"maria","description":"Search by name or email"},"required":false,"description":"Search by name or email","name":"search","in":"query"}],"responses":{"200":{"description":"List of customers","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"cus_01abc"},"email":{"type":"string","format":"email","example":"customer@example.com"},"firstName":{"type":"string","nullable":true,"example":"Maria"},"lastName":{"type":"string","nullable":true,"example":"Garcia"},"phone":{"type":"string","nullable":true,"example":"+1234567890"},"acceptsMarketing":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"orderCount":{"type":"integer","example":5},"totalSpend":{"type":"integer","example":25000,"description":"Total spend in cents"}},"required":["id","email","firstName","lastName","phone","acceptsMarketing","createdAt","updatedAt","orderCount","totalSpend"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"},"nextCursor":{"type":"string","nullable":true,"example":"eyJ0Ijoi...","description":"Signed cursor for the next page (null = last page)."}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"400":{"description":"Bad request (e.g. invalid/tampered cursor)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Customers"],"summary":"Create a new customer","description":"Creates a new customer record. Email must be unique within the tenant.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","minLength":1,"maxLength":255,"format":"email","example":"customer@example.com"},"firstName":{"type":"string","minLength":1,"maxLength":255,"example":"Maria"},"lastName":{"type":"string","minLength":1,"maxLength":255,"example":"Garcia"},"phone":{"type":"string","maxLength":50,"example":"+1234567890"},"acceptsMarketing":{"type":"boolean","default":false,"example":false}},"required":["email"]}}}},"responses":{"201":{"description":"Customer created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"cus_01abc"},"email":{"type":"string","format":"email","example":"customer@example.com"},"firstName":{"type":"string","nullable":true,"example":"Maria"},"lastName":{"type":"string","nullable":true,"example":"Garcia"},"phone":{"type":"string","nullable":true,"example":"+1234567890"},"acceptsMarketing":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","email","firstName","lastName","phone","acceptsMarketing","createdAt","updatedAt"]}}}},"409":{"description":"Email already exists","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/segments":{"get":{"tags":["Customer Segments"],"summary":"List customer segments","description":"Returns customer segments with member counts.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"List of segments","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"type":{"type":"string"},"conditions":{"nullable":true},"memberCount":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","slug","description","type","memberCount","createdAt","updatedAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Customer Segments"],"summary":"Create customer segment","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"example":"VIP"},"description":{"type":"string","maxLength":500,"example":"High-value customers"},"type":{"type":"string","enum":["manual","automatic"],"default":"manual"},"conditions":{"type":"object","properties":{"logic":{"type":"string","enum":["AND","OR"],"default":"AND"},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","enum":["totalSpend","orderCount","lastOrderDate","createdAt","acceptsMarketing","country","tag"]},"operator":{"type":"string","enum":["eq","neq","gt","gte","lt","lte","in","not_in","contains","not_contains","before","after","within_days","not_within_days"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]}},"required":["field","operator","value"]},"minItems":1,"maxItems":20}},"required":["conditions"],"example":{"logic":"AND","conditions":[{"field":"totalSpend","operator":"gte","value":50000}]},"description":"Canonical conditions for automatic segments. Required when type=automatic."}},"required":["name"]}}}},"responses":{"201":{"description":"Segment created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"type":{"type":"string","enum":["manual","automatic"]},"conditions":{"nullable":true},"createdAt":{"type":"string"}},"required":["id","name","description","type","createdAt"]}},"required":["data"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/segments/{id}":{"get":{"tags":["Customer Segments"],"summary":"Get customer segment by ID","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Segment ID"},"required":true,"description":"Segment ID","name":"id","in":"path"}],"responses":{"200":{"description":"Segment details","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"type":{"type":"string","enum":["manual","automatic"]},"conditions":{"nullable":true},"memberCount":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","slug","description","type","memberCount","createdAt","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Segment not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Customer Segments"],"summary":"Update customer segment","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"example":"VIP Gold"},"description":{"type":"string","nullable":true,"maxLength":500,"example":"Top tier customers"},"conditions":{"type":"object","nullable":true,"properties":{"logic":{"type":"string","enum":["AND","OR"],"default":"AND"},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","enum":["totalSpend","orderCount","lastOrderDate","createdAt","acceptsMarketing","country","tag"]},"operator":{"type":"string","enum":["eq","neq","gt","gte","lt","lte","in","not_in","contains","not_contains","before","after","within_days","not_within_days"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]}},"required":["field","operator","value"]},"minItems":1,"maxItems":20}},"required":["conditions"]}}}}}},"responses":{"200":{"description":"Segment updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"type":{"type":"string","enum":["manual","automatic"]},"conditions":{"nullable":true},"createdAt":{"type":"string"}},"required":["id","name","description","type","createdAt"]}},"required":["data"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Segment not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Customer Segments"],"summary":"Delete customer segment","description":"Delete a segment and remove all member associations.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Segment deleted"},"404":{"description":"Segment not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/segments/{id}/members":{"post":{"tags":["Customer Segments"],"summary":"Add customer to segment (body-based)","description":"Add a customer to a segment by passing customerId in the request body.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Segment ID"},"required":true,"description":"Segment ID","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"customerId":{"type":"string","description":"Customer ID to add to segment","example":"cust_abc123"}},"required":["customerId"]}}}},"responses":{"201":{"description":"Member added","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"segmentId":{"type":"string"},"customerId":{"type":"string"},"addedAt":{"type":"string"}},"required":["segmentId","customerId","addedAt"]}},"required":["data"]}}}},"404":{"description":"Segment or customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Customer already in segment","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"get":{"tags":["Customer Segments"],"summary":"List segment members","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Segment ID"},"required":true,"description":"Segment ID","name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"per_page","in":"query"},{"schema":{"type":"string","description":"Filter by customer email or name"},"required":false,"description":"Filter by customer email or name","name":"search","in":"query"}],"responses":{"200":{"description":"Segment members with pagination","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"customerId":{"type":"string"},"customer":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true}},"required":["id","email","firstName","lastName"]},"addedAt":{"type":"string"}},"required":["id","customerId","customer","addedAt"]}},"total":{"type":"integer"},"page":{"type":"integer"},"per_page":{"type":"integer"}},"required":["items","total","page","per_page"]}}}},"404":{"description":"Segment not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/segments/{id}/members/{customerId}":{"post":{"tags":["Customer Segments"],"summary":"Add customer to segment","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Segment ID"},"required":true,"description":"Segment ID","name":"id","in":"path"},{"schema":{"type":"string","description":"Customer ID"},"required":true,"description":"Customer ID","name":"customerId","in":"path"}],"responses":{"201":{"description":"Member added","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"segmentId":{"type":"string"},"customerId":{"type":"string"},"addedAt":{"type":"string"}},"required":["segmentId","customerId","addedAt"]}},"required":["data"]}}}},"404":{"description":"Segment or customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Customer already in segment","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Customer Segments"],"summary":"Remove customer from segment","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Segment ID"},"required":true,"description":"Segment ID","name":"id","in":"path"},{"schema":{"type":"string","description":"Customer ID"},"required":true,"description":"Customer ID","name":"customerId","in":"path"}],"responses":{"204":{"description":"Member removed"},"404":{"description":"Membership not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/bulk/add-to-segment":{"post":{"tags":["Customer Segments"],"summary":"Bulk add customers to segment","description":"Add multiple customers to a manual segment at once. Automatic segments reject this operation.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"segmentId":{"type":"string","description":"Target segment ID"},"customerIds":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":500,"description":"List of customer IDs to add (max 500)","example":["cust_abc123","cust_def456"]}},"required":["segmentId","customerIds"]}}}},"responses":{"200":{"description":"Bulk add result","content":{"application/json":{"schema":{"type":"object","properties":{"added":{"type":"integer","description":"Number of customers successfully added"},"skipped":{"type":"integer","description":"Number of customers already in segment (skipped)"}},"required":["added","skipped"]}}}},"400":{"description":"Segment is automatic or invalid","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Segment not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/segments/{id}/recompute":{"post":{"tags":["Customer Segments"],"summary":"Recompute automatic segment membership","description":"Triggers an on-demand recomputation of an automatic segment's membership. Only `type=automatic` segments are eligible. RBAC: admin + owner.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Segment ID"},"required":true,"description":"Segment ID","name":"id","in":"path"}],"responses":{"200":{"description":"Recompute completed","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"segmentId":{"type":"string"},"added":{"type":"integer"},"removed":{"type":"integer"},"total":{"type":"integer"},"recomputedAt":{"type":"string"}},"required":["segmentId","added","removed","total","recomputedAt"]}},"required":["data"]}}}},"400":{"description":"Segment is not automatic","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Segment not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/{id}":{"get":{"tags":["Customers"],"summary":"Get customer by ID","description":"Returns full customer details including addresses and recent orders","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Customer details with addresses and recent orders","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"cus_01abc"},"email":{"type":"string","format":"email","example":"customer@example.com"},"firstName":{"type":"string","nullable":true,"example":"Maria"},"lastName":{"type":"string","nullable":true,"example":"Garcia"},"phone":{"type":"string","nullable":true,"example":"+1234567890"},"acceptsMarketing":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"addresses":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"addr_01abc"},"customerId":{"type":"string","example":"cus_01abc"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"company":{"type":"string","nullable":true},"address1":{"type":"string","example":"123 Main St"},"address2":{"type":"string","nullable":true},"city":{"type":"string","example":"Austin"},"state":{"type":"string","nullable":true,"example":"TX"},"zip":{"type":"string","example":"78701"},"country":{"type":"string","example":"US"},"phone":{"type":"string","nullable":true},"isDefault":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","customerId","firstName","lastName","company","address1","address2","city","state","zip","country","phone","isDefault","createdAt","updatedAt"]}},"recentOrders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"ord_01abc"},"status":{"type":"string","example":"confirmed"},"total":{"type":"integer","example":5999,"description":"Total in cents"},"currency":{"type":"string","example":"USD"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","status","total","currency","createdAt"]}}},"required":["id","email","firstName","lastName","phone","acceptsMarketing","createdAt","updatedAt","addresses","recentOrders"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Customers"],"summary":"Update a customer","description":"Partially updates a customer record. Only provided fields are changed.","parameters":[{"schema":{"type":"string","minLength":1,"example":"cus_01abc"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":255,"format":"email","example":"updated@example.com"},"firstName":{"type":"string","minLength":1,"maxLength":255,"example":"Maria"},"lastName":{"type":"string","minLength":1,"maxLength":255,"example":"Garcia"},"phone":{"type":"string","maxLength":50,"example":"+1234567890"},"acceptsMarketing":{"type":"boolean","example":true}}}}}},"responses":{"200":{"description":"Customer updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"cus_01abc"},"email":{"type":"string","format":"email","example":"customer@example.com"},"firstName":{"type":"string","nullable":true,"example":"Maria"},"lastName":{"type":"string","nullable":true,"example":"Garcia"},"phone":{"type":"string","nullable":true,"example":"+1234567890"},"acceptsMarketing":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","email","firstName","lastName","phone","acceptsMarketing","createdAt","updatedAt"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Email already exists","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Customers"],"summary":"Soft-delete a customer","description":"Soft-deletes a customer by setting deleted_at timestamp. Order history is preserved.","parameters":[{"schema":{"type":"string","minLength":1,"example":"cus_01abc"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Customer soft-deleted successfully"},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/{id}/orders":{"get":{"tags":["Customers"],"summary":"Get customer orders","description":"Returns paginated orders for a specific customer, scoped to the current tenant.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Paginated customer orders","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"ord_01abc"},"status":{"type":"string","example":"confirmed"},"total":{"type":"integer","example":5999,"description":"Total in cents"},"currency":{"type":"string","example":"USD"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","status","total","currency","createdAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/{id}/addresses":{"get":{"tags":["Customers"],"summary":"List customer addresses","description":"Returns all saved addresses for a specific customer, scoped to the current tenant.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Customer addresses array","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"addr_01abc"},"customerId":{"type":"string","example":"cus_01abc"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"company":{"type":"string","nullable":true},"address1":{"type":"string","example":"123 Main St"},"address2":{"type":"string","nullable":true},"city":{"type":"string","example":"Austin"},"state":{"type":"string","nullable":true,"example":"TX"},"zip":{"type":"string","example":"78701"},"country":{"type":"string","example":"US"},"phone":{"type":"string","nullable":true},"isDefault":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","customerId","firstName","lastName","company","address1","address2","city","state","zip","country","phone","isDefault","createdAt","updatedAt"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Customers"],"summary":"Create a customer address","description":"Adds a new address for a customer. If isDefault is true, clears the default flag on all other addresses.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":255,"example":"Maria"},"lastName":{"type":"string","minLength":1,"maxLength":255,"example":"Garcia"},"company":{"type":"string","maxLength":255,"example":"Acme Inc."},"address1":{"type":"string","minLength":1,"maxLength":255,"example":"123 Main St"},"address2":{"type":"string","maxLength":255,"example":"Suite 100"},"city":{"type":"string","minLength":1,"maxLength":100,"example":"Austin"},"state":{"type":"string","maxLength":50,"example":"TX"},"zip":{"type":"string","minLength":1,"maxLength":20,"example":"78701"},"country":{"type":"string","minLength":2,"maxLength":2,"example":"US"},"phone":{"type":"string","maxLength":50,"example":"+1234567890"},"isDefault":{"type":"boolean","default":false,"example":false}},"required":["address1","city","zip","country"]}}}},"responses":{"201":{"description":"Address created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"addr_01abc"},"customerId":{"type":"string","example":"cus_01abc"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"company":{"type":"string","nullable":true},"address1":{"type":"string","example":"123 Main St"},"address2":{"type":"string","nullable":true},"city":{"type":"string","example":"Austin"},"state":{"type":"string","nullable":true,"example":"TX"},"zip":{"type":"string","example":"78701"},"country":{"type":"string","example":"US"},"phone":{"type":"string","nullable":true},"isDefault":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","customerId","firstName","lastName","company","address1","address2","city","state","zip","country","phone","isDefault","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/{id}/addresses/{addressId}":{"patch":{"tags":["Customers"],"summary":"Update a customer address","description":"Partially updates an existing address for a customer. If isDefault is set to true, clears the default flag on all other addresses.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"addressId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":255,"example":"Maria"},"lastName":{"type":"string","minLength":1,"maxLength":255,"example":"Garcia"},"company":{"type":"string","maxLength":255,"example":"Acme Inc."},"address1":{"type":"string","minLength":1,"maxLength":255,"example":"123 Main St"},"address2":{"type":"string","maxLength":255,"example":"Suite 100"},"city":{"type":"string","minLength":1,"maxLength":100,"example":"Austin"},"state":{"type":"string","maxLength":50,"example":"TX"},"zip":{"type":"string","minLength":1,"maxLength":20,"example":"78701"},"country":{"type":"string","minLength":2,"maxLength":2,"example":"US"},"phone":{"type":"string","maxLength":50,"example":"+1234567890"},"isDefault":{"type":"boolean","example":false}}}}}},"responses":{"200":{"description":"Address updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"addr_01abc"},"customerId":{"type":"string","example":"cus_01abc"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"company":{"type":"string","nullable":true},"address1":{"type":"string","example":"123 Main St"},"address2":{"type":"string","nullable":true},"city":{"type":"string","example":"Austin"},"state":{"type":"string","nullable":true,"example":"TX"},"zip":{"type":"string","example":"78701"},"country":{"type":"string","example":"US"},"phone":{"type":"string","nullable":true},"isDefault":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","customerId","firstName","lastName","company","address1","address2","city","state","zip","country","phone","isDefault","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Customer or address not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Customers"],"summary":"Delete a customer address","description":"Removes an address from a customer. Returns 409 if attempting to delete the only default address.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"addressId","in":"path"}],"responses":{"204":{"description":"Address deleted successfully"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Customer or address not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Cannot delete the only default address","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/validate-vat":{"post":{"tags":["Customers","Tax"],"summary":"Validate an EU VAT ID via VIES","description":"Validates an EU VAT number against the EC VIES service. Results are cached for 24 hours. Gracefully falls back if VIES is unavailable.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"vatId":{"type":"string","minLength":3,"maxLength":20,"example":"DE123456789","description":"EU VAT ID (country prefix + number)"}},"required":["vatId"]}}}},"responses":{"200":{"description":"Validation result (check isValid field)","content":{"application/json":{"schema":{"type":"object","properties":{"isValid":{"type":"boolean","example":true},"countryCode":{"type":"string","example":"DE"},"vatNumber":{"type":"string","example":"123456789"},"name":{"type":"string","example":"Acme GmbH"},"address":{"type":"string","example":"Berlin, DE"},"validatedAt":{"type":"integer","example":1716912000},"source":{"type":"string","enum":["vies","cached","fallback"],"example":"vies"}},"required":["isValid","countryCode","vatNumber","validatedAt","source"]}}}},"400":{"description":"Invalid VAT format","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/:id/validate-vat":{"post":{"tags":["Customers","Tax"],"summary":"Validate VAT ID and update customer record","description":"Validates the provided VAT ID via VIES. If valid, updates customer.vat_id and sets vat_verified_at to now.","parameters":[{"schema":{"type":"string","example":"cus_abc123"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"vatId":{"type":"string","minLength":3,"maxLength":20,"example":"DE123456789","description":"EU VAT ID (country prefix + number)"}},"required":["vatId"]}}}},"responses":{"200":{"description":"Validation result","content":{"application/json":{"schema":{"type":"object","properties":{"validation":{"type":"object","properties":{"isValid":{"type":"boolean","example":true},"countryCode":{"type":"string","example":"DE"},"vatNumber":{"type":"string","example":"123456789"},"name":{"type":"string","example":"Acme GmbH"},"address":{"type":"string","example":"Berlin, DE"},"validatedAt":{"type":"integer","example":1716912000},"source":{"type":"string","enum":["vies","cached","fallback"],"example":"vies"}},"required":["isValid","countryCode","vatNumber","validatedAt","source"]},"customerUpdated":{"type":"boolean","example":true}},"required":["validation","customerUpdated"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/:id/exemption-certificates":{"get":{"tags":["Customers","Tax"],"summary":"List tax exemption certificates for a customer","parameters":[{"schema":{"type":"string","example":"cus_abc123"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"List of exemption certificates","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"cert_abc123"},"customerId":{"type":"string","example":"cus_abc123"},"certificateNumber":{"type":"string","example":"EX-2024-001"},"certificateType":{"type":"string","enum":["resale","government","nonprofit","agriculture","other"]},"issuingState":{"type":"string","nullable":true},"issuingCountry":{"type":"string","example":"DE"},"validFrom":{"type":"integer","example":1704067200},"validTo":{"type":"integer","nullable":true},"fileUrl":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","customerId","certificateNumber","certificateType","issuingState","issuingCountry","validFrom","validTo","fileUrl","notes","createdAt","updatedAt"]}}},"required":["data"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Customers","Tax"],"summary":"Create a tax exemption certificate for a customer","description":"Accepts JSON body. To attach a file, upload to R2 separately and pass the fileUrl, or use multipart (file stored under exemption-certs/{tenantId}/{certId}.{ext}).","parameters":[{"schema":{"type":"string","example":"cus_abc123"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"certificateNumber":{"type":"string","minLength":1,"maxLength":100,"example":"EX-2024-001"},"certificateType":{"type":"string","enum":["resale","government","nonprofit","agriculture","other"]},"issuingState":{"type":"string","maxLength":50},"issuingCountry":{"type":"string","minLength":2,"maxLength":2,"example":"DE"},"validFrom":{"type":"integer","nullable":true,"example":1704067200,"description":"Unix seconds"},"validTo":{"type":"integer","nullable":true},"notes":{"type":"string","maxLength":1000}},"required":["certificateNumber","certificateType","issuingCountry","validFrom"]}}}},"responses":{"201":{"description":"Certificate created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"customerId":{"type":"string"},"certificateNumber":{"type":"string"},"certificateType":{"type":"string","enum":["resale","government","nonprofit","agriculture","other"]},"issuingState":{"type":"string","nullable":true},"issuingCountry":{"type":"string"},"validFrom":{"type":"integer"},"validTo":{"type":"integer","nullable":true},"fileUrl":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","customerId","certificateNumber","certificateType","issuingState","issuingCountry","validFrom","validTo","fileUrl","notes","createdAt","updatedAt"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/customers/:id/exemption-certificates/:certId":{"patch":{"tags":["Customers","Tax"],"summary":"Update a tax exemption certificate","parameters":[{"schema":{"type":"string","example":"cus_abc123"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","example":"cert_abc123"},"required":true,"name":"certId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"certificateNumber":{"type":"string","minLength":1,"maxLength":100},"certificateType":{"type":"string","enum":["resale","government","nonprofit","agriculture","other"]},"issuingState":{"type":"string","nullable":true,"maxLength":50},"issuingCountry":{"type":"string","minLength":2,"maxLength":2},"validFrom":{"type":"integer","nullable":true},"validTo":{"type":"integer","nullable":true},"fileUrl":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true,"maxLength":1000}}}}}},"responses":{"200":{"description":"Updated certificate","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"customerId":{"type":"string"},"certificateNumber":{"type":"string"},"certificateType":{"type":"string","enum":["resale","government","nonprofit","agriculture","other"]},"issuingState":{"type":"string","nullable":true},"issuingCountry":{"type":"string"},"validFrom":{"type":"integer"},"validTo":{"type":"integer","nullable":true},"fileUrl":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","customerId","certificateNumber","certificateType","issuingState","issuingCountry","validFrom","validTo","fileUrl","notes","createdAt","updatedAt"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Customers","Tax"],"summary":"Delete a tax exemption certificate","parameters":[{"schema":{"type":"string","example":"cus_abc123"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","example":"cert_abc123"},"required":true,"name":"certId","in":"path"}],"responses":{"204":{"description":"Deleted successfully"},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/categories":{"get":{"tags":["Categories"],"summary":"List categories as tree","description":"Returns all categories organized as a hierarchical tree with product counts.","responses":{"200":{"description":"Category tree","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryTreeResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Categories"],"summary":"Create a category","description":"Creates a new product category with optional parent for nesting.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Electronics","description":"Category name"},"slug":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$","example":"electronics","description":"URL-friendly slug (lowercase, hyphens only)"},"parentId":{"type":"string","nullable":true,"example":null,"description":"Parent category ID for nesting"},"description":{"type":"string","nullable":true,"maxLength":2000,"example":"All electronic devices","description":"Category description"},"imageUrl":{"type":"string","nullable":true,"format":"uri","example":null,"description":"Category image URL"},"position":{"type":"integer","minimum":0,"example":0,"description":"Display order"}},"required":["name","slug"]}}}},"responses":{"201":{"description":"Category created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"cat_abc123def456"},"name":{"type":"string","example":"Electronics"},"slug":{"type":"string","example":"electronics"},"parentId":{"type":"string","nullable":true,"example":null},"description":{"type":"string","nullable":true,"example":"All electronic devices"},"imageUrl":{"type":"string","nullable":true,"example":null},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","slug","parentId","description","imageUrl","position","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Slug already exists","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/categories/{id}":{"patch":{"tags":["Categories"],"summary":"Update a category","description":"Partially updates a category. Prevents circular parent assignments.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"cat_abc123def456"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Electronics","description":"Category name"},"slug":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$","example":"electronics","description":"URL-friendly slug"},"parentId":{"type":"string","nullable":true,"example":null,"description":"Parent category ID for nesting"},"description":{"type":"string","nullable":true,"maxLength":2000,"example":"All electronic devices","description":"Category description"},"imageUrl":{"type":"string","nullable":true,"format":"uri","example":null,"description":"Category image URL"},"position":{"type":"integer","minimum":0,"example":0,"description":"Display order"}}}}}},"responses":{"200":{"description":"Category updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"cat_abc123def456"},"name":{"type":"string","example":"Electronics"},"slug":{"type":"string","example":"electronics"},"parentId":{"type":"string","nullable":true,"example":null},"description":{"type":"string","nullable":true,"example":"All electronic devices"},"imageUrl":{"type":"string","nullable":true,"example":null},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","slug","parentId","description","imageUrl","position","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Category not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Slug conflict","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error (circular parent)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Categories"],"summary":"Delete a category","description":"Deletes a category. Returns 409 if it has child categories or assigned products.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"cat_abc123def456"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Category deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Category not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Category has children or products","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/pages":{"get":{"tags":["Pages"],"summary":"List pages","description":"Returns CMS pages for the current tenant. Supports filtering by status and pageType with page-based pagination.","parameters":[{"schema":{"type":"string","enum":["published","draft","archived"],"example":"published"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","example":"blog","description":"Filter by pageType"},"required":false,"description":"Filter by pageType","name":"type","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"List of pages with pagination","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"page_01abc"},"title":{"type":"string","example":"About Us"},"slug":{"type":"string","example":"about-us"},"content":{"type":"string","nullable":true,"example":"<p>Welcome to our store</p>"},"status":{"type":"string","enum":["published","draft","archived"],"example":"published"},"pageType":{"type":"string","nullable":true,"example":"page"},"metaTitle":{"type":"string","nullable":true,"example":"About Us | Our Store"},"metaDescription":{"type":"string","nullable":true,"example":"Learn about our store"},"thumbnail":{"type":"string","nullable":true,"example":"/images/about.jpg"},"excerpt":{"type":"string","nullable":true,"example":"Learn about our store and team."},"publishedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","title","slug","content","status","pageType","metaTitle","metaDescription","thumbnail","excerpt","publishedAt","createdAt","updatedAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Pages"],"summary":"Create a new CMS page","description":"Creates a new page with a unique slug for the tenant.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":255,"example":"About Us"},"slug":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$","example":"about-us"},"content":{"type":"string","example":"<p>Welcome to our store</p>"},"status":{"type":"string","enum":["published","draft","archived"],"default":"draft","example":"draft"},"pageType":{"type":"string","maxLength":50,"default":"page","example":"page"},"metaTitle":{"type":"string","maxLength":255,"example":"About Us | Our Store"},"metaDescription":{"type":"string","maxLength":500,"example":"Learn about our store"},"thumbnail":{"type":"string","maxLength":500,"example":"/images/about.jpg"},"excerpt":{"type":"string","maxLength":500,"example":"Learn about our store."}},"required":["title","slug"]}}}},"responses":{"201":{"description":"Page created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"page_01abc"},"title":{"type":"string","example":"About Us"},"slug":{"type":"string","example":"about-us"},"content":{"type":"string","nullable":true,"example":"<p>Welcome to our store</p>"},"status":{"type":"string","enum":["published","draft","archived"],"example":"published"},"pageType":{"type":"string","nullable":true,"example":"page"},"metaTitle":{"type":"string","nullable":true,"example":"About Us | Our Store"},"metaDescription":{"type":"string","nullable":true,"example":"Learn about our store"},"thumbnail":{"type":"string","nullable":true,"example":"/images/about.jpg"},"excerpt":{"type":"string","nullable":true,"example":"Learn about our store and team."},"publishedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","title","slug","content","status","pageType","metaTitle","metaDescription","thumbnail","excerpt","publishedAt","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Slug already in use","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/pages/by-slug/{slug}":{"get":{"tags":["Pages"],"summary":"Get published page by slug","description":"Returns a published page by its slug for storefront rendering. Only published pages are returned.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"}],"responses":{"200":{"description":"Page found with blocks","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"page_01abc"},"title":{"type":"string","example":"About Us"},"slug":{"type":"string","example":"about-us"},"content":{"type":"string","nullable":true,"example":"<p>Welcome to our store</p>"},"status":{"type":"string","enum":["published","draft","archived"],"example":"published"},"pageType":{"type":"string","nullable":true,"example":"page"},"metaTitle":{"type":"string","nullable":true,"example":"About Us | Our Store"},"metaDescription":{"type":"string","nullable":true,"example":"Learn about our store"},"thumbnail":{"type":"string","nullable":true,"example":"/images/about.jpg"},"excerpt":{"type":"string","nullable":true,"example":"Learn about our store and team."},"publishedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"blocks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"blk_01abc"},"pageId":{"type":"string","example":"page_01abc"},"type":{"type":"string","example":"rich_text"},"content":{"type":"string","example":"{\"text\": \"Hello\"}"},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","pageId","type","content","position","createdAt","updatedAt"]}}},"required":["id","title","slug","content","status","pageType","metaTitle","metaDescription","thumbnail","excerpt","publishedAt","createdAt","updatedAt","blocks"]}}}},"404":{"description":"Page not found or not published","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/pages/{id}":{"get":{"tags":["Pages"],"summary":"Get page by ID","description":"Returns a page by ID including all page blocks, ordered by position.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Page with blocks","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"page_01abc"},"title":{"type":"string","example":"About Us"},"slug":{"type":"string","example":"about-us"},"content":{"type":"string","nullable":true,"example":"<p>Welcome to our store</p>"},"status":{"type":"string","enum":["published","draft","archived"],"example":"published"},"pageType":{"type":"string","nullable":true,"example":"page"},"metaTitle":{"type":"string","nullable":true,"example":"About Us | Our Store"},"metaDescription":{"type":"string","nullable":true,"example":"Learn about our store"},"thumbnail":{"type":"string","nullable":true,"example":"/images/about.jpg"},"excerpt":{"type":"string","nullable":true,"example":"Learn about our store and team."},"publishedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"blocks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"blk_01abc"},"pageId":{"type":"string","example":"page_01abc"},"type":{"type":"string","example":"rich_text"},"content":{"type":"string","example":"{\"text\": \"Hello\"}"},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","pageId","type","content","position","createdAt","updatedAt"]}}},"required":["id","title","slug","content","status","pageType","metaTitle","metaDescription","thumbnail","excerpt","publishedAt","createdAt","updatedAt","blocks"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Page not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Pages"],"summary":"Update a CMS page","description":"Partially updates a page. If blocks are provided, all existing blocks are replaced.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":255,"example":"Updated Title"},"slug":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$","example":"updated-title"},"content":{"type":"string","nullable":true,"example":"<p>Updated content</p>"},"status":{"type":"string","enum":["published","draft","archived"],"example":"published"},"pageType":{"type":"string","maxLength":50,"example":"page"},"metaTitle":{"type":"string","nullable":true,"maxLength":255,"example":"Updated Meta Title"},"metaDescription":{"type":"string","nullable":true,"maxLength":500,"example":"Updated meta description"},"thumbnail":{"type":"string","nullable":true,"maxLength":500,"example":"/images/updated.jpg"},"excerpt":{"type":"string","nullable":true,"maxLength":500,"example":"Updated excerpt."},"blocks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"blk_01abc"},"type":{"type":"string","minLength":1,"example":"rich_text"},"content":{"type":"string","example":"{\"text\": \"Hello\"}"},"position":{"type":"integer","minimum":0,"example":0}},"required":["type","content","position"]},"description":"Replace all blocks with this array"}}}}}},"responses":{"200":{"description":"Updated page with blocks","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"page_01abc"},"title":{"type":"string","example":"About Us"},"slug":{"type":"string","example":"about-us"},"content":{"type":"string","nullable":true,"example":"<p>Welcome to our store</p>"},"status":{"type":"string","enum":["published","draft","archived"],"example":"published"},"pageType":{"type":"string","nullable":true,"example":"page"},"metaTitle":{"type":"string","nullable":true,"example":"About Us | Our Store"},"metaDescription":{"type":"string","nullable":true,"example":"Learn about our store"},"thumbnail":{"type":"string","nullable":true,"example":"/images/about.jpg"},"excerpt":{"type":"string","nullable":true,"example":"Learn about our store and team."},"publishedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"blocks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"blk_01abc"},"pageId":{"type":"string","example":"page_01abc"},"type":{"type":"string","example":"rich_text"},"content":{"type":"string","example":"{\"text\": \"Hello\"}"},"position":{"type":"integer","example":0},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","pageId","type","content","position","createdAt","updatedAt"]}}},"required":["id","title","slug","content","status","pageType","metaTitle","metaDescription","thumbnail","excerpt","publishedAt","createdAt","updatedAt","blocks"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Page not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Slug already in use","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Pages"],"summary":"Delete a page","description":"Permanently deletes a CMS page by ID.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"page_01abc"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Page deleted successfully"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Page not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/pages/{id}/preview-token":{"post":{"tags":["Pages"],"summary":"Mint a short-lived preview token for a page","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Preview token","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"expiresIn":{"type":"integer"}},"required":["token","expiresIn"]}}}},"404":{"description":"Page not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Preview not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/pages/{id}/status":{"patch":{"tags":["Pages"],"summary":"Update page status","description":"Publishes, unpublishes, or archives a page. Sets published_at when transitioning to published.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"page_01abc"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["draft","published","archived"],"example":"published"}},"required":["status"]}}}},"responses":{"200":{"description":"Page status updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"page_01abc"},"title":{"type":"string","example":"About Us"},"slug":{"type":"string","example":"about-us"},"content":{"type":"string","nullable":true,"example":"<p>Welcome to our store</p>"},"status":{"type":"string","enum":["published","draft","archived"],"example":"published"},"pageType":{"type":"string","nullable":true,"example":"page"},"metaTitle":{"type":"string","nullable":true,"example":"About Us | Our Store"},"metaDescription":{"type":"string","nullable":true,"example":"Learn about our store"},"thumbnail":{"type":"string","nullable":true,"example":"/images/about.jpg"},"excerpt":{"type":"string","nullable":true,"example":"Learn about our store and team."},"publishedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","title","slug","content","status","pageType","metaTitle","metaDescription","thumbnail","excerpt","publishedAt","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Page not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings/agentic":{"get":{"tags":["Settings","Agentic"],"summary":"Get agentic surface toggles (MCP / UCP / ACP / llms.txt / agent feed)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Effective agentic settings (defaults when never configured: all enabled)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AgenticSettings"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Settings","Agentic"],"summary":"Update agentic surface toggles (partial)","description":"Per-surface opt-out for the agentic endpoints. Only provided fields are persisted; a disabled surface answers a clean 404 on its public route(s).","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchAgenticSettings"}}}},"responses":{"200":{"description":"Updated effective agentic settings","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AgenticSettings"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/agentic/access-log":{"get":{"tags":["Agentic"],"summary":"List agent access-log entries (keyset paginated, newest first)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","enum":["mcp","ucp","acp","llms","feed"]},"required":false,"name":"protocol","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0},"required":false,"name":"since","in":"query"}],"responses":{"200":{"description":"One page of access-log entries + opaque nextCursor (null on the last page)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AgentAccessLogEntry"}},"nextCursor":{"type":"string","nullable":true}},"required":["data","nextCursor"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/agentic/access-log/stats":{"get":{"tags":["Agentic"],"summary":"Agent access-log stats — request counts per protocol, last 7 and 30 days","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Counts per protocol for the 7-day and 30-day windows","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"last7d":{"type":"object","properties":{"total":{"type":"integer"},"byProtocol":{"type":"object","properties":{"mcp":{"type":"integer"},"ucp":{"type":"integer"},"acp":{"type":"integer"},"llms":{"type":"integer"},"feed":{"type":"integer"}},"required":["mcp","ucp","acp","llms","feed"]}},"required":["total","byProtocol"]},"last30d":{"type":"object","properties":{"total":{"type":"integer"},"byProtocol":{"type":"object","properties":{"mcp":{"type":"integer"},"ucp":{"type":"integer"},"acp":{"type":"integer"},"llms":{"type":"integer"},"feed":{"type":"integer"}},"required":["mcp","ucp","acp","llms","feed"]}},"required":["total","byProtocol"]}},"required":["last7d","last30d"]}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings/languages":{"get":{"tags":["Translations"],"summary":"List enabled languages","description":"Returns all languages configured for the current tenant.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"1","description":"Page number (default: 1)"},"required":false,"description":"Page number (default: 1)","name":"page","in":"query"},{"schema":{"type":"string","example":"50","description":"Items per page (max 100)"},"required":false,"description":"Items per page (max 100)","name":"limit","in":"query"},{"schema":{"type":"string","example":"-createdAt","description":"Sort field. Prefix - for desc. Fields: name, code, createdAt"},"required":false,"description":"Sort field. Prefix - for desc. Fields: name, code, createdAt","name":"sort","in":"query"},{"schema":{"type":"string","example":"id,code,name,isDefault","description":"Fields to return (csv)"},"required":false,"description":"Fields to return (csv)","name":"fields","in":"query"},{"schema":{"type":"string","description":"Full-text search in: name, code"},"required":false,"description":"Full-text search in: name, code","name":"search","in":"query"}],"responses":{"200":{"description":"List of languages","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"lang_01"},"code":{"type":"string","example":"en"},"name":{"type":"string","example":"English"},"isDefault":{"type":"boolean","example":false},"isActive":{"type":"boolean","example":true},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","code","name","isDefault","isActive","createdAt"]}}},"required":["data"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Translations"],"summary":"Enable a language","description":"Add a new language for the current tenant. Enforces plan limits.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","minLength":2,"maxLength":10,"example":"en","description":"ISO 639-1 language code"},"name":{"type":"string","minLength":1,"maxLength":100,"example":"English"},"isDefault":{"type":"boolean","default":false,"example":false}},"required":["code","name"]}}}},"responses":{"201":{"description":"Language created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","example":"lang_01"},"code":{"type":"string","example":"en"},"name":{"type":"string","example":"English"},"isDefault":{"type":"boolean","example":false},"isActive":{"type":"boolean","example":true},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","code","name","isDefault","isActive","createdAt"]}},"required":["data"]}}}},"402":{"description":"Plan limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Language code already exists","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings/languages/{code}":{"patch":{"tags":["Translations"],"summary":"Update language","description":"Update language properties (name, default, active status).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":2,"example":"en"},"required":true,"name":"code","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"example":"English (US)"},"isDefault":{"type":"boolean","example":true},"isActive":{"type":"boolean","example":true}}}}}},"responses":{"200":{"description":"Language updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","example":"lang_01"},"code":{"type":"string","example":"en"},"name":{"type":"string","example":"English"},"isDefault":{"type":"boolean","example":false},"isActive":{"type":"boolean","example":true},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","code","name","isDefault","isActive","createdAt"]}},"required":["data"]}}}},"404":{"description":"Language not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Translations"],"summary":"Disable a language","description":"Delete a language and all its associated translations. Cannot delete the default language.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":2,"example":"en"},"required":true,"name":"code","in":"path"}],"responses":{"204":{"description":"Language deleted"},"400":{"description":"Cannot delete default language","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Language not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/{entityType}/{entityId}/translations/{locale}":{"get":{"tags":["Translations"],"summary":"Get translations for entity","description":"Returns all translated fields for a specific entity and locale.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["products","categories","pages"],"example":"products"},"required":true,"name":"entityType","in":"path"},{"schema":{"type":"string","example":"prod_01"},"required":true,"name":"entityId","in":"path"},{"schema":{"type":"string","minLength":2,"example":"en"},"required":true,"name":"locale","in":"path"}],"responses":{"200":{"description":"Translation data","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"entityType":{"type":"string","example":"product"},"entityId":{"type":"string","example":"prod_01"},"locale":{"type":"string","example":"en"},"translations":{"type":"object","additionalProperties":{"type":"string"},"example":{"name":"Cotton T-Shirt","description":"A premium cotton t-shirt"}}},"required":["entityType","entityId","locale","translations"]}},"required":["data"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"put":{"tags":["Translations"],"summary":"Set all translations for entity locale","description":"Replace all translated fields for a specific entity and locale. Existing translations for this entity/locale are deleted and replaced.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["products","categories","pages"],"example":"products"},"required":true,"name":"entityType","in":"path"},{"schema":{"type":"string","example":"prod_01"},"required":true,"name":"entityId","in":"path"},{"schema":{"type":"string","minLength":2,"example":"en"},"required":true,"name":"locale","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"translations":{"type":"object","additionalProperties":{"type":"string"},"example":{"name":"Cotton T-Shirt","description":"A premium cotton t-shirt"},"description":"Field name to translated value map"}},"required":["translations"]}}}},"responses":{"200":{"description":"Translations set","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"entityType":{"type":"string","example":"product"},"entityId":{"type":"string","example":"prod_01"},"locale":{"type":"string","example":"en"},"translations":{"type":"object","additionalProperties":{"type":"string"},"example":{"name":"Cotton T-Shirt","description":"A premium cotton t-shirt"}}},"required":["entityType","entityId","locale","translations"]}},"required":["data"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Translations"],"summary":"Update specific translation fields","description":"Update or add specific translated fields for a given entity and locale without affecting other existing fields.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["products","categories","pages"],"example":"products"},"required":true,"name":"entityType","in":"path"},{"schema":{"type":"string","example":"prod_01"},"required":true,"name":"entityId","in":"path"},{"schema":{"type":"string","minLength":2,"example":"en"},"required":true,"name":"locale","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"translations":{"type":"object","additionalProperties":{"type":"string"},"example":{"name":"Cotton T-Shirt Updated"},"description":"Field name to translated value map (partial update)"}},"required":["translations"]}}}},"responses":{"200":{"description":"Translations updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"entityType":{"type":"string","example":"product"},"entityId":{"type":"string","example":"prod_01"},"locale":{"type":"string","example":"en"},"translations":{"type":"object","additionalProperties":{"type":"string"},"example":{"name":"Cotton T-Shirt","description":"A premium cotton t-shirt"}}},"required":["entityType","entityId","locale","translations"]}},"required":["data"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Translations"],"summary":"Delete translations for entity locale","description":"Remove all translations for a specific entity and locale.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["products","categories","pages"],"example":"products"},"required":true,"name":"entityType","in":"path"},{"schema":{"type":"string","example":"prod_01"},"required":true,"name":"entityId","in":"path"},{"schema":{"type":"string","minLength":2,"example":"en"},"required":true,"name":"locale","in":"path"}],"responses":{"204":{"description":"Translations deleted"},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings":{"get":{"tags":["Settings"],"summary":"Get all settings","description":"Returns all tenant settings organized by group. Settings are grouped by key prefix (e.g., \"general.store_name\" belongs to the \"general\" group).","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"All settings organized by group","content":{"application/json":{"schema":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD"},"data":{"type":"array","items":{"type":"object","properties":{"group":{"type":"string","example":"checkout"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"set_01abc"},"key":{"type":"string","example":"checkout.currency"},"value":{"type":"string","example":"USD"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","key","value","createdAt","updatedAt"]}}},"required":["group","data"]}}},"required":["currency","data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Settings"],"summary":"Update settings","description":"Upserts an array of settings. For each key, inserts a new setting or updates the existing value if the key already exists. Requires admin or higher role.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"settings":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"example":"checkout.currency"},"value":{"type":"string","example":"USD"}},"required":["key","value"]},"minItems":1,"example":[{"key":"checkout.currency","value":"USD"},{"key":"checkout.tax_rate","value":"0.16"}]}},"required":["settings"]}}}},"responses":{"200":{"description":"Settings updated","content":{"application/json":{"schema":{"type":"object","properties":{"updated":{"type":"integer","example":2},"settings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"set_01abc"},"key":{"type":"string","example":"checkout.currency"},"value":{"type":"string","example":"USD"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","key","value","createdAt","updatedAt"]}}},"required":["updated","settings"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden – requires admin or higher role","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings/tax-rates":{"get":{"tags":["Settings"],"summary":"List all tax rates","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of tax rates","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"txr_a1b2c3d4e5f6"},"name":{"type":"string","example":"US Federal Tax"},"rate":{"type":"integer","example":825,"description":"Tax rate in basis points (825 = 8.25%)"},"country":{"type":"string","nullable":true,"example":"US"},"state":{"type":"string","nullable":true,"example":"CA"},"categoryId":{"type":"string","nullable":true,"example":null},"isDefault":{"type":"integer","example":0},"isActive":{"type":"integer","example":1},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","rate","country","state","categoryId","isDefault","isActive","createdAt","updatedAt"]}}},"required":["data"]}}}}}},"post":{"tags":["Settings"],"summary":"Create a tax rate","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"US Federal Tax"},"rate":{"type":"integer","minimum":0,"maximum":10000,"example":825,"description":"Tax rate in basis points (825 = 8.25%)"},"country":{"type":"string","maxLength":2,"example":"US"},"state":{"type":"string","maxLength":100,"example":"CA"},"categoryId":{"type":"string","example":null},"isDefault":{"type":"integer","minimum":0,"maximum":1,"default":0,"example":0},"isActive":{"type":"integer","minimum":0,"maximum":1,"default":1,"example":1}},"required":["name","rate"]}}}},"responses":{"201":{"description":"Tax rate created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"txr_a1b2c3d4e5f6"},"name":{"type":"string","example":"US Federal Tax"},"rate":{"type":"integer","example":825,"description":"Tax rate in basis points (825 = 8.25%)"},"country":{"type":"string","nullable":true,"example":"US"},"state":{"type":"string","nullable":true,"example":"CA"},"categoryId":{"type":"string","nullable":true,"example":null},"isDefault":{"type":"integer","example":0},"isActive":{"type":"integer","example":1},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","rate","country","state","categoryId","isDefault","isActive","createdAt","updatedAt"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings/tax-rates/:id":{"patch":{"tags":["Settings"],"summary":"Update a tax rate","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Updated Tax"},"rate":{"type":"integer","minimum":0,"maximum":10000,"example":900},"country":{"type":"string","maxLength":2,"example":"US"},"state":{"type":"string","maxLength":100,"example":"TX"},"categoryId":{"type":"string","nullable":true,"example":null},"isDefault":{"type":"integer","minimum":0,"maximum":1,"example":0},"isActive":{"type":"integer","minimum":0,"maximum":1,"example":1}}}}}},"responses":{"200":{"description":"Tax rate updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"txr_a1b2c3d4e5f6"},"name":{"type":"string","example":"US Federal Tax"},"rate":{"type":"integer","example":825,"description":"Tax rate in basis points (825 = 8.25%)"},"country":{"type":"string","nullable":true,"example":"US"},"state":{"type":"string","nullable":true,"example":"CA"},"categoryId":{"type":"string","nullable":true,"example":null},"isDefault":{"type":"integer","example":0},"isActive":{"type":"integer","example":1},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","rate","country","state","categoryId","isDefault","isActive","createdAt","updatedAt"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Settings"],"summary":"Delete a tax rate","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Tax rate deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings/navigation":{"get":{"tags":["Navigation"],"summary":"List all navigation menus","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"All navigation menus","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","nullable":true,"example":"nav_01"},"name":{"type":"string","example":"Main Navigation"},"location":{"type":"string","example":"header"},"items":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":255,"example":"Shop"},"url":{"type":"string","minLength":1,"maxLength":2048,"example":"/shop"},"children":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":255,"example":"T-Shirts"},"url":{"type":"string","minLength":1,"maxLength":2048,"example":"/shop/t-shirts"}},"required":["label","url"]},"description":"Second-level items (max 2 levels)"}},"required":["label","url"]},"description":"Menu items (max 2 levels deep)"},"createdAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","location","items","createdAt","updatedAt"]}}},"required":["data"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings/navigation/{location}":{"get":{"tags":["Navigation"],"summary":"Get navigation menu by location","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"header"},"required":true,"name":"location","in":"path"}],"responses":{"200":{"description":"Navigation menu. When no menu exists yet for the requested location, an empty (unsaved) menu shell is returned with `id: null` and `items: []` so the client can render an empty \"create your menu\" state instead of an error.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","nullable":true,"example":"nav_01"},"name":{"type":"string","example":"Main Navigation"},"location":{"type":"string","example":"header"},"items":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":255,"example":"Shop"},"url":{"type":"string","minLength":1,"maxLength":2048,"example":"/shop"},"children":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":255,"example":"T-Shirts"},"url":{"type":"string","minLength":1,"maxLength":2048,"example":"/shop/t-shirts"}},"required":["label","url"]},"description":"Second-level items (max 2 levels)"}},"required":["label","url"]},"description":"Menu items (max 2 levels deep)"},"createdAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","location","items","createdAt","updatedAt"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"put":{"tags":["Navigation"],"summary":"Create or update a navigation menu","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"header"},"required":true,"name":"location","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Main Navigation"},"items":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":255,"example":"Shop"},"url":{"type":"string","minLength":1,"maxLength":2048,"example":"/shop"},"children":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":255,"example":"T-Shirts"},"url":{"type":"string","minLength":1,"maxLength":2048,"example":"/shop/t-shirts"}},"required":["label","url"]},"description":"Second-level items (max 2 levels)"}},"required":["label","url"]},"description":"Menu items with optional children (2 levels)","example":[{"label":"Shop","url":"/shop","children":[{"label":"T-Shirts","url":"/shop/t-shirts"}]},{"label":"About","url":"/about"}]}},"required":["name","items"]}}}},"responses":{"200":{"description":"Menu created or updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","nullable":true,"example":"nav_01"},"name":{"type":"string","example":"Main Navigation"},"location":{"type":"string","example":"header"},"items":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":255,"example":"Shop"},"url":{"type":"string","minLength":1,"maxLength":2048,"example":"/shop"},"children":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":255,"example":"T-Shirts"},"url":{"type":"string","minLength":1,"maxLength":2048,"example":"/shop/t-shirts"}},"required":["label","url"]},"description":"Second-level items (max 2 levels)"}},"required":["label","url"]},"description":"Menu items (max 2 levels deep)"},"createdAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","nullable":true,"example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","location","items","createdAt","updatedAt"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Navigation"],"summary":"Delete a navigation menu","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"header"},"required":true,"name":"location","in":"path"}],"responses":{"204":{"description":"Menu deleted"},"404":{"description":"Menu not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings/payment-methods":{"get":{"tags":["Settings","Payments"],"summary":"Get enabled payment methods","description":"Returns the tenant's enabled Stripe payment methods plus Apple Pay / PayPal availability.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentMethodsSettings"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentMethodsProblem"}}}}}},"post":{"tags":["Settings","Payments"],"summary":"Update enabled payment methods","description":"Sets the tenant's enabled Stripe payment methods. `card` is always kept enabled.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePaymentMethods"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePaymentMethodsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentMethodsUpdateProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentMethodsUpdateProblem"}}}}}}},"/v1/settings/payment-gateways":{"get":{"tags":["Settings","Payments"],"summary":"List configured payment gateways (no secrets)","description":"Returns every configured gateway for the tenant with display-safe public credential fields, a `hasSecrets` presence flag and the free-form config. Secret values are never returned.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Configured gateways","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PaymentGatewaySummary"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentGatewaysProblem"}}}}}}},"/v1/settings/payment-gateways/{provider}":{"put":{"tags":["Settings","Payments"],"summary":"Create or update a payment gateway configuration","description":"Upserts the tenant gateway row for the provider. `credentials` is a PARTIAL patch — omitted (or empty-string) keys keep the stored encrypted value, so secrets only travel when the merchant retypes them. `config` replaces the stored config when present.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["stripe","paypal","klarna","mercadopago","redsys","sequra","manual_cod","manual_bank_transfer"],"example":"redsys"},"required":true,"name":"provider","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertPaymentGateway"}}}},"responses":{"200":{"description":"Upserted gateway summary (no secrets)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PaymentGatewaySummary"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentGatewaysProblem"}}}},"422":{"description":"Validation error (unknown provider / malformed body)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentGatewaysProblem"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentGatewaysProblem"}}}}}}},"/v1/settings/customs":{"get":{"tags":["Settings"],"summary":"Get customs / international shipping settings","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Customs settings","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"iossNumber":{"type":"string","nullable":true},"eoriNumber":{"type":"string","nullable":true},"sellerTaxId":{"type":"string","nullable":true},"customsDutiesType":{"type":"string","enum":["DAP","DDP"]}},"required":["iossNumber","eoriNumber","sellerTaxId","customsDutiesType"]}},"required":["data"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Settings"],"summary":"Update customs / international shipping settings","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"iossNumber":{"type":"string","nullable":true},"eoriNumber":{"type":"string","nullable":true},"sellerTaxId":{"type":"string","nullable":true},"customsDutiesType":{"type":"string","enum":["DAP","DDP"]}}}}}},"responses":{"200":{"description":"Updated customs settings","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"iossNumber":{"type":"string","nullable":true},"eoriNumber":{"type":"string","nullable":true},"sellerTaxId":{"type":"string","nullable":true},"customsDutiesType":{"type":"string","enum":["DAP","DDP"]}},"required":["iossNumber","eoriNumber","sellerTaxId","customsDutiesType"]}},"required":["data"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/settings/exporta":{"get":{"tags":["Settings"],"summary":"Get Exporta settings (locales, display currencies, tax display)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Exporta settings (defaults when never configured)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ExportaSettings"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"put":{"tags":["Settings"],"summary":"Replace Exporta settings","description":"Full replace (PUT semantics) of the Exporta configuration. Currencies are validated against ISO 4217, normalised to uppercase and deduplicated; locales are deduplicated preserving order.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutExportaSettings"}}}},"responses":{"200":{"description":"Updated Exporta settings","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ExportaSettings"}},"required":["data"]}}}},"400":{"description":"Invalid currency code","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings/{group}":{"get":{"tags":["Settings"],"summary":"Get settings by group","description":"Returns all settings belonging to the specified group. Settings are grouped by key prefix (e.g., \"checkout.currency\" belongs to the \"checkout\" group).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"group","in":"path"}],"responses":{"200":{"description":"Settings for the specified group","content":{"application/json":{"schema":{"type":"object","properties":{"group":{"type":"string","example":"checkout"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"set_01abc"},"key":{"type":"string","example":"checkout.currency"},"value":{"type":"string","example":"USD"},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","key","value","createdAt","updatedAt"]}}},"required":["group","data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Group not found (no settings with this prefix)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings/onboarding/complete":{"post":{"tags":["Settings"],"summary":"Complete merchant onboarding","description":"Marks the `onboardingCompleted` setting and queues a setup-summary email to the admin who finished the wizard (F5-T2). Idempotent on the setting; the summary email is re-sent on every completion so the UI confirmation toast is always truthful.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Onboarding marked complete","content":{"application/json":{"schema":{"type":"object","properties":{"completed":{"type":"boolean"},"emailQueued":{"type":"boolean"}},"required":["completed","emailQueued"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden – requires admin or higher role","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings/invoicing":{"get":{"tags":["Settings"],"summary":"Get invoice configuration","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Invoice configuration","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"country":{"type":"string"},"format":{"type":"string"},"taxId":{"type":"string","nullable":true},"businessName":{"type":"string","nullable":true},"businessAddress":{"nullable":true},"certPath":{"type":"string","nullable":true},"isActive":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","country","format","taxId","businessName","certPath","isActive","createdAt","updatedAt"]}},"required":["data"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Settings"],"summary":"Update invoice configuration","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"country":{"type":"string","minLength":2,"maxLength":2,"example":"ES"},"format":{"type":"string","example":"SII"},"taxId":{"type":"string","example":"B12345678"},"businessName":{"type":"string","example":"My Store S.L."},"businessAddress":{"type":"object","additionalProperties":{"nullable":true},"example":{"street":"Calle Mayor 1","city":"Madrid","zip":"28001"}},"certPath":{"type":"string"},"isActive":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Invoice configuration updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"country":{"type":"string"},"format":{"type":"string"},"taxId":{"type":"string","nullable":true},"businessName":{"type":"string","nullable":true},"businessAddress":{"nullable":true},"certPath":{"type":"string","nullable":true},"isActive":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","country","format","taxId","businessName","certPath","isActive","createdAt","updatedAt"]}},"required":["data"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tenants/me/theme":{"get":{"tags":["Settings"],"summary":"Get current tenant theme tokens","description":"Returns the persisted theme tokens for the current tenant. If none have been saved yet, returns the default theme with `isDefault: true` and `theme_version: 0`.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Theme tokens","content":{"application/json":{"schema":{"type":"object","properties":{"theme":{"$ref":"#/components/schemas/ThemeTokens"},"isDefault":{"type":"boolean","example":false},"theme_version":{"type":"integer","minimum":0,"example":1716120000000}},"required":["theme","isDefault","theme_version"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Settings"],"summary":"Update tenant theme tokens","description":"Merges a partial theme patch into the current tenant theme and persists it. Requires admin or owner role. Bumps `theme_version` to `Date.now()` so the storefront cache key auto-invalidates.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThemeTokensPatch"}}}},"responses":{"200":{"description":"Theme updated","content":{"application/json":{"schema":{"type":"object","properties":{"theme":{"$ref":"#/components/schemas/ThemeTokens"},"isDefault":{"type":"boolean","example":false},"theme_version":{"type":"integer","minimum":0,"example":1716120000000}},"required":["theme","isDefault","theme_version"]}}}},"400":{"description":"Validation error (e.g. malformed OKLCH color)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden – requires admin or owner role","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}}}}},"/v1/tenants/me/theme/logo":{"post":{"tags":["Settings"],"summary":"Upload tenant theme logo","description":"Uploads the tenant logo to R2 and returns its durable CDN URL. Store the URL in the theme tokens via PATCH /tenants/me/theme. Requires admin or owner role.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"201":{"description":"Logo uploaded","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Durable CDN URL of the uploaded logo"}},"required":["url"]}}}},"400":{"description":"No file provided","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden – requires admin or owner role","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"422":{"description":"Invalid file type/size","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}}}}},"/v1/tenants/me/theme/preview-session":{"post":{"tags":["Settings"],"summary":"Create a theme-preview session (draft snapshot)","description":"Snapshots the provided DRAFT theme tokens in KV under an opaque random token with a 15-minute TTL. The storefront `/preview/theme?draft=<token>` route resolves the snapshot server-side (no cookies — immune to Safari ITP) so the preview iframe first-paints with the draft theme. Requires admin or owner role.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThemePreviewSessionRequest"}}}},"responses":{"201":{"description":"Preview session created","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","example":"2kD1x9uYpQnLg4bZfW0Hqw"},"expiresAt":{"type":"string","example":"2026-07-08T12:15:00.000Z"},"ttlSeconds":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":900}},"required":["token","expiresAt","ttlSeconds"]}}}},"400":{"description":"Validation error (malformed theme tokens)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden – requires admin or owner role","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}},"503":{"description":"Preview-session store unavailable (no KV binding)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["type","title","status"]}}}}}}},"/v1/discounts":{"get":{"tags":["Discounts"],"summary":"List discount codes","description":"Returns paginated discount codes for the current tenant with usage stats and validity info.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","enum":["true","false"],"example":"true","description":"Filter by active status"},"required":false,"description":"Filter by active status","name":"isActive","in":"query"}],"responses":{"200":{"description":"Paginated list of discounts","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"disc_01abc2def3gh"},"code":{"type":"string","example":"SUMMER20"},"type":{"type":"string","enum":["percentage","fixed_amount","free_shipping"],"example":"percentage"},"value":{"type":"integer","example":2000,"description":"Discount value: percentage (e.g. 2000 = 20.00%) or fixed amount in cents"},"minPurchaseAmount":{"type":"integer","nullable":true,"example":5000,"description":"Minimum order total in cents"},"maxUses":{"type":"integer","nullable":true,"example":100,"description":"Maximum total uses, null for unlimited"},"usedCount":{"type":"integer","example":0,"description":"Current usage count"},"appliesToType":{"type":"string","enum":["all","specific_products","specific_categories"],"example":"all"},"appliesToIds":{"type":"array","nullable":true,"items":{"type":"string"},"example":null},"startsAt":{"type":"string","nullable":true,"example":"2025-06-01T00:00:00.000Z"},"endsAt":{"type":"string","nullable":true,"example":"2025-08-31T23:59:59.000Z"},"isActive":{"type":"boolean","example":true},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"remainingUses":{"type":"integer","nullable":true,"example":95,"description":"Remaining uses (null if unlimited)"}},"required":["id","code","type","value","minPurchaseAmount","maxUses","usedCount","appliesToType","appliesToIds","startsAt","endsAt","isActive","createdAt","updatedAt","remainingUses"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Discounts"],"summary":"Create a discount","description":"Creates a new discount code with type, value, and usage limits.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","minLength":1,"maxLength":50,"example":"SUMMER20"},"type":{"type":"string","enum":["percentage","fixed_amount","free_shipping"],"example":"percentage"},"value":{"type":"integer","minimum":0,"example":2000,"description":"Percentage (e.g. 2000 = 20%) or fixed amount in cents"},"minPurchaseAmount":{"type":"integer","minimum":0,"example":5000},"maxUses":{"type":"integer","minimum":1,"example":100},"appliesToType":{"type":"string","enum":["all","specific_products","specific_categories"],"default":"all","example":"all"},"appliesToIds":{"type":"array","items":{"type":"string"},"example":null},"startsAt":{"type":"string","format":"date-time","example":"2025-06-01T00:00:00.000Z"},"endsAt":{"type":"string","format":"date-time","example":"2025-08-31T23:59:59.000Z"},"isActive":{"type":"boolean","default":true,"example":true}},"required":["code","type","value"]}}}},"responses":{"201":{"description":"Discount created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"disc_01abc2def3gh"},"code":{"type":"string","example":"SUMMER20"},"type":{"type":"string","enum":["percentage","fixed_amount","free_shipping"],"example":"percentage"},"value":{"type":"integer","example":2000,"description":"Discount value: percentage (e.g. 2000 = 20.00%) or fixed amount in cents"},"minPurchaseAmount":{"type":"integer","nullable":true,"example":5000,"description":"Minimum order total in cents"},"maxUses":{"type":"integer","nullable":true,"example":100,"description":"Maximum total uses, null for unlimited"},"usedCount":{"type":"integer","example":0,"description":"Current usage count"},"appliesToType":{"type":"string","enum":["all","specific_products","specific_categories"],"example":"all"},"appliesToIds":{"type":"array","nullable":true,"items":{"type":"string"},"example":null},"startsAt":{"type":"string","nullable":true,"example":"2025-06-01T00:00:00.000Z"},"endsAt":{"type":"string","nullable":true,"example":"2025-08-31T23:59:59.000Z"},"isActive":{"type":"boolean","example":true},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","code","type","value","minPurchaseAmount","maxUses","usedCount","appliesToType","appliesToIds","startsAt","endsAt","isActive","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Discount code already exists","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/discounts/validate":{"post":{"tags":["Discounts"],"summary":"Validate a discount code","description":"Validates a discount code against an order total. Returns discount details and calculated savings if valid.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","minLength":1,"example":"SUMMER20"},"orderTotal":{"type":"integer","minimum":0,"example":10000,"description":"Order total in cents"}},"required":["code","orderTotal"]}}}},"responses":{"200":{"description":"Discount is valid","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean","example":true},"discount":{"type":"object","properties":{"id":{"type":"string","example":"disc_01abc2def3gh"},"code":{"type":"string","example":"SUMMER20"},"type":{"type":"string","enum":["percentage","fixed_amount","free_shipping"],"example":"percentage"},"value":{"type":"integer","example":2000,"description":"Discount value: percentage (e.g. 2000 = 20.00%) or fixed amount in cents"},"minPurchaseAmount":{"type":"integer","nullable":true,"example":5000,"description":"Minimum order total in cents"}},"required":["id","code","type","value","minPurchaseAmount"],"description":"Discount details"},"savings":{"type":"integer","example":2000,"description":"Calculated savings in cents"}},"required":["valid","discount","savings"]}}}},"400":{"description":"Invalid, expired, or usage-exceeded discount code","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/discounts/apply":{"post":{"tags":["Discounts"],"summary":"Apply a discount to an order","description":"Validates and applies a discount code to an existing order. Updates order totals and increments the discount usage count.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"orderId":{"type":"string","minLength":1,"example":"ord_01abc2def3gh","description":"Order ID to apply the discount to"},"code":{"type":"string","minLength":1,"example":"SUMMER20","description":"Discount code to apply"}},"required":["orderId","code"]}}}},"responses":{"200":{"description":"Discount applied successfully","content":{"application/json":{"schema":{"type":"object","properties":{"order":{"type":"object","properties":{"id":{"type":"string"},"subtotal":{"type":"integer"},"shippingTotal":{"type":"integer"},"taxTotal":{"type":"integer"},"discountTotal":{"type":"integer"},"total":{"type":"integer"},"currency":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","subtotal","shippingTotal","taxTotal","discountTotal","total","currency","updatedAt"],"description":"Updated order totals"},"discount":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"type":{"type":"string","enum":["percentage","fixed_amount","free_shipping"]},"value":{"type":"integer"},"amount":{"type":"integer","description":"Actual discount amount applied in cents"}},"required":["id","code","type","value","amount"],"description":"Applied discount details"}},"required":["order","discount"]}}}},"400":{"description":"Invalid discount or order state","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Order or discount not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Discount already applied to this order","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/discounts/{id}":{"get":{"tags":["Discounts"],"summary":"Get discount by ID","description":"Returns the details of a specific discount code.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"disc_01abc2def3gh"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Discount details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"disc_01abc2def3gh"},"code":{"type":"string","example":"SUMMER20"},"type":{"type":"string","enum":["percentage","fixed_amount","free_shipping"],"example":"percentage"},"value":{"type":"integer","example":2000,"description":"Discount value: percentage (e.g. 2000 = 20.00%) or fixed amount in cents"},"minPurchaseAmount":{"type":"integer","nullable":true,"example":5000,"description":"Minimum order total in cents"},"maxUses":{"type":"integer","nullable":true,"example":100,"description":"Maximum total uses, null for unlimited"},"usedCount":{"type":"integer","example":0,"description":"Current usage count"},"appliesToType":{"type":"string","enum":["all","specific_products","specific_categories"],"example":"all"},"appliesToIds":{"type":"array","nullable":true,"items":{"type":"string"},"example":null},"startsAt":{"type":"string","nullable":true,"example":"2025-06-01T00:00:00.000Z"},"endsAt":{"type":"string","nullable":true,"example":"2025-08-31T23:59:59.000Z"},"isActive":{"type":"boolean","example":true},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"remainingUses":{"type":"integer","nullable":true,"example":95,"description":"Remaining uses (null if unlimited)"}},"required":["id","code","type","value","minPurchaseAmount","maxUses","usedCount","appliesToType","appliesToIds","startsAt","endsAt","isActive","createdAt","updatedAt","remainingUses"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Discount not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Discounts"],"summary":"Update a discount","description":"Updates an existing discount. Only provided fields are updated.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"disc_01abc2def3gh"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","minLength":1,"maxLength":50,"example":"SUMMER25"},"type":{"type":"string","enum":["percentage","fixed_amount","free_shipping"],"example":"percentage"},"value":{"type":"integer","minimum":0,"example":2500},"minPurchaseAmount":{"type":"integer","nullable":true,"minimum":0,"example":5000},"maxUses":{"type":"integer","nullable":true,"minimum":1,"example":200},"appliesToType":{"type":"string","enum":["all","specific_products","specific_categories"],"example":"all"},"appliesToIds":{"type":"array","nullable":true,"items":{"type":"string"},"example":null},"startsAt":{"type":"string","nullable":true,"format":"date-time","example":"2025-06-01T00:00:00.000Z"},"endsAt":{"type":"string","nullable":true,"format":"date-time","example":"2025-08-31T23:59:59.000Z"},"isActive":{"type":"boolean","example":true}}}}}},"responses":{"200":{"description":"Discount updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"disc_01abc2def3gh"},"code":{"type":"string","example":"SUMMER20"},"type":{"type":"string","enum":["percentage","fixed_amount","free_shipping"],"example":"percentage"},"value":{"type":"integer","example":2000,"description":"Discount value: percentage (e.g. 2000 = 20.00%) or fixed amount in cents"},"minPurchaseAmount":{"type":"integer","nullable":true,"example":5000,"description":"Minimum order total in cents"},"maxUses":{"type":"integer","nullable":true,"example":100,"description":"Maximum total uses, null for unlimited"},"usedCount":{"type":"integer","example":0,"description":"Current usage count"},"appliesToType":{"type":"string","enum":["all","specific_products","specific_categories"],"example":"all"},"appliesToIds":{"type":"array","nullable":true,"items":{"type":"string"},"example":null},"startsAt":{"type":"string","nullable":true,"example":"2025-06-01T00:00:00.000Z"},"endsAt":{"type":"string","nullable":true,"example":"2025-08-31T23:59:59.000Z"},"isActive":{"type":"boolean","example":true},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","code","type","value","minPurchaseAmount","maxUses","usedCount","appliesToType","appliesToIds","startsAt","endsAt","isActive","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Discount not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Discount code already exists","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Discounts"],"summary":"Delete a discount","description":"Permanently removes a discount code.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"disc_01abc2def3gh"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Discount deleted successfully"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Discount not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/shipping/calculate":{"post":{"tags":["Shipping"],"summary":"Calculate shipping rates","description":"Calculates applicable shipping methods and rates for a destination address and cart items.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"destination":{"type":"object","properties":{"country":{"type":"string","minLength":2,"maxLength":3,"example":"US","description":"ISO country code"},"state":{"type":"string","example":"CA","description":"State/province code"},"zip":{"type":"string","example":"90210","description":"Postal code"}},"required":["country"],"description":"Shipping destination"},"items":{"type":"array","items":{"type":"object","properties":{"price":{"type":"integer","minimum":0,"example":2999,"description":"Item price in cents"},"quantity":{"type":"integer","minimum":1,"example":2,"description":"Item quantity"},"weight":{"type":"number","minimum":0,"example":1.5,"description":"Item weight in kg"}},"required":["price","quantity"]},"minItems":1,"description":"Cart items"}},"required":["destination","items"]}}}},"responses":{"200":{"description":"Available shipping methods with calculated rates","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"methodId":{"type":"string","example":"shm_abc123def456"},"zoneName":{"type":"string","example":"Domestic"},"methodName":{"type":"string","example":"Standard Shipping"},"type":{"type":"string","enum":["flat_rate","free","weight_based","price_based"],"example":"flat_rate"},"price":{"type":"integer","example":999,"description":"Calculated shipping price in cents"}},"required":["methodId","zoneName","methodName","type","price"]}}},"required":["data"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/webhooks/shippo":{"post":{"tags":["Webhooks"],"summary":"Shippo tracking webhook","description":"Receives Shippo TrackingUpdated events. Verified via X-Shippo-Signature header.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","enum":["track_updated"]},"test":{"type":"boolean"},"data":{"type":"object","properties":{"tracking_number":{"type":"string"},"tracking_status":{"type":"object","properties":{"status":{"type":"string"},"status_details":{"type":"string"},"location":{"type":"object","nullable":true,"properties":{"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string"}}},"status_date":{"type":"string"}},"required":["status"]}},"required":["tracking_number","tracking_status"]}},"required":["event","data"]}}}},"responses":{"200":{"description":"Processed","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"error":{"type":"string"}},"required":["ok","error"]}}}}}}},"/v1/shipping/zones":{"get":{"tags":["Shipping"],"summary":"List shipping zones","description":"Returns all shipping zones for the tenant with their associated shipping methods and rates.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Shipping zones with methods","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"shz_abc123def456"},"name":{"type":"string","example":"Domestic"},"countries":{"type":"array","items":{"type":"string"},"example":["US","CA"]},"isDefault":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"methods":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"shm_abc123def456"},"zoneId":{"type":"string","example":"shz_abc123def456"},"name":{"type":"string","example":"Standard Shipping"},"type":{"type":"string","enum":["flat_rate","free","weight_based","price_based"],"example":"flat_rate"},"price":{"type":"integer","example":999},"minOrderAmount":{"type":"integer","nullable":true,"example":null},"maxOrderAmount":{"type":"integer","nullable":true,"example":null},"isActive":{"type":"boolean","example":true},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","zoneId","name","type","price","minOrderAmount","maxOrderAmount","isActive","createdAt","updatedAt"]}}},"required":["id","name","countries","isDefault","createdAt","updatedAt","methods"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Shipping"],"summary":"Create a shipping zone","description":"Creates a new shipping zone with associated countries.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Domestic","description":"Shipping zone name"},"countries":{"type":"array","items":{"type":"string","minLength":2,"maxLength":3},"minItems":1,"example":["US","CA"],"description":"Array of ISO country codes"},"isDefault":{"type":"boolean","example":false,"description":"Whether this is the default/fallback zone"}},"required":["name","countries"]}}}},"responses":{"201":{"description":"Shipping zone created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"shz_abc123def456"},"name":{"type":"string","example":"Domestic"},"countries":{"type":"array","items":{"type":"string"},"example":["US","CA"]},"isDefault":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","countries","isDefault","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Zone name already exists","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/shipping/zones/{id}":{"patch":{"tags":["Shipping"],"summary":"Update a shipping zone","description":"Updates an existing shipping zone.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"shz_abc123def456","description":"Shipping zone ID"},"required":true,"description":"Shipping zone ID","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Domestic","description":"Shipping zone name"},"countries":{"type":"array","items":{"type":"string","minLength":2,"maxLength":3},"minItems":1,"example":["US","CA"],"description":"Array of ISO country codes"},"isDefault":{"type":"boolean","example":false,"description":"Whether this is the default/fallback zone"}}}}}},"responses":{"200":{"description":"Shipping zone updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"shz_abc123def456"},"name":{"type":"string","example":"Domestic"},"countries":{"type":"array","items":{"type":"string"},"example":["US","CA"]},"isDefault":{"type":"boolean","example":false},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","name","countries","isDefault","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Zone not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Zone name already exists","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Shipping"],"summary":"Delete a shipping zone","description":"Deletes a shipping zone and its associated shipping methods.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"shz_abc123def456","description":"Shipping zone ID"},"required":true,"description":"Shipping zone ID","name":"id","in":"path"}],"responses":{"204":{"description":"Shipping zone deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Zone not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/shipping/zones/{zoneId}/methods":{"get":{"tags":["Shipping"],"summary":"List shipping methods for a zone","description":"Returns all shipping methods belonging to the specified zone.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"shz_abc123def456","description":"Shipping zone ID"},"required":true,"description":"Shipping zone ID","name":"zoneId","in":"path"}],"responses":{"200":{"description":"Shipping methods list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"shm_abc123def456"},"zoneId":{"type":"string","example":"shz_abc123def456"},"name":{"type":"string","example":"Standard Shipping"},"type":{"type":"string","enum":["flat_rate","free","weight_based","price_based"],"example":"flat_rate"},"price":{"type":"integer","example":999},"minOrderAmount":{"type":"integer","nullable":true,"example":null},"maxOrderAmount":{"type":"integer","nullable":true,"example":null},"isActive":{"type":"boolean","example":true},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","zoneId","name","type","price","minOrderAmount","maxOrderAmount","isActive","createdAt","updatedAt"]}}},"required":["data"]}}}},"404":{"description":"Zone not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Shipping"],"summary":"Create a shipping method","description":"Creates a new shipping method within the specified zone.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"shz_abc123def456","description":"Shipping zone ID"},"required":true,"description":"Shipping zone ID","name":"zoneId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Standard Shipping","description":"Method name"},"type":{"type":"string","enum":["flat_rate","free","weight_based","price_based"],"example":"flat_rate","description":"Shipping rate type"},"price":{"type":"integer","minimum":0,"example":999,"description":"Price in cents"},"minOrderAmount":{"type":"integer","nullable":true,"minimum":0,"example":null,"description":"Minimum order amount in cents"},"maxOrderAmount":{"type":"integer","nullable":true,"minimum":0,"example":null,"description":"Maximum order amount in cents"},"isActive":{"type":"boolean","example":true,"description":"Whether this method is active"}},"required":["name","type"]}}}},"responses":{"201":{"description":"Shipping method created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"shm_abc123def456"},"zoneId":{"type":"string","example":"shz_abc123def456"},"name":{"type":"string","example":"Standard Shipping"},"type":{"type":"string","enum":["flat_rate","free","weight_based","price_based"],"example":"flat_rate"},"price":{"type":"integer","example":999},"minOrderAmount":{"type":"integer","nullable":true,"example":null},"maxOrderAmount":{"type":"integer","nullable":true,"example":null},"isActive":{"type":"boolean","example":true},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","zoneId","name","type","price","minOrderAmount","maxOrderAmount","isActive","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Zone not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/shipping/zones/{zoneId}/methods/{methodId}":{"patch":{"tags":["Shipping"],"summary":"Update a shipping method","description":"Updates an existing shipping method within the specified zone.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"shz_abc123def456","description":"Shipping zone ID"},"required":true,"description":"Shipping zone ID","name":"zoneId","in":"path"},{"schema":{"type":"string","example":"shm_abc123def456","description":"Shipping method ID"},"required":true,"description":"Shipping method ID","name":"methodId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Standard Shipping","description":"Method name"},"type":{"type":"string","enum":["flat_rate","free","weight_based","price_based"],"example":"flat_rate","description":"Shipping rate type"},"price":{"type":"integer","minimum":0,"example":999,"description":"Price in cents"},"minOrderAmount":{"type":"integer","nullable":true,"minimum":0,"example":null,"description":"Minimum order amount in cents"},"maxOrderAmount":{"type":"integer","nullable":true,"minimum":0,"example":null,"description":"Maximum order amount in cents"},"isActive":{"type":"boolean","example":true,"description":"Whether this method is active"}}}}}},"responses":{"200":{"description":"Shipping method updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"shm_abc123def456"},"zoneId":{"type":"string","example":"shz_abc123def456"},"name":{"type":"string","example":"Standard Shipping"},"type":{"type":"string","enum":["flat_rate","free","weight_based","price_based"],"example":"flat_rate"},"price":{"type":"integer","example":999},"minOrderAmount":{"type":"integer","nullable":true,"example":null},"maxOrderAmount":{"type":"integer","nullable":true,"example":null},"isActive":{"type":"boolean","example":true},"createdAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","example":"2025-01-01T00:00:00.000Z"}},"required":["id","zoneId","name","type","price","minOrderAmount","maxOrderAmount","isActive","createdAt","updatedAt"]}}}},"404":{"description":"Zone or method not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Shipping"],"summary":"Delete a shipping method","description":"Deletes a shipping method from the specified zone.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"shz_abc123def456","description":"Shipping zone ID"},"required":true,"description":"Shipping zone ID","name":"zoneId","in":"path"},{"schema":{"type":"string","example":"shm_abc123def456","description":"Shipping method ID"},"required":true,"description":"Shipping method ID","name":"methodId","in":"path"}],"responses":{"204":{"description":"Shipping method deleted"},"404":{"description":"Zone or method not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/carrier-accounts":{"get":{"tags":["Carrier Accounts"],"summary":"List carrier accounts","description":"Returns all carrier accounts (credentials are masked).","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Carrier accounts list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"ca_01abc123"},"carrier":{"type":"string","enum":["shippo","easypost","ups","dhl","fedex","usps","manual","packlink","sendcloud"]},"displayName":{"type":"string","nullable":true},"isActive":{"type":"integer"},"isTestMode":{"type":"integer"},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","carrier","displayName","isActive","isTestMode","createdAt","updatedAt"]}}},"required":["data"]}}}}}},"post":{"tags":["Carrier Accounts"],"summary":"Create carrier account","description":"Creates a new carrier account. Credentials are encrypted with AES-GCM before storage.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"carrier":{"type":"string","enum":["shippo","easypost","ups","dhl","fedex","usps","manual","packlink","sendcloud"],"example":"shippo"},"displayName":{"type":"string","minLength":1,"maxLength":100,"example":"Shippo Production"},"credentials":{"type":"object","additionalProperties":{"type":"string"},"example":{"apiKey":"shippo_live_xxx"}},"isTestMode":{"type":"boolean","default":false,"example":false}},"required":["carrier","credentials"]}}}},"responses":{"201":{"description":"Carrier account created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"carrier":{"type":"string"},"displayName":{"type":"string","nullable":true},"isActive":{"type":"number"},"isTestMode":{"type":"number"},"createdAt":{"type":"number"}},"required":["id","carrier","displayName","isActive","isTestMode","createdAt"]}},"required":["data"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/carrier-accounts/:id":{"patch":{"tags":["Carrier Accounts"],"summary":"Update carrier account metadata","description":"Updates displayName, isActive, or isTestMode. Credentials cannot be changed here — use rotate-credentials.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"displayName":{"type":"string","minLength":1,"maxLength":100,"example":"Shippo Staging"},"isActive":{"type":"boolean","example":true},"isTestMode":{"type":"boolean","example":false}}}}}},"responses":{"200":{"description":"Updated carrier account","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"carrier":{"type":"string"},"displayName":{"type":"string","nullable":true},"isActive":{"type":"number"},"isTestMode":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","carrier","displayName","isActive","isTestMode","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Carrier Accounts"],"summary":"Deactivate carrier account","description":"Soft-deletes by setting isActive=0. Row is preserved.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Carrier account deactivated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"isActive":{"type":"number"}},"required":["id","isActive"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/carrier-accounts/:id/rotate-credentials":{"post":{"tags":["Carrier Accounts"],"summary":"Rotate carrier credentials","description":"Re-encrypts and replaces stored credentials with newCredentials.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"newCredentials":{"type":"object","additionalProperties":{"type":"string"},"example":{"apiKey":"shippo_live_new_xxx"}}},"required":["newCredentials"]}}}},"responses":{"200":{"description":"Credentials rotated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"updatedAt":{"type":"number"}},"required":["id","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/shipping/rates/live":{"post":{"tags":["Shipping"],"summary":"Get live shipping rates","description":"Fetches real-time rates from Shippo using the active carrier account.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fromAddress":{"type":"object","properties":{"name":{"type":"string","example":"John Doe"},"street1":{"type":"string","example":"215 Clayton St"},"city":{"type":"string","example":"San Francisco"},"state":{"type":"string","example":"CA"},"zip":{"type":"string","example":"94117"},"country":{"type":"string","minLength":2,"maxLength":2,"example":"US"},"phone":{"type":"string"},"email":{"type":"string","format":"email"}},"required":["name","street1","city","state","zip","country"]},"toAddress":{"type":"object","properties":{"name":{"type":"string","example":"John Doe"},"street1":{"type":"string","example":"215 Clayton St"},"city":{"type":"string","example":"San Francisco"},"state":{"type":"string","example":"CA"},"zip":{"type":"string","example":"94117"},"country":{"type":"string","minLength":2,"maxLength":2,"example":"US"},"phone":{"type":"string"},"email":{"type":"string","format":"email"}},"required":["name","street1","city","state","zip","country"]},"parcels":{"type":"array","items":{"type":"object","properties":{"lengthMm":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":200},"widthMm":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":150},"heightMm":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":100},"weightGrams":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":500}},"required":["lengthMm","widthMm","heightMm","weightGrams"]},"minItems":1,"description":"List of parcels to ship"},"carrier":{"type":"string","enum":["shippo","packlink","sendcloud"],"default":"shippo","example":"shippo"}},"required":["fromAddress","toAddress","parcels"]}}}},"responses":{"200":{"description":"Available live rates","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"rateId":{"type":"string","example":"adcfdddf8ec64b84ad22772bce3ea37a"},"carrier":{"type":"string","example":"USPS"},"service":{"type":"string","example":"Priority Mail"},"amountCents":{"type":"integer","example":599},"currency":{"type":"string","example":"USD"},"estimatedDays":{"type":"integer","nullable":true,"example":2},"carrierLogoUrl":{"type":"string","example":"https://shippo-static.s3.amazonaws.com/providers/75/USPS.png"},"dropoff":{"type":"boolean"}},"required":["rateId","carrier","service","amountCents","currency","estimatedDays","carrierLogoUrl"]}}},"required":["data"]}}}},"400":{"description":"No active carrier account","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}},"502":{"description":"Carrier provider error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/:orderId/shipments":{"post":{"tags":["Shipments"],"summary":"Purchase label and create shipment","description":"Buys a shipping label (Shippo by default; Packlink PRO / Sendcloud via `carrier`), uploads the label to R2, creates an order_shipments record, and updates order tracking. For international Shippo shipments, generates a customs declaration automatically.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"orderId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"rateId":{"type":"string","example":"adcfdddf8ec64b84ad22772bce3ea37a"},"labelFormat":{"type":"string","enum":["pdf","png","zpl"],"default":"pdf"},"fromWarehouseId":{"type":"string","example":"wh_01abc123"},"carrier":{"type":"string","enum":["shippo","packlink","sendcloud"],"default":"shippo","example":"shippo"}},"required":["rateId"]}}}},"responses":{"201":{"description":"Shipment created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"orderId":{"type":"string"},"shipmentNumber":{"type":"string"},"carrier":{"type":"string"},"carrierService":{"type":"string","nullable":true},"carrierTransactionId":{"type":"string","nullable":true},"trackingNumber":{"type":"string","nullable":true},"trackingUrl":{"type":"string","nullable":true},"labelUrl":{"type":"string","nullable":true},"labelFormat":{"type":"string"},"status":{"type":"string"},"costCents":{"type":"integer","nullable":true},"currency":{"type":"string","nullable":true},"customsDeclarationId":{"type":"string","nullable":true},"createdAt":{"type":"integer"}},"required":["id","orderId","shipmentNumber","carrier","carrierService","carrierTransactionId","trackingNumber","trackingUrl","labelUrl","labelFormat","status","costCents","currency","customsDeclarationId","createdAt"]}},"required":["data"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}},"502":{"description":"Carrier provider error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"get":{"tags":["Shipments"],"summary":"List shipments for order","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"orderId","in":"path"}],"responses":{"200":{"description":"Shipments list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"orderId":{"type":"string"},"shipmentNumber":{"type":"string"},"carrier":{"type":"string"},"carrierService":{"type":"string","nullable":true},"trackingNumber":{"type":"string","nullable":true},"trackingUrl":{"type":"string","nullable":true},"labelUrl":{"type":"string","nullable":true},"labelFormat":{"type":"string"},"status":{"type":"string"},"costCents":{"type":"integer","nullable":true},"currency":{"type":"string","nullable":true},"estimatedDeliveryAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","orderId","shipmentNumber","carrier","carrierService","trackingNumber","trackingUrl","labelUrl","labelFormat","status","costCents","currency","estimatedDeliveryAt","createdAt","updatedAt"]}}},"required":["data"]}}}}}}},"/v1/shipments/:id":{"get":{"tags":["Shipments"],"summary":"Get shipment detail with tracking events","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Shipment detail","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"orderId":{"type":"string"},"shipmentNumber":{"type":"string"},"carrier":{"type":"string"},"carrierService":{"type":"string","nullable":true},"carrierShipmentId":{"type":"string","nullable":true},"carrierTransactionId":{"type":"string","nullable":true},"trackingNumber":{"type":"string","nullable":true},"trackingUrl":{"type":"string","nullable":true},"labelUrl":{"type":"string","nullable":true},"labelFormat":{"type":"string"},"status":{"type":"string"},"costCents":{"type":"integer","nullable":true},"currency":{"type":"string","nullable":true},"weightGrams":{"type":"integer","nullable":true},"estimatedDeliveryAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"trackingEvents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"eventType":{"type":"string"},"description":{"type":"string","nullable":true},"location":{"type":"string","nullable":true},"eventAt":{"type":"integer"},"createdAt":{"type":"integer"}},"required":["id","eventType","description","location","eventAt","createdAt"]}}},"required":["id","orderId","shipmentNumber","carrier","carrierService","carrierShipmentId","carrierTransactionId","trackingNumber","trackingUrl","labelUrl","labelFormat","status","costCents","currency","weightGrams","estimatedDeliveryAt","createdAt","updatedAt","trackingEvents"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/shipments/:id/refresh-tracking":{"post":{"tags":["Shipments"],"summary":"Poll the carrier aggregator for fresh tracking events","description":"For Packlink/Sendcloud shipments: fetches tracking from the provider, appends new tracking_events, updates the shipment status (and the order on delivery). Shippo shipments are tracked via webhook instead.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Tracking refreshed","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"shipmentId":{"type":"string"},"status":{"type":"string"},"eventsAdded":{"type":"integer"},"events":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string"},"eventType":{"type":"string"},"description":{"type":"string","nullable":true},"location":{"type":"string","nullable":true},"occurredAt":{"type":"integer"}},"required":["status","eventType","description","location","occurredAt"]}}},"required":["shipmentId","status","eventsAdded","events"]}},"required":["data"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}},"502":{"description":"Carrier provider error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/shipping/rates/live/international":{"post":{"tags":["Shipping"],"summary":"Get live international shipping rates","description":"Fetches real-time rates from Shippo and filters to only return carriers that support international shipments (UPS Worldwide, DHL Express, USPS International, FedEx International). All results include `customsRequired: true`.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fromAddress":{"type":"object","properties":{"name":{"type":"string"},"street1":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string","minLength":2,"maxLength":2},"phone":{"type":"string"},"email":{"type":"string","format":"email"}},"required":["name","street1","city","state","zip","country"]},"toAddress":{"type":"object","properties":{"name":{"type":"string"},"street1":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string","minLength":2,"maxLength":2},"phone":{"type":"string"},"email":{"type":"string","format":"email"}},"required":["name","street1","city","state","zip","country"]},"parcels":{"type":"array","items":{"type":"object","properties":{"lengthMm":{"type":"integer","minimum":0,"exclusiveMinimum":true},"widthMm":{"type":"integer","minimum":0,"exclusiveMinimum":true},"heightMm":{"type":"integer","minimum":0,"exclusiveMinimum":true},"weightGrams":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["lengthMm","widthMm","heightMm","weightGrams"]},"minItems":1}},"required":["fromAddress","toAddress","parcels"]}}}},"responses":{"200":{"description":"International rates","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"rateId":{"type":"string"},"carrier":{"type":"string"},"service":{"type":"string"},"amountCents":{"type":"integer"},"currency":{"type":"string"},"estimatedDays":{"type":"integer","nullable":true},"carrierLogoUrl":{"type":"string"},"customsRequired":{"type":"boolean","enum":[true]}},"required":["rateId","carrier","service","amountCents","currency","estimatedDays","carrierLogoUrl","customsRequired"]}}},"required":["data"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/:id/customs-declaration":{"get":{"tags":["Customs"],"summary":"Get customs declaration for an order","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Customs declaration with items","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"shipmentId":{"type":"string"},"orderId":{"type":"string"},"declarationType":{"type":"string"},"reasonForExport":{"type":"string"},"incoterm":{"type":"string"},"totalValueCents":{"type":"integer"},"currency":{"type":"string"},"totalWeightGrams":{"type":"integer"},"iossNumber":{"type":"string","nullable":true},"eoriNumber":{"type":"string","nullable":true},"importerTaxId":{"type":"string","nullable":true},"nonDeliveryOption":{"type":"string"},"certify":{"type":"integer"},"certifySigner":{"type":"string","nullable":true},"shippoCustomsId":{"type":"string","nullable":true},"customsFormUrl":{"type":"string","nullable":true},"createdAt":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"declarationId":{"type":"string"},"orderItemId":{"type":"string","nullable":true},"description":{"type":"string"},"hsCode":{"type":"string","nullable":true},"originCountry":{"type":"string"},"quantity":{"type":"integer"},"valueAmountCents":{"type":"integer"},"weightGrams":{"type":"integer"},"currency":{"type":"string"},"tariffNumber":{"type":"string","nullable":true},"createdAt":{"type":"integer"}},"required":["id","declarationId","orderItemId","description","hsCode","originCountry","quantity","valueAmountCents","weightGrams","currency","tariffNumber","createdAt"]}}},"required":["id","shipmentId","orderId","declarationType","reasonForExport","incoterm","totalValueCents","currency","totalWeightGrams","iossNumber","eoriNumber","importerTaxId","nonDeliveryOption","certify","certifySigner","shippoCustomsId","customsFormUrl","createdAt"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Customs"],"summary":"Manually create or regenerate customs declaration for an order","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"regenerate":{"type":"boolean","default":false},"reasonForExport":{"type":"string","enum":["sold","gift","sample","return","repair","other"],"default":"sold"}}}}}},"responses":{"201":{"description":"Customs declaration created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"shipmentId":{"type":"string"},"orderId":{"type":"string"},"declarationType":{"type":"string"},"reasonForExport":{"type":"string"},"incoterm":{"type":"string"},"totalValueCents":{"type":"integer"},"currency":{"type":"string"},"totalWeightGrams":{"type":"integer"},"iossNumber":{"type":"string","nullable":true},"eoriNumber":{"type":"string","nullable":true},"importerTaxId":{"type":"string","nullable":true},"nonDeliveryOption":{"type":"string"},"certify":{"type":"integer"},"certifySigner":{"type":"string","nullable":true},"shippoCustomsId":{"type":"string","nullable":true},"customsFormUrl":{"type":"string","nullable":true},"createdAt":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"declarationId":{"type":"string"},"orderItemId":{"type":"string","nullable":true},"description":{"type":"string"},"hsCode":{"type":"string","nullable":true},"originCountry":{"type":"string"},"quantity":{"type":"integer"},"valueAmountCents":{"type":"integer"},"weightGrams":{"type":"integer"},"currency":{"type":"string"},"tariffNumber":{"type":"string","nullable":true},"createdAt":{"type":"integer"}},"required":["id","declarationId","orderItemId","description","hsCode","originCountry","quantity","valueAmountCents","weightGrams","currency","tariffNumber","createdAt"]}}},"required":["id","shipmentId","orderId","declarationType","reasonForExport","incoterm","totalValueCents","currency","totalWeightGrams","iossNumber","eoriNumber","importerTaxId","nonDeliveryOption","certify","certifySigner","shippoCustomsId","customsFormUrl","createdAt"]}},"required":["data"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/customs-declarations":{"get":{"tags":["Customs"],"summary":"List customs declarations (admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","default":"1"},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","default":"25"},"required":false,"name":"perPage","in":"query"}],"responses":{"200":{"description":"Paginated customs declarations list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"shipmentId":{"type":"string"},"orderId":{"type":"string"},"declarationType":{"type":"string"},"reasonForExport":{"type":"string"},"incoterm":{"type":"string"},"totalValueCents":{"type":"integer"},"currency":{"type":"string"},"totalWeightGrams":{"type":"integer"},"iossNumber":{"type":"string","nullable":true},"eoriNumber":{"type":"string","nullable":true},"importerTaxId":{"type":"string","nullable":true},"nonDeliveryOption":{"type":"string"},"certify":{"type":"integer"},"certifySigner":{"type":"string","nullable":true},"shippoCustomsId":{"type":"string","nullable":true},"customsFormUrl":{"type":"string","nullable":true},"createdAt":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"declarationId":{"type":"string"},"orderItemId":{"type":"string","nullable":true},"description":{"type":"string"},"hsCode":{"type":"string","nullable":true},"originCountry":{"type":"string"},"quantity":{"type":"integer"},"valueAmountCents":{"type":"integer"},"weightGrams":{"type":"integer"},"currency":{"type":"string"},"tariffNumber":{"type":"string","nullable":true},"createdAt":{"type":"integer"}},"required":["id","declarationId","orderItemId","description","hsCode","originCountry","quantity","valueAmountCents","weightGrams","currency","tariffNumber","createdAt"]}}},"required":["id","shipmentId","orderId","declarationType","reasonForExport","incoterm","totalValueCents","currency","totalWeightGrams","iossNumber","eoriNumber","importerTaxId","nonDeliveryOption","certify","certifySigner","shippoCustomsId","customsFormUrl","createdAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"perPage":{"type":"number"},"total":{"type":"number"}},"required":["page","perPage","total"]}},"required":["data","pagination"]}}}}}}},"/v1/customs-declarations/:id":{"get":{"tags":["Customs"],"summary":"Get customs declaration detail with items","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Customs declaration detail","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"shipmentId":{"type":"string"},"orderId":{"type":"string"},"declarationType":{"type":"string"},"reasonForExport":{"type":"string"},"incoterm":{"type":"string"},"totalValueCents":{"type":"integer"},"currency":{"type":"string"},"totalWeightGrams":{"type":"integer"},"iossNumber":{"type":"string","nullable":true},"eoriNumber":{"type":"string","nullable":true},"importerTaxId":{"type":"string","nullable":true},"nonDeliveryOption":{"type":"string"},"certify":{"type":"integer"},"certifySigner":{"type":"string","nullable":true},"shippoCustomsId":{"type":"string","nullable":true},"customsFormUrl":{"type":"string","nullable":true},"createdAt":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"declarationId":{"type":"string"},"orderItemId":{"type":"string","nullable":true},"description":{"type":"string"},"hsCode":{"type":"string","nullable":true},"originCountry":{"type":"string"},"quantity":{"type":"integer"},"valueAmountCents":{"type":"integer"},"weightGrams":{"type":"integer"},"currency":{"type":"string"},"tariffNumber":{"type":"string","nullable":true},"createdAt":{"type":"integer"}},"required":["id","declarationId","orderItemId","description","hsCode","originCountry","quantity","valueAmountCents","weightGrams","currency","tariffNumber","createdAt"]}}},"required":["id","shipmentId","orderId","declarationType","reasonForExport","incoterm","totalValueCents","currency","totalWeightGrams","iossNumber","eoriNumber","importerTaxId","nonDeliveryOption","certify","certifySigner","shippoCustomsId","customsFormUrl","createdAt"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/newsletter/subscribe":{"post":{"tags":["Newsletter"],"summary":"Subscribe to newsletter","description":"Subscribe an email address to the store newsletter.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeNewsletter"}}}},"responses":{"200":{"description":"Subscription result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeNewsletterResponse"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterError"}}}}}}},"/v1/newsletter/unsubscribe":{"post":{"tags":["Newsletter"],"summary":"Unsubscribe from newsletter","description":"Unsubscribe an email address from the store newsletter.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnsubscribeNewsletter"}}}},"responses":{"200":{"description":"Unsubscription result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnsubscribeNewsletterResponse"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterError"}}}}}}},"/v1/newsletter/subscribers":{"get":{"tags":["Newsletter"],"summary":"List newsletter subscribers","description":"Returns a paginated list of newsletter subscribers. Supports filtering, sorting, and search.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"1","description":"Page number (default: 1)"},"required":false,"description":"Page number (default: 1)","name":"page","in":"query"},{"schema":{"type":"string","example":"25","description":"Items per page (max 100)"},"required":false,"description":"Items per page (max 100)","name":"limit","in":"query"},{"schema":{"type":"string","example":"-createdAt","description":"Sort field. Prefix - for desc. Fields: email, subscribedAt, createdAt"},"required":false,"description":"Sort field. Prefix - for desc. Fields: email, subscribedAt, createdAt","name":"sort","in":"query"},{"schema":{"type":"string","example":"id,email,firstName,lastName","description":"Fields to return (csv)"},"required":false,"description":"Fields to return (csv)","name":"fields","in":"query"},{"schema":{"type":"string","description":"Full-text search in: email"},"required":false,"description":"Full-text search in: email","name":"search","in":"query"}],"responses":{"200":{"description":"Paginated list of subscribers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterError"}}}}}}},"/v1/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhook endpoints","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"1","description":"Page number (default: 1)"},"required":false,"description":"Page number (default: 1)","name":"page","in":"query"},{"schema":{"type":"string","example":"25","description":"Items per page (max 100)"},"required":false,"description":"Items per page (max 100)","name":"limit","in":"query"},{"schema":{"type":"string","example":"-createdAt","description":"Sort field. Prefix - for desc. Fields: createdAt, updatedAt"},"required":false,"description":"Sort field. Prefix - for desc. Fields: createdAt, updatedAt","name":"sort","in":"query"},{"schema":{"type":"string","example":"id,tenantId,url,events","description":"Fields to return (csv)"},"required":false,"description":"Fields to return (csv)","name":"fields","in":"query"},{"schema":{"type":"string","description":"Full-text search in: url"},"required":false,"description":"Full-text search in: url","name":"search","in":"query"}],"responses":{"200":{"description":"List of webhook endpoints","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Webhooks"],"summary":"Create webhook endpoint","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookEndpoint"}}}},"responses":{"201":{"description":"Webhook endpoint created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/webhooks/{id}":{"patch":{"tags":["Webhooks"],"summary":"Update webhook endpoint","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookEndpoint"}}}},"responses":{"200":{"description":"Webhook endpoint updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Webhooks"],"summary":"Delete webhook endpoint","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Webhook endpoint deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/webhooks/{id}/deliveries":{"get":{"tags":["Webhooks"],"summary":"List webhook deliveries","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"page","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Paginated delivery log","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/webhooks/deliveries/{id}/retry":{"post":{"tags":["Webhooks"],"summary":"Manually retry a webhook delivery","description":"Resets a failed or exhausted delivery and re-enqueues it. Admin only.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Delivery re-enqueued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRetryResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Admin role required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Delivery not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Delivery already delivered or in a non-retryable state","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/webhooks/{id}/test":{"post":{"tags":["Webhooks"],"summary":"Send a test webhook event","description":"Dispatches a synthetic test event to the webhook endpoint. Admin only.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestWebhookBody"}}}},"responses":{"202":{"description":"Test event accepted for delivery","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestWebhookResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Admin role required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Webhook endpoint not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/webhooks/{id}/deliveries/{deliveryId}":{"get":{"tags":["Webhooks"],"summary":"Get webhook delivery detail","description":"Returns full detail for a single webhook delivery, including request/response bodies. Admin only.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"deliveryId","in":"path"}],"responses":{"200":{"description":"Delivery detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryDetail"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Admin role required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Delivery not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/webhooks/{id}/deliveries/{deliveryId}/retry":{"post":{"tags":["Webhooks"],"summary":"Retry a webhook delivery (tenant-scoped path)","description":"Resets a failed or exhausted delivery and re-enqueues it. Verifies the delivery belongs to the specified endpoint and tenant. Admin only.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"deliveryId","in":"path"}],"responses":{"200":{"description":"Delivery re-enqueued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookScopedRetryResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Admin role required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Delivery not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Delivery already delivered or in a non-retryable state","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/webhooks-v2":{"get":{"tags":["Webhooks V2"],"summary":"List webhook v2 subscriptions","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of subscriptions","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"url":{"type":"string","format":"uri"},"eventTypes":{"type":"array","items":{"type":"string","enum":["order.created","order.updated","order.cancelled","order.fulfilled","order.refunded","product.created","product.updated","product.deleted","customer.created","customer.updated","payment.succeeded","payment.failed","payment.refunded","subscription.created","subscription.cancelled","subscription.renewed","cart.abandoned","review.created","inventory.low"]}},"retryStrategy":{"type":"string","enum":["exponential","linear","none"]},"maxAttempts":{"type":"integer","minimum":1,"maximum":10},"baseDelayMs":{"type":"integer","minimum":100},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","tenantId","url","eventTypes","retryStrategy","maxAttempts","baseDelayMs","isActive","createdAt","updatedAt"]}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Webhooks V2"],"summary":"Create webhook v2 subscription","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"eventTypes":{"type":"array","items":{"type":"string","enum":["order.created","order.updated","order.cancelled","order.fulfilled","order.refunded","product.created","product.updated","product.deleted","customer.created","customer.updated","payment.succeeded","payment.failed","payment.refunded","subscription.created","subscription.cancelled","subscription.renewed","cart.abandoned","review.created","inventory.low"]},"minItems":1},"retryStrategy":{"type":"string","enum":["exponential","linear","none"],"default":"exponential"},"maxAttempts":{"type":"integer","minimum":1,"maximum":10,"default":5},"baseDelayMs":{"type":"integer","minimum":100,"default":1000}},"required":["url","eventTypes"]}}}},"responses":{"201":{"description":"Subscription created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"url":{"type":"string","format":"uri"},"eventTypes":{"type":"array","items":{"type":"string","enum":["order.created","order.updated","order.cancelled","order.fulfilled","order.refunded","product.created","product.updated","product.deleted","customer.created","customer.updated","payment.succeeded","payment.failed","payment.refunded","subscription.created","subscription.cancelled","subscription.renewed","cart.abandoned","review.created","inventory.low"]}},"retryStrategy":{"type":"string","enum":["exponential","linear","none"]},"maxAttempts":{"type":"integer","minimum":1,"maximum":10},"baseDelayMs":{"type":"integer","minimum":100},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","tenantId","url","eventTypes","retryStrategy","maxAttempts","baseDelayMs","isActive","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/webhooks-v2/{id}":{"patch":{"tags":["Webhooks V2"],"summary":"Update webhook v2 subscription","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"eventTypes":{"type":"array","items":{"type":"string","enum":["order.created","order.updated","order.cancelled","order.fulfilled","order.refunded","product.created","product.updated","product.deleted","customer.created","customer.updated","payment.succeeded","payment.failed","payment.refunded","subscription.created","subscription.cancelled","subscription.renewed","cart.abandoned","review.created","inventory.low"]},"minItems":1},"retryStrategy":{"type":"string","enum":["exponential","linear","none"]},"maxAttempts":{"type":"integer","minimum":1,"maximum":10},"baseDelayMs":{"type":"integer","minimum":100},"isActive":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Subscription updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"url":{"type":"string","format":"uri"},"eventTypes":{"type":"array","items":{"type":"string","enum":["order.created","order.updated","order.cancelled","order.fulfilled","order.refunded","product.created","product.updated","product.deleted","customer.created","customer.updated","payment.succeeded","payment.failed","payment.refunded","subscription.created","subscription.cancelled","subscription.renewed","cart.abandoned","review.created","inventory.low"]}},"retryStrategy":{"type":"string","enum":["exponential","linear","none"]},"maxAttempts":{"type":"integer","minimum":1,"maximum":10},"baseDelayMs":{"type":"integer","minimum":100},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","tenantId","url","eventTypes","retryStrategy","maxAttempts","baseDelayMs","isActive","createdAt","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Webhooks V2"],"summary":"Delete webhook v2 subscription","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/webhooks-v2/{id}/test":{"post":{"tags":["Webhooks V2"],"summary":"Send a test event to a subscription","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"eventType":{"type":"string"},"payload":{"type":"object","additionalProperties":{"nullable":true}}},"required":["eventType"]}}}},"responses":{"202":{"description":"Test event enqueued","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/webhooks-v2/{id}/deliveries":{"get":{"tags":["Webhooks V2"],"summary":"List deliveries for a subscription","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"List of deliveries","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"subscriptionId":{"type":"string"},"eventType":{"type":"string"},"payload":{"type":"string"},"idempotencyKey":{"type":"string","nullable":true},"traceparent":{"type":"string","nullable":true},"attemptNumber":{"type":"integer"},"responseStatus":{"type":"integer","nullable":true},"responseBody":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","in_flight","delivered","failed","exhausted"]},"deliveredAt":{"type":"string","nullable":true,"format":"date-time"},"nextRetryAt":{"type":"string","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","subscriptionId","eventType","payload","idempotencyKey","traceparent","attemptNumber","responseStatus","responseBody","status","deliveredAt","nextRetryAt","createdAt"]}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/webhooks-v2/{id}/deliveries/{deliveryId}/replay":{"post":{"tags":["Webhooks V2"],"summary":"Replay a delivery","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"deliveryId","in":"path"}],"responses":{"202":{"description":"Replay enqueued","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/api-keys":{"get":{"tags":["API Keys"],"summary":"List API keys for tenant","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of API keys","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"name":{"type":"string"},"keyPrefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["products:read","products:write","orders:read","orders:write","customers:read","customers:write","catalog:read","webhooks:read","webhooks:write","analytics:read","settings:read","settings:write","invoices:read","invoices:write"]}},"rateLimitPerMinute":{"type":"integer"},"expiresAt":{"type":"string","nullable":true,"format":"date-time"},"lastUsedAt":{"type":"string","nullable":true,"format":"date-time"},"revokedAt":{"type":"string","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"createdByUserId":{"type":"string"}},"required":["id","tenantId","name","keyPrefix","scopes","rateLimitPerMinute","expiresAt","lastUsedAt","revokedAt","createdAt","createdByUserId"]}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["API Keys"],"summary":"Create an API key (fullKey returned once)","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"description":{"type":"string","maxLength":255},"scopes":{"type":"array","items":{"type":"string","enum":["products:read","products:write","orders:read","orders:write","customers:read","customers:write","catalog:read","webhooks:read","webhooks:write","analytics:read","settings:read","settings:write","invoices:read","invoices:write"]},"minItems":1},"rateLimitPerMinute":{"type":"integer","minimum":1,"maximum":1000,"default":60},"expiresAt":{"type":"string","format":"date-time"},"expiresInDays":{"type":"integer","minimum":1,"maximum":3650}},"required":["name","scopes"]}}}},"responses":{"201":{"description":"API key created — fullKey shown only once","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"name":{"type":"string"},"keyPrefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["products:read","products:write","orders:read","orders:write","customers:read","customers:write","catalog:read","webhooks:read","webhooks:write","analytics:read","settings:read","settings:write","invoices:read","invoices:write"]}},"rateLimitPerMinute":{"type":"integer"},"expiresAt":{"type":"string","nullable":true,"format":"date-time"},"lastUsedAt":{"type":"string","nullable":true,"format":"date-time"},"revokedAt":{"type":"string","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"createdByUserId":{"type":"string"},"fullKey":{"type":"string"}},"required":["id","tenantId","name","keyPrefix","scopes","rateLimitPerMinute","expiresAt","lastUsedAt","revokedAt","createdAt","createdByUserId","fullKey"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/api-keys/{id}":{"get":{"tags":["API Keys"],"summary":"Get an API key","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"API key details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"name":{"type":"string"},"keyPrefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["products:read","products:write","orders:read","orders:write","customers:read","customers:write","catalog:read","webhooks:read","webhooks:write","analytics:read","settings:read","settings:write","invoices:read","invoices:write"]}},"rateLimitPerMinute":{"type":"integer"},"expiresAt":{"type":"string","nullable":true,"format":"date-time"},"lastUsedAt":{"type":"string","nullable":true,"format":"date-time"},"revokedAt":{"type":"string","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"createdByUserId":{"type":"string"}},"required":["id","tenantId","name","keyPrefix","scopes","rateLimitPerMinute","expiresAt","lastUsedAt","revokedAt","createdAt","createdByUserId"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["API Keys"],"summary":"Update an API key","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"scopes":{"type":"array","items":{"type":"string"}},"rateLimitPerMinute":{"type":"integer","minimum":1,"maximum":10000},"expiresAt":{"type":"string","nullable":true,"format":"date-time"}}}}}},"responses":{"200":{"description":"Updated API key","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"name":{"type":"string"},"keyPrefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["products:read","products:write","orders:read","orders:write","customers:read","customers:write","catalog:read","webhooks:read","webhooks:write","analytics:read","settings:read","settings:write","invoices:read","invoices:write"]}},"rateLimitPerMinute":{"type":"integer"},"expiresAt":{"type":"string","nullable":true,"format":"date-time"},"lastUsedAt":{"type":"string","nullable":true,"format":"date-time"},"revokedAt":{"type":"string","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"createdByUserId":{"type":"string"}},"required":["id","tenantId","name","keyPrefix","scopes","rateLimitPerMinute","expiresAt","lastUsedAt","revokedAt","createdAt","createdByUserId"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"410":{"description":"Key has been revoked","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/api-keys/{id}/rotate":{"post":{"tags":["API Keys"],"summary":"Rotate an API key","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"New key — fullKey shown only once","content":{"application/json":{"schema":{"type":"object","properties":{"fullKey":{"type":"string"},"keyPrefix":{"type":"string"}},"required":["fullKey","keyPrefix"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/api-keys/{id}/revoke":{"post":{"tags":["API Keys"],"summary":"Revoke an API key","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/api-keys/{id}/audit":{"get":{"tags":["API Keys"],"summary":"Get audit log for a specific API key","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["created","used","rotated","revoked","rate_limited"]},"required":false,"name":"action","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"name":"date_from","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"name":"date_to","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Paginated audit log entries","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"apiKeyId":{"type":"string"},"tenantId":{"type":"string"},"action":{"type":"string","enum":["created","used","rotated","revoked","rate_limited"]},"actorUserId":{"type":"string","nullable":true},"ip":{"type":"string","nullable":true},"userAgent":{"type":"string","nullable":true},"ts":{"type":"integer"}},"required":["id","apiKeyId","tenantId","action","actorUserId","ip","userAgent","ts"]}},"total":{"type":"integer"},"page":{"type":"integer"},"per_page":{"type":"integer"}},"required":["items","total","page","per_page"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/payments/intent":{"post":{"tags":["Payments"],"summary":"Create a payment intent","description":"Creates a Stripe PaymentIntent for an order. Returns the client_secret for frontend payment confirmation.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"orderId":{"type":"string","minLength":1,"example":"ord_01"},"automatic_payment_methods":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"],"description":"Enable automatic payment method selection (Stripe)"},"payment_method_types":{"type":"array","items":{"type":"string"},"description":"Explicit list of payment method types (e.g. [\"card\", \"klarna\"])"}},"required":["orderId"]}}}},"responses":{"200":{"description":"Payment intent created","content":{"application/json":{"schema":{"type":"object","properties":{"clientSecret":{"type":"string","example":"pi_3MtwBwLkdIwHu7ix_secret_abc123"},"paymentIntentId":{"type":"string","example":"pi_3MtwBwLkdIwHu7ix28a3tqPa"}},"required":["clientSecret","paymentIntentId"]}}}},"400":{"description":"Bad request — order not in payable state","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Stripe credentials not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/payments/refund":{"post":{"tags":["Payments"],"summary":"Process a refund","description":"Creates a Stripe refund for a payment intent. Supports full and partial refunds.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"paymentIntentId":{"type":"string","minLength":1,"example":"pi_3MtwBwLkdIwHu7ix28a3tqPa"},"amount":{"type":"integer","minimum":1,"example":2500,"description":"Refund amount in cents. Omit for full refund."}},"required":["paymentIntentId"]}}}},"responses":{"200":{"description":"Refund processed","content":{"application/json":{"schema":{"type":"object","properties":{"refundId":{"type":"string","example":"re_3MtwBwLkdIwHu7ix28a3tqPa"},"paymentIntentId":{"type":"string","example":"pi_3MtwBwLkdIwHu7ix28a3tqPa"},"amount":{"type":"integer","example":2500,"description":"Refunded amount in cents"},"status":{"type":"string","example":"succeeded"},"orderId":{"type":"string","example":"ord_01"}},"required":["refundId","paymentIntentId","amount","status","orderId"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Order not found for payment intent","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Stripe credentials not configured","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/orders/{id}/mark-paid":{"post":{"tags":["Orders","Payments"],"summary":"Mark an offline-payment order as paid (manual reconciliation)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkOrderPaidInput"}}}},"responses":{"200":{"description":"Order reconciled (or already paid)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkOrderPaidResponse"}}}},"400":{"description":"Order not awaiting payment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsProblem"}}}}}}},"/v1/b2b/customer-groups":{"get":{"tags":["B2B","CustomerGroups"],"summary":"List customer groups","parameters":[{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"isActive","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerGroupList"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"post":{"tags":["B2B","CustomerGroups"],"summary":"Create a customer group","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomerGroup"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerGroup"}}}},"409":{"description":"Slug already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/customer-groups/{id}":{"get":{"tags":["B2B","CustomerGroups"],"summary":"Get a customer group by id","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerGroup"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"patch":{"tags":["B2B","CustomerGroups"],"summary":"Update a customer group","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomerGroup"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerGroup"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"409":{"description":"Slug conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"delete":{"tags":["B2B","CustomerGroups"],"summary":"Delete a customer group","description":"Refuses deletion if any customers are still assigned to the group. Reassign customers first.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"409":{"description":"Group still has customers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/tier-prices":{"get":{"tags":["B2B","TierPrices"],"summary":"List tier prices","parameters":[{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"productId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"variantId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"customerGroupId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TierPriceList"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"post":{"tags":["B2B","TierPrices"],"summary":"Create a tier price","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTierPrice"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TierPrice"}}}},"400":{"description":"Bad request — FK missing or date range invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"409":{"description":"Duplicate (product+variant+group+minQty)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/tier-prices/bulk":{"post":{"tags":["B2B","TierPrices"],"summary":"Bulk import tier prices","description":"Inserts up to 500 tier prices in one call. Skips rows that violate UNIQUE or FK and reports them in `errors`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTierPrices"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTierPriceResult"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/tier-prices/{id}":{"patch":{"tags":["B2B","TierPrices"],"summary":"Update a tier price","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTierPrice"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TierPrice"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"409":{"description":"Conflict — minQty change collides with another tier","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"delete":{"tags":["B2B","TierPrices"],"summary":"Delete a tier price","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/price-lists":{"get":{"tags":["B2B","PriceLists"],"summary":"List price lists","parameters":[{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"customerGroupId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"accountId","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"active","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceListList"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"post":{"tags":["B2B","PriceLists"],"summary":"Create a price list (optionally with items)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePriceList"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceListWithItems"}}}},"400":{"description":"Bad request — invalid scope or item FK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/price-lists/{id}/items":{"put":{"tags":["B2B","PriceLists"],"summary":"Replace the items of a price list","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPriceListItems"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceListWithItems"}}}},"400":{"description":"Bad request — invalid item FK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/price-lists/{id}":{"get":{"tags":["B2B","PriceLists"],"summary":"Get a price list with its items","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceListWithItems"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"patch":{"tags":["B2B","PriceLists"],"summary":"Update a price list","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePriceList"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceList"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"delete":{"tags":["B2B","PriceLists"],"summary":"Delete a price list (cascades its items)","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/accounts":{"get":{"tags":["B2B","Accounts"],"summary":"List B2B accounts","parameters":[{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"$ref":"#/components/schemas/B2bAccountStatus"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"customerId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bAccountList"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"post":{"tags":["B2B","Accounts"],"summary":"Create a B2B account for an existing customer","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateB2bAccount"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bAccount"}}}},"400":{"description":"Bad request — customer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"409":{"description":"Account already exists for this customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/accounts/{id}":{"get":{"tags":["B2B","Accounts"],"summary":"Get a B2B account by id","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bAccount"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"patch":{"tags":["B2B","Accounts"],"summary":"Update a B2B account","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateB2bAccount"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bAccount"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/accounts/{id}/approve":{"post":{"tags":["B2B","Accounts"],"summary":"Approve a pending B2B account","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bAccount"}}}},"400":{"description":"Account not in pending_approval","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/accounts/{id}/suspend":{"post":{"tags":["B2B","Accounts"],"summary":"Suspend an active B2B account","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bAccount"}}}},"400":{"description":"Account cannot be suspended from current status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/quotes":{"get":{"tags":["B2B","Quotes"],"summary":"List quotes (admin)","parameters":[{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"$ref":"#/components/schemas/QuoteStatus"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"accountId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteList"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/quotes/{id}/revisions":{"get":{"tags":["B2B","Quotes"],"summary":"Quote negotiation history (admin)","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRevisionList"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/quotes/{id}":{"get":{"tags":["B2B","Quotes"],"summary":"Get a quote by id","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden — not the requester or approver","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"patch":{"tags":["B2B","Quotes"],"summary":"Admin update a quote","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateQuote"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Quote is terminal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/quotes/{id}/approve":{"post":{"tags":["B2B","Quotes"],"summary":"Approve a quote","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"Illegal transition","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/quotes/{id}/reject":{"post":{"tags":["B2B","Quotes"],"summary":"Reject a quote","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RejectQuote"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"Illegal transition","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/purchase-orders":{"get":{"tags":["B2B","PurchaseOrders"],"summary":"List purchase orders (admin)","parameters":[{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"$ref":"#/components/schemas/PurchaseOrderStatus"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"accountId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderList"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/purchase-orders/{id}":{"patch":{"tags":["B2B","PurchaseOrders"],"summary":"Update a purchase order (admin — typically mark paid)","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePurchaseOrder"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrder"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/approval-requests":{"get":{"tags":["B2B","ApprovalRequests"],"summary":"List approval requests (admin queue)","parameters":[{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"$ref":"#/components/schemas/ApprovalRequestStatus"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"accountId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"approverId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalRequestAdminList"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/accounts/{id}/credit-memos":{"get":{"tags":["B2B","CreditMemos"],"summary":"List credit memos for a B2B account","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditMemoList"}}}}}},"post":{"tags":["B2B","CreditMemos"],"summary":"Issue a credit memo for a B2B account","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCreditMemo"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditMemo"}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/accounts/{id}/statement":{"get":{"tags":["B2B","CreditMemos"],"summary":"Account statement with aging buckets","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountStatement"}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/b2b/credit-memos/{id}/apply":{"post":{"tags":["B2B","CreditMemos"],"summary":"Apply a credit memo to an invoice (order)","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyCreditMemo"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditMemo"}}}},"400":{"description":"Amount exceeds memo balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Memo not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"409":{"description":"Memo not applicable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/returns/reasons":{"get":{"tags":["Returns"],"summary":"List return reasons (staff)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Reason catalog","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ReturnReason"}}},"required":["data"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}}}},"post":{"tags":["Returns"],"summary":"Create a return reason","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReturnReason"}}}},"responses":{"201":{"description":"Reason created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnReason"}}}},"409":{"description":"Reason code already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}}}}},"/v1/settings/returns/reasons/{id}":{"patch":{"tags":["Returns"],"summary":"Update a return reason","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateReturnReason"}}}},"responses":{"200":{"description":"Reason updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ReturnReason"}},"required":["data"]}}}},"404":{"description":"Reason not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}}}},"delete":{"tags":["Returns"],"summary":"Soft-delete a return reason (sets isActive=false)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Reason deactivated","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"id":{"type":"string"},"isActive":{"type":"boolean"},"updatedAt":{"type":"string"}},"required":["message","id","isActive","updatedAt"]}}}},"404":{"description":"Reason not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}}}}},"/v1/storefront/returns/reasons":{"get":{"tags":["Returns"],"summary":"List return reasons (storefront)","responses":{"200":{"description":"Customer-visible reasons","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ReturnReason"}}},"required":["data"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}}}}},"/v1/orders/{orderId}/returns":{"post":{"tags":["Returns"],"summary":"Create a return (RMA) for an order","description":"Opens a return request for one or more items of a delivered/shipped order. Auto-approves when the matched reason has autoApprove=true.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"orderId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReturn"}}}},"responses":{"201":{"description":"Return created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnDetail"}}}},"400":{"description":"Order not eligible for return","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"404":{"description":"Order or item not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"409":{"description":"Item already in an active return","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}}}},"get":{"tags":["Returns"],"summary":"List returns for a specific order","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"orderId","in":"path"}],"responses":{"200":{"description":"Returns for this order","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ReturnDetail"}}},"required":["data"]}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}}}}},"/v1/returns":{"get":{"tags":["Returns"],"summary":"List returns (staff)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"customerId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"orderId","in":"query"},{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Paged returns","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PagedReturns"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}}}}},"/v1/returns/{id}":{"get":{"tags":["Returns"],"summary":"Get a return by ID","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Return detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnDetail"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"404":{"description":"Return not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}}}},"delete":{"tags":["Returns"],"summary":"Delete a return","description":"Deletes a return. Only allowed for non-terminal returns (terminal returns are kept for audit).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Return deleted"},"404":{"description":"Return not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"409":{"description":"Return is in a terminal state and cannot be deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}}}}},"/v1/returns/{id}/status":{"patch":{"tags":["Returns"],"summary":"Transition a return to a new status","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateReturnStatus"}}}},"responses":{"200":{"description":"Return updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnDetail"}}}},"400":{"description":"Illegal status transition","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"404":{"description":"Return not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}}}}},"/v1/returns/{id}/history":{"get":{"tags":["Returns"],"summary":"Get status history timeline for a return","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Status history timeline","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ReturnStatusHistoryEntry"}}},"required":["data"]}}}},"404":{"description":"Return not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReturnProblem"}}}}}}},"/v1/reviews":{"get":{"tags":["Reviews"],"summary":"List reviews (admin — all statuses)","description":"Staff-only. Lists reviews across all moderation statuses, with optional product/status filters for the moderation queue.","parameters":[{"schema":{"type":"string"},"required":false,"name":"product_id","in":"query"},{"schema":{"$ref":"#/components/schemas/ReviewStatus"},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Reviews","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListReviewsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}}}}},"/v1/reviews/{id}":{"patch":{"tags":["Reviews"],"summary":"Moderate a review (admin — approve/reject)","description":"Staff-only. Transitions a review to approved / rejected / pending. Approving a review makes it publicly visible and counts toward the aggregate rating.","parameters":[{"schema":{"type":"string","minLength":1,"example":"rev_01"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModerateReview"}}}},"responses":{"200":{"description":"Review moderated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Review"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}},"404":{"description":"Review not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewProblem"}}}}}}},"/v1/storefront/downloads/{token}":{"get":{"tags":["Downloads","Storefront"],"summary":"Consume a download token and stream the file","description":"Validates a single-use-budget download token, decrements its remaining count, and streams the file from R2.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"File stream"},"403":{"description":"Download limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadProblem"}}}},"404":{"description":"Token or file not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadProblem"}}}},"410":{"description":"Token expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadProblem"}}}}}}},"/v1/storefront/customer/downloads":{"get":{"tags":["Downloads","Storefront"],"summary":"List the authenticated customer's downloadable items","responses":{"200":{"description":"Customer download tokens","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"tokenId":{"type":"string"},"downloadId":{"type":"string"},"fileName":{"type":"string"},"downloadsRemaining":{"type":"integer"},"expiresAt":{"type":"string"}},"required":["tokenId","downloadId","fileName","downloadsRemaining","expiresAt"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadProblem"}}}}}}},"/v1/products/{id}/downloads":{"post":{"tags":["Downloads"],"summary":"Register a downloadable file for a product","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDownload"}}}},"responses":{"201":{"description":"Download registered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Download"}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadProblem"}}}}}},"get":{"tags":["Downloads"],"summary":"List downloadable files for a product","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Downloads","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Download"}}},"required":["data"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadProblem"}}}}}}},"/v1/products/{id}/downloads/{dlId}":{"delete":{"tags":["Downloads"],"summary":"Delete a downloadable file","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"dlId","in":"path"}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Download not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadProblem"}}}}}}},"/v1/storefront/gift-cards/balance":{"post":{"tags":["GiftCards","Storefront"],"summary":"Check a gift card balance","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckGiftCardBalance"}}}},"responses":{"200":{"description":"Balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardBalance"}}}},"404":{"description":"Gift card not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}}}}},"/v1/storefront/gift-cards/redeem":{"post":{"tags":["GiftCards","Storefront"],"summary":"Redeem balance from a gift card","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedeemGiftCard"}}}},"responses":{"200":{"description":"Redeemed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardRedeemResult"}}}},"400":{"description":"Gift card not redeemable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}},"404":{"description":"Gift card not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}},"409":{"description":"Idempotency conflict — already redeemed for this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}}}}},"/v1/gift-cards/stats":{"get":{"tags":["GiftCards"],"summary":"Gift card program statistics","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Stats","content":{"application/json":{"schema":{"type":"object","properties":{"totalIssued":{"type":"integer"},"activeCards":{"type":"integer"},"outstandingBalance":{"type":"integer"},"totalRedeemedAmount":{"type":"integer"},"redemptionRate":{"type":"number"},"expiringSoon":{"type":"integer"}},"required":["totalIssued","activeCards","outstandingBalance","totalRedeemedAmount","redemptionRate","expiringSoon"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}}}}},"/v1/gift-cards/{id}":{"get":{"tags":["GiftCards"],"summary":"Get gift card detail with redemption history","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Gift card detail","content":{"application/json":{"schema":{"type":"object","properties":{"giftCard":{"$ref":"#/components/schemas/GiftCard"},"redemptions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"giftCardId":{"type":"string"},"orderId":{"type":"string","nullable":true},"amount":{"type":"integer"},"balanceAfter":{"type":"integer"},"createdAt":{"type":"string"}},"required":["id","giftCardId","orderId","amount","balanceAfter","createdAt"]}},"totalRedeemed":{"type":"integer"},"redemptionCount":{"type":"integer"}},"required":["giftCard","redemptions","totalRedeemed","redemptionCount"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}}}},"patch":{"tags":["GiftCards"],"summary":"Update gift card metadata (expiry, recipient email, message)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGiftCard"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCard"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}}}}},"/v1/gift-cards":{"get":{"tags":["GiftCards"],"summary":"List gift cards (admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Gift cards","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/GiftCard"}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}}}},"post":{"tags":["GiftCards"],"summary":"Manually issue a gift card (admin)","description":"Creates a gift card without a purchase. The raw code is returned ONCE in the response — it is never persisted.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGiftCard"}}}},"responses":{"201":{"description":"Gift card issued","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GiftCard"},{"type":"object","properties":{"code":{"type":"string","description":"Raw code — shown once."}},"required":["code"]}]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}}}}},"/v1/gift-cards/{id}/void":{"patch":{"tags":["GiftCards"],"summary":"Void a gift card (admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Voided","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCard"}}}},"404":{"description":"Gift card not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}},"409":{"description":"Gift card already in a terminal state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}}}}},"/v1/gift-cards/{id}/redemptions":{"get":{"tags":["GiftCards"],"summary":"List redemptions for a gift card (admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Redemptions","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"giftCardId":{"type":"string"},"orderId":{"type":"string","nullable":true},"amount":{"type":"integer"},"balanceAfter":{"type":"integer"},"createdAt":{"type":"string"}},"required":["id","giftCardId","orderId","amount","balanceAfter","createdAt"]}}},"required":["data"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCardProblem"}}}}}}},"/v1/storefront/subscriptions":{"get":{"tags":["Subscriptions","Storefront"],"summary":"List the authenticated customer's subscriptions","responses":{"200":{"description":"Subscriptions","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustomerSubscription"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}}}}},"/v1/storefront/subscriptions/{id}/pause":{"post":{"tags":["Subscriptions","Storefront"],"summary":"Pause a subscription","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Updated subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerSubscription"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"404":{"description":"Subscription not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"409":{"description":"Subscription not in a valid state for this action","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}}}}},"/v1/storefront/subscriptions/{id}/resume":{"post":{"tags":["Subscriptions","Storefront"],"summary":"Resume a subscription","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Updated subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerSubscription"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"404":{"description":"Subscription not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"409":{"description":"Subscription not in a valid state for this action","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}}}}},"/v1/storefront/subscriptions/{id}/cancel":{"post":{"tags":["Subscriptions","Storefront"],"summary":"Cancel a subscription","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Updated subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerSubscription"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"404":{"description":"Subscription not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"409":{"description":"Subscription not in a valid state for this action","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}}}}},"/v1/products/{id}/subscription-plan":{"post":{"tags":["Subscriptions"],"summary":"Create the subscription plan for a product","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSubscriptionPlan"}}}},"responses":{"201":{"description":"Plan created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionPlan"}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"409":{"description":"Product already has a subscription plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}}}},"get":{"tags":["Subscriptions"],"summary":"Get the subscription plan for a product","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionPlan"}}}},"404":{"description":"No plan for this product","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}}}},"patch":{"tags":["Subscriptions"],"summary":"Update the subscription plan for a product","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSubscriptionPlan"}}}},"responses":{"200":{"description":"Plan updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionPlan"}}}},"404":{"description":"No plan for this product","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}}}}},"/v1/subscriptions":{"get":{"tags":["Subscriptions"],"summary":"List all customer subscriptions (admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Subscriptions","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustomerSubscription"}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionProblem"}}}}}}},"/v1/subscriptions/:id/invoices":{"get":{"tags":["Subscriptions"],"summary":"List invoices for a subscription","description":"Returns paginated subscription_invoices for a given subscription. RBAC: customer (own subscription) or admin.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"sub_abc123"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["draft","open","paid","uncollectible","void","failed"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","description":"Unix timestamp (seconds) — filter invoices paid_at >= from"},"required":false,"description":"Unix timestamp (seconds) — filter invoices paid_at >= from","name":"from","in":"query"},{"schema":{"type":"string","description":"Unix timestamp (seconds) — filter invoices paid_at <= to"},"required":false,"description":"Unix timestamp (seconds) — filter invoices paid_at <= to","name":"to","in":"query"},{"schema":{"type":"string","default":"1"},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","default":"20"},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Invoices list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"subscriptionId":{"type":"string"},"stripeInvoiceId":{"type":"string","nullable":true},"paypalPaymentId":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","open","paid","uncollectible","void","failed"]},"amountCents":{"type":"number"},"currency":{"type":"string"},"invoiceNumber":{"type":"string","nullable":true},"invoicePdfUrl":{"type":"string","nullable":true},"periodStart":{"type":"number","nullable":true},"periodEnd":{"type":"number","nullable":true},"paidAt":{"type":"number","nullable":true},"attemptCount":{"type":"number","nullable":true},"nextPaymentAttempt":{"type":"number","nullable":true},"failureReason":{"type":"string","nullable":true},"createdAt":{"type":"number"}},"required":["id","subscriptionId","stripeInvoiceId","paypalPaymentId","status","amountCents","currency","invoiceNumber","invoicePdfUrl","periodStart","periodEnd","paidAt","attemptCount","nextPaymentAttempt","failureReason","createdAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"perPage":{"type":"number"},"total":{"type":"number"}},"required":["page","perPage","total"]}},"required":["data","pagination"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Subscription not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/subscriptions/metrics":{"get":{"tags":["Subscriptions"],"summary":"Subscription metrics (MRR/ARR/churn)","description":"Admin-only endpoint returning MRR, ARR, churn rate, LTV, and per-plan breakdowns.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["month","year"],"default":"month"},"required":false,"name":"period","in":"query"}],"responses":{"200":{"description":"Subscription metrics","content":{"application/json":{"schema":{"type":"object","properties":{"mrr":{"type":"number","description":"Monthly Recurring Revenue in cents"},"arr":{"type":"number","description":"Annual Recurring Revenue in cents (mrr * 12)"},"active_subscriptions":{"type":"number"},"trialing":{"type":"number"},"past_due":{"type":"number"},"cancelled_this_period":{"type":"number"},"churn_rate_pct":{"type":"number","description":"Churn rate percentage for the period"},"ltv_avg_cents":{"type":"number","description":"Average LTV per customer in cents"},"new_this_period":{"type":"number"},"upgraded_this_period":{"type":"number","description":"Placeholder — requires plan_change_history table"},"downgraded_this_period":{"type":"number","description":"Placeholder — requires plan_change_history table"},"by_plan":{"type":"array","items":{"type":"object","properties":{"planId":{"type":"string"},"name":{"type":"string","nullable":true},"subscribers":{"type":"number"},"mrr":{"type":"number"}},"required":["planId","name","subscribers","mrr"]}}},"required":["mrr","arr","active_subscriptions","trialing","past_due","cancelled_this_period","churn_rate_pct","ltv_avg_cents","new_this_period","upgraded_this_period","downgraded_this_period","by_plan"]}}}},"403":{"description":"Forbidden — admin only","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/reports/order-stats-daily":{"get":{"tags":["Reports"],"summary":"Order stats by day (CQRS read model)","description":"Returns daily order aggregates from the projection read model. Lag tolerance: 5 min.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","nullable":true,"description":"Epoch seconds start (inclusive)"},"required":false,"description":"Epoch seconds start (inclusive)","name":"from","in":"query"},{"schema":{"type":"integer","nullable":true,"description":"Epoch seconds end (exclusive)"},"required":false,"description":"Epoch seconds end (exclusive)","name":"to","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"Max rows returned"},"required":false,"description":"Max rows returned","name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque pagination cursor (date/id string)"},"required":false,"description":"Opaque pagination cursor (date/id string)","name":"cursor","in":"query"}],"responses":{"200":{"description":"Daily order stats","headers":{"Cache-Control":{"schema":{"type":"string"}},"X-Read-Model-Lag-Tolerance":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"date":{"type":"string"},"orders_count":{"type":"integer"},"revenue_cents":{"type":"integer"},"refunds_count":{"type":"integer"},"refunds_cents":{"type":"integer"},"avg_order_value_cents":{"type":"integer"}},"required":["id","date","orders_count","revenue_cents","refunds_count","refunds_cents","avg_order_value_cents"]}},"next_cursor":{"type":"string","nullable":true}},"required":["data","next_cursor"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/reports/product-stats-monthly":{"get":{"tags":["Reports"],"summary":"Product stats by month (CQRS read model)","description":"Returns monthly product aggregates from the projection read model. Lag tolerance: 5 min.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","nullable":true,"description":"Epoch seconds start (inclusive)"},"required":false,"description":"Epoch seconds start (inclusive)","name":"from","in":"query"},{"schema":{"type":"integer","nullable":true,"description":"Epoch seconds end (exclusive)"},"required":false,"description":"Epoch seconds end (exclusive)","name":"to","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"Max rows returned"},"required":false,"description":"Max rows returned","name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque pagination cursor (date/id string)"},"required":false,"description":"Opaque pagination cursor (date/id string)","name":"cursor","in":"query"}],"responses":{"200":{"description":"Monthly product stats","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"month":{"type":"string"},"product_id":{"type":"string"},"units_sold":{"type":"integer"},"revenue_cents":{"type":"integer"},"views":{"type":"integer"},"conversion_rate":{"type":"integer"}},"required":["id","month","product_id","units_sold","revenue_cents","views","conversion_rate"]}},"next_cursor":{"type":"string","nullable":true}},"required":["data","next_cursor"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/reports/customer-ltv":{"get":{"tags":["Reports"],"summary":"Customer lifetime value (CQRS read model)","description":"Returns customer LTV aggregates from the projection read model. Lag tolerance: 5 min.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","nullable":true,"description":"Epoch seconds start (inclusive)"},"required":false,"description":"Epoch seconds start (inclusive)","name":"from","in":"query"},{"schema":{"type":"integer","nullable":true,"description":"Epoch seconds end (exclusive)"},"required":false,"description":"Epoch seconds end (exclusive)","name":"to","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"Max rows returned"},"required":false,"description":"Max rows returned","name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque pagination cursor (date/id string)"},"required":false,"description":"Opaque pagination cursor (date/id string)","name":"cursor","in":"query"}],"responses":{"200":{"description":"Customer LTV data","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"customer_id":{"type":"string"},"total_orders":{"type":"integer"},"total_spent_cents":{"type":"integer"},"avg_order_value_cents":{"type":"integer"},"first_order_at":{"type":"integer","nullable":true},"last_order_at":{"type":"integer","nullable":true},"predicted_ltv_cents":{"type":"integer","nullable":true},"updated_at":{"type":"integer"}},"required":["customer_id","total_orders","total_spent_cents","avg_order_value_cents","first_order_at","last_order_at","predicted_ltv_cents","updated_at"]}},"next_cursor":{"type":"string","nullable":true}},"required":["data","next_cursor"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/reports/inventory-status":{"get":{"tags":["Reports"],"summary":"Inventory status snapshot (CQRS read model)","description":"Returns inventory available/reserved quantities from the projection read model. Lag tolerance: 5 min.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","nullable":true,"description":"Epoch seconds start (inclusive)"},"required":false,"description":"Epoch seconds start (inclusive)","name":"from","in":"query"},{"schema":{"type":"integer","nullable":true,"description":"Epoch seconds end (exclusive)"},"required":false,"description":"Epoch seconds end (exclusive)","name":"to","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"Max rows returned"},"required":false,"description":"Max rows returned","name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque pagination cursor (date/id string)"},"required":false,"description":"Opaque pagination cursor (date/id string)","name":"cursor","in":"query"}],"responses":{"200":{"description":"Inventory status data","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"product_variant_id":{"type":"string"},"available_qty":{"type":"integer"},"reserved_qty":{"type":"integer"},"reorder_point":{"type":"integer"},"last_sync_at":{"type":"integer"}},"required":["product_variant_id","available_qty","reserved_qty","reorder_point","last_sync_at"]}},"next_cursor":{"type":"string","nullable":true}},"required":["data","next_cursor"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/reports/tax/widget":{"get":{"tags":["Reports"],"summary":"Tax collected summary widget","description":"Compact tax-collected summary for the dashboard widget: totals by currency plus the top countries by tax collected over a rolling period. Excludes cancelled / failed orders. RBAC: admin + owner (+ superadmin).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["today","7d","30d","month"],"default":"30d","description":"Rolling window for tax collected. `month` = calendar month-to-date.","example":"30d"},"required":false,"description":"Rolling window for tax collected. `month` = calendar month-to-date.","name":"period","in":"query"}],"responses":{"200":{"description":"Tax widget summary","content":{"application/json":{"schema":{"type":"object","properties":{"period":{"type":"string","enum":["today","7d","30d","month"]},"totalByCurrency":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string"},"amount":{"type":"number"}},"required":["currency","amount"]}},"topCountries":{"type":"array","items":{"type":"object","properties":{"country":{"type":"string"},"amount":{"type":"number"},"currency":{"type":"string"}},"required":["country","amount","currency"]}}},"required":["period","totalByCurrency","topCountries"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/reports/tax":{"get":{"tags":["Reports"],"summary":"Tax report by country/state","description":"Aggregates tax collected by country and state for the given period. Use format=csv for a streamable export. RBAC: tax.reports.read (admin + owner).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Start of period (ISO 8601 date, inclusive)","example":"2026-01-01"},"required":true,"description":"Start of period (ISO 8601 date, inclusive)","name":"from","in":"query"},{"schema":{"type":"string","description":"End of period (ISO 8601 date, inclusive)","example":"2026-03-31"},"required":true,"description":"End of period (ISO 8601 date, inclusive)","name":"to","in":"query"},{"schema":{"type":"string","description":"Filter by shipping country (ISO 3166-1 alpha-2)","example":"ES"},"required":false,"description":"Filter by shipping country (ISO 3166-1 alpha-2)","name":"country","in":"query"},{"schema":{"type":"string","enum":["json","csv"],"default":"json","description":"Response format","example":"json"},"required":false,"description":"Response format","name":"format","in":"query"}],"responses":{"200":{"description":"Tax report (JSON or CSV)","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string"},"country":{"type":"string","nullable":true},"state":{"type":"string","nullable":true},"subtotal_total":{"type":"number"},"tax_total":{"type":"number"},"gross_total":{"type":"number"},"order_count":{"type":"number"}},"required":["currency","country","state","subtotal_total","tax_total","gross_total","order_count"]}},"totals":{"type":"object","properties":{"subtotal":{"type":"number"},"tax":{"type":"number"},"gross":{"type":"number"}},"required":["subtotal","tax","gross"]},"period":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"]}},"required":["items","totals","period"]}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/reports/sales":{"get":{"tags":["Reports"],"summary":"Sales report (CQRS read model)","description":"Aggregates the order_stats_daily projection over a date range, bucketed by day/week/month. net_revenue = revenue - refunds. RBAC: reports.manage (admin + owner).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Start of period (ISO 8601 date, inclusive). Defaults to 30 days ago.","example":"2026-01-01"},"required":false,"description":"Start of period (ISO 8601 date, inclusive). Defaults to 30 days ago.","name":"from","in":"query"},{"schema":{"type":"string","description":"End of period (ISO 8601 date, inclusive). Defaults to today.","example":"2026-03-31"},"required":false,"description":"End of period (ISO 8601 date, inclusive). Defaults to today.","name":"to","in":"query"},{"schema":{"type":"string","enum":["day","week","month"],"default":"day","description":"Time-bucket granularity for grouped rows","example":"day"},"required":false,"description":"Time-bucket granularity for grouped rows","name":"group_by","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"default":100,"description":"Maximum rows returned"},"required":false,"description":"Maximum rows returned","name":"limit","in":"query"}],"responses":{"200":{"description":"Sales report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesReport"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/reports/products":{"get":{"tags":["Reports"],"summary":"Product performance report (CQRS read model + raw)","description":"Top products by revenue/units over a month range from product_stats_monthly, joined to products for names and to order_items for distinct order counts. RBAC: reports.manage (admin + owner).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Start of period (ISO 8601 date, inclusive). Defaults to 30 days ago.","example":"2026-01-01"},"required":false,"description":"Start of period (ISO 8601 date, inclusive). Defaults to 30 days ago.","name":"from","in":"query"},{"schema":{"type":"string","description":"End of period (ISO 8601 date, inclusive). Defaults to today.","example":"2026-03-31"},"required":false,"description":"End of period (ISO 8601 date, inclusive). Defaults to today.","name":"to","in":"query"},{"schema":{"type":"string","enum":["day","week","month"],"default":"day","description":"Time-bucket granularity for grouped rows","example":"day"},"required":false,"description":"Time-bucket granularity for grouped rows","name":"group_by","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"default":100,"description":"Maximum rows returned"},"required":false,"description":"Maximum rows returned","name":"limit","in":"query"}],"responses":{"200":{"description":"Products report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductsReport"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/reports/inventory":{"get":{"tags":["Reports"],"summary":"Inventory health report (CQRS read model)","description":"Snapshot of the inventory_status projection with a below-reorder-point flag. RBAC: reports.manage (admin + owner).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Start of period (ISO 8601 date, inclusive). Defaults to 30 days ago.","example":"2026-01-01"},"required":false,"description":"Start of period (ISO 8601 date, inclusive). Defaults to 30 days ago.","name":"from","in":"query"},{"schema":{"type":"string","description":"End of period (ISO 8601 date, inclusive). Defaults to today.","example":"2026-03-31"},"required":false,"description":"End of period (ISO 8601 date, inclusive). Defaults to today.","name":"to","in":"query"},{"schema":{"type":"string","enum":["day","week","month"],"default":"day","description":"Time-bucket granularity for grouped rows","example":"day"},"required":false,"description":"Time-bucket granularity for grouped rows","name":"group_by","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"default":100,"description":"Maximum rows returned"},"required":false,"description":"Maximum rows returned","name":"limit","in":"query"}],"responses":{"200":{"description":"Inventory report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryReport"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/reports/customers":{"get":{"tags":["Reports"],"summary":"Customer value report (CQRS read model)","description":"Top customers by lifetime spend from the customer_ltv projection, optionally filtered to those whose last order falls inside the date range. RBAC: reports.manage (admin + owner).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Start of period (ISO 8601 date, inclusive). Defaults to 30 days ago.","example":"2026-01-01"},"required":false,"description":"Start of period (ISO 8601 date, inclusive). Defaults to 30 days ago.","name":"from","in":"query"},{"schema":{"type":"string","description":"End of period (ISO 8601 date, inclusive). Defaults to today.","example":"2026-03-31"},"required":false,"description":"End of period (ISO 8601 date, inclusive). Defaults to today.","name":"to","in":"query"},{"schema":{"type":"string","enum":["day","week","month"],"default":"day","description":"Time-bucket granularity for grouped rows","example":"day"},"required":false,"description":"Time-bucket granularity for grouped rows","name":"group_by","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"default":100,"description":"Maximum rows returned"},"required":false,"description":"Maximum rows returned","name":"limit","in":"query"}],"responses":{"200":{"description":"Customers report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomersReport"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/reports/finance":{"get":{"tags":["Reports"],"summary":"Finance summary report (raw orders)","description":"P&L-style summary over a date range: gross revenue, refunds, net revenue, tax, shipping and discounts, broken down by currency. Reads raw orders (tax/shipping/discount components are not carried by the daily read model). RBAC: reports.manage (admin + owner).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Start of period (ISO 8601 date, inclusive). Defaults to 30 days ago.","example":"2026-01-01"},"required":false,"description":"Start of period (ISO 8601 date, inclusive). Defaults to 30 days ago.","name":"from","in":"query"},{"schema":{"type":"string","description":"End of period (ISO 8601 date, inclusive). Defaults to today.","example":"2026-03-31"},"required":false,"description":"End of period (ISO 8601 date, inclusive). Defaults to today.","name":"to","in":"query"},{"schema":{"type":"string","enum":["day","week","month"],"default":"day","description":"Time-bucket granularity for grouped rows","example":"day"},"required":false,"description":"Time-bucket granularity for grouped rows","name":"group_by","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"default":100,"description":"Maximum rows returned"},"required":false,"description":"Maximum rows returned","name":"limit","in":"query"}],"responses":{"200":{"description":"Finance report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceReport"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/_internal/cqrs/health":{"get":{"tags":["Reports"],"summary":"CQRS read-model freshness health","description":"Returns measured projection lag per CQRS read model + SLA + status. Global status is degraded when any read model exceeds its SLA.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"CQRS health snapshot","headers":{"X-Read-Model-Lag":{"schema":{"type":"string"}},"X-CQRS-Status":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["fresh","degraded"],"example":"fresh"},"measuredAt":{"type":"integer","example":1717000000},"readModels":{"type":"array","items":{"type":"object","properties":{"readModel":{"type":"string","example":"order_stats_daily"},"lag":{"type":"integer","nullable":true,"example":12,"description":"now - MAX(projected_at) in seconds; null when never projected"},"sla":{"type":"integer","example":300},"status":{"type":"string","enum":["fresh","degraded","unknown"],"example":"fresh"}},"required":["readModel","lag","sla","status"]}}},"required":["status","measuredAt","readModels"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/invoices/generate":{"post":{"tags":["Invoicing"],"summary":"Generate electronic invoice for an order","description":"Builds, signs, and dispatches a country-specific electronic invoice (CFDI/SII/WSFEv1/UBL). Sandbox by default — production requires INVOICING_<COUNTRY>_PROD_ENABLED=true.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"orderId":{"type":"string","example":"ord_abc123"},"country":{"type":"string","enum":["MX","ES","AR","CO"]},"format":{"type":"string","enum":["CFDI_4.0","SII","WSFEv1","UBL_2.1"]}},"required":["orderId"]}}}},"responses":{"200":{"description":"Invoice issued or pending","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"orderId":{"type":"string"},"country":{"type":"string","enum":["MX","ES","AR","CO"]},"format":{"type":"string","enum":["CFDI_4.0","SII","WSFEv1","UBL_2.1"]},"status":{"type":"string","enum":["pending","signed","accepted","rejected","cancelled"]},"uuidAuthority":{"type":"string","nullable":true},"serialNumber":{"type":"string","nullable":true},"xmlR2Key":{"type":"string","nullable":true},"pdfR2Key":{"type":"string","nullable":true},"totalCents":{"type":"integer"},"currency":{"type":"string","minLength":3,"maxLength":3},"pacResponse":{"nullable":true},"sealedAt":{"type":"integer","nullable":true},"retainUntil":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","orderId","country","format","status","uuidAuthority","serialNumber","xmlR2Key","pdfR2Key","totalCents","currency","sealedAt","retainUntil","createdAt","updatedAt"]}}}},"404":{"description":"Order or config not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation / config error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"503":{"description":"PAC circuit open","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/invoices/{id}":{"get":{"tags":["Invoicing"],"summary":"Get invoice detail with signed download URLs","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Invoice detail","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"orderId":{"type":"string"},"country":{"type":"string","enum":["MX","ES","AR","CO"]},"format":{"type":"string","enum":["CFDI_4.0","SII","WSFEv1","UBL_2.1"]},"status":{"type":"string","enum":["pending","signed","accepted","rejected","cancelled"]},"uuidAuthority":{"type":"string","nullable":true},"serialNumber":{"type":"string","nullable":true},"xmlR2Key":{"type":"string","nullable":true},"pdfR2Key":{"type":"string","nullable":true},"totalCents":{"type":"integer"},"currency":{"type":"string","minLength":3,"maxLength":3},"pacResponse":{"nullable":true},"sealedAt":{"type":"integer","nullable":true},"retainUntil":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"pdfSignedUrl":{"type":"string","nullable":true,"format":"uri"},"xmlSignedUrl":{"type":"string","nullable":true,"format":"uri"}},"required":["id","orderId","country","format","status","uuidAuthority","serialNumber","xmlR2Key","pdfR2Key","totalCents","currency","sealedAt","retainUntil","createdAt","updatedAt","pdfSignedUrl","xmlSignedUrl"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/invoices":{"get":{"tags":["Invoicing"],"summary":"List electronic invoices","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","enum":["MX","ES","AR","CO"]},"required":false,"name":"country","in":"query"},{"schema":{"type":"string","enum":["pending","signed","accepted","rejected","cancelled"]},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"Paginated invoice list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"orderId":{"type":"string"},"country":{"type":"string","enum":["MX","ES","AR","CO"]},"format":{"type":"string","enum":["CFDI_4.0","SII","WSFEv1","UBL_2.1"]},"status":{"type":"string","enum":["pending","signed","accepted","rejected","cancelled"]},"uuidAuthority":{"type":"string","nullable":true},"serialNumber":{"type":"string","nullable":true},"xmlR2Key":{"type":"string","nullable":true},"pdfR2Key":{"type":"string","nullable":true},"totalCents":{"type":"integer"},"currency":{"type":"string","minLength":3,"maxLength":3},"pacResponse":{"nullable":true},"sealedAt":{"type":"integer","nullable":true},"retainUntil":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","orderId","country","format","status","uuidAuthority","serialNumber","xmlR2Key","pdfR2Key","totalCents","currency","sealedAt","retainUntil","createdAt","updatedAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/invoices/{id}/cancel":{"post":{"tags":["Invoicing"],"summary":"Cancel an electronic invoice","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1},"substituteInvoiceUuid":{"type":"string","nullable":true}},"required":["reason"]}}}},"responses":{"200":{"description":"Cancellation result","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"orderId":{"type":"string"},"country":{"type":"string","enum":["MX","ES","AR","CO"]},"format":{"type":"string","enum":["CFDI_4.0","SII","WSFEv1","UBL_2.1"]},"status":{"type":"string","enum":["pending","signed","accepted","rejected","cancelled"]},"uuidAuthority":{"type":"string","nullable":true},"serialNumber":{"type":"string","nullable":true},"xmlR2Key":{"type":"string","nullable":true},"pdfR2Key":{"type":"string","nullable":true},"totalCents":{"type":"integer"},"currency":{"type":"string","minLength":3,"maxLength":3},"pacResponse":{"nullable":true},"sealedAt":{"type":"integer","nullable":true},"retainUntil":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","orderId","country","format","status","uuidAuthority","serialNumber","xmlR2Key","pdfR2Key","totalCents","currency","sealedAt","retainUntil","createdAt","updatedAt"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Cannot cancel","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/invoicing/configs":{"get":{"tags":["Invoicing"],"summary":"List invoice fiscal configs (one per country)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of configs","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"country":{"type":"string","enum":["MX","ES","AR","CO"]},"format":{"type":"string","enum":["CFDI_4.0","SII","WSFEv1","UBL_2.1"]},"taxId":{"type":"string"},"businessName":{"type":"string"},"businessAddress":{"type":"string"},"pacProvider":{"type":"string","enum":["solfacil","edicom","manual"]},"certificateR2Key":{"type":"string","nullable":true},"certificateExpiresAt":{"type":"integer","nullable":true},"nextSequentialNumber":{"type":"integer"},"ivaRate":{"type":"integer"},"isActive":{"type":"boolean"},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","country","format","taxId","businessName","businessAddress","pacProvider","certificateR2Key","certificateExpiresAt","nextSequentialNumber","ivaRate","isActive","createdAt","updatedAt"]}}},"required":["data"]}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"put":{"tags":["Invoicing"],"summary":"Create or update an invoice fiscal config","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"country":{"type":"string","enum":["MX","ES","AR","CO"]},"format":{"type":"string","enum":["CFDI_4.0","SII","WSFEv1","UBL_2.1"]},"taxId":{"type":"string","minLength":1},"businessName":{"type":"string","minLength":1},"businessAddress":{"type":"string","minLength":1},"pacProvider":{"type":"string","enum":["solfacil","edicom","manual"]},"ivaRate":{"type":"integer","minimum":0},"isActive":{"type":"boolean","default":true}},"required":["country","format","taxId","businessName","businessAddress","pacProvider"]}}}},"responses":{"200":{"description":"Config saved","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"country":{"type":"string","enum":["MX","ES","AR","CO"]},"format":{"type":"string","enum":["CFDI_4.0","SII","WSFEv1","UBL_2.1"]},"taxId":{"type":"string"},"businessName":{"type":"string"},"businessAddress":{"type":"string"},"pacProvider":{"type":"string","enum":["solfacil","edicom","manual"]},"certificateR2Key":{"type":"string","nullable":true},"certificateExpiresAt":{"type":"integer","nullable":true},"nextSequentialNumber":{"type":"integer"},"ivaRate":{"type":"integer"},"isActive":{"type":"boolean"},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","country","format","taxId","businessName","businessAddress","pacProvider","certificateR2Key","certificateExpiresAt","nextSequentialNumber","ivaRate","isActive","createdAt","updatedAt"]}}}},"422":{"description":"Validation","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/invoicing/certificates":{"post":{"tags":["Invoicing"],"summary":"Upload CSD / digital certificate for a country","description":"Stores cert + private key (PKCS#8 base64) in R2 as a JSON bundle. PAC credentials are AES-GCM encrypted with ENCRYPTION_KEY before DB write.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"country":{"type":"string","enum":["MX","ES","AR","CO"]},"certificateBase64":{"type":"string","minLength":1},"privateKeyBase64":{"type":"string","minLength":1},"password":{"type":"string"},"pacCredentialsJson":{"type":"string"}},"required":["country","certificateBase64","privateKeyBase64"]}}}},"responses":{"200":{"description":"Certificate stored","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"certificateR2Key":{"type":"string"},"certificateExpiresAt":{"type":"integer","nullable":true}},"required":["ok","certificateR2Key","certificateExpiresAt"]}}}},"422":{"description":"Invalid certificate","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/numbering-incidents":{"get":{"tags":["Invoicing"],"summary":"List invoice numbering incidents (serial gaps, keyset by id DESC)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["F","R"]},"required":false,"name":"series","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Keyset-paginated numbering incident list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"series":{"type":"string","enum":["F","R"]},"seriesYear":{"type":"integer","nullable":true},"number":{"type":"integer"},"serialNumber":{"type":"string"},"orderId":{"type":"string","nullable":true},"refundId":{"type":"string","nullable":true},"reason":{"type":"string"},"createdAt":{"type":"integer"}},"required":["id","series","seriesYear","number","serialNumber","orderId","refundId","reason","createdAt"]}},"nextCursor":{"type":"string","nullable":true}},"required":["data","nextCursor"]}}}},"404":{"description":"Tenant DB unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/verifactu/records":{"get":{"tags":["Verifactu"],"summary":"List VERI*FACTU records (keyset pagination by chain_index, DESC)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["pending","sent","accepted","rejected","error"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":1},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Keyset-paginated record list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"invoiceId":{"type":"string"},"recordType":{"type":"string","enum":["alta","anulacion"]},"chainIndex":{"type":"integer"},"prevHash":{"type":"string","nullable":true},"hash":{"type":"string"},"payload":{"nullable":true},"qrUrl":{"type":"string","nullable":true},"aeatStatus":{"type":"string","enum":["pending","sent","accepted","rejected","error"]},"aeatResponse":{"nullable":true},"sifVersion":{"type":"string"},"createdAt":{"type":"integer"}},"required":["id","invoiceId","recordType","chainIndex","prevHash","hash","qrUrl","aeatStatus","sifVersion","createdAt"]}},"nextCursor":{"type":"integer","nullable":true}},"required":["data","nextCursor"]}}}},"404":{"description":"Tenant DB unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/verifactu/records/{id}":{"get":{"tags":["Verifactu"],"summary":"Get one VERI*FACTU record","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Record detail","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"invoiceId":{"type":"string"},"recordType":{"type":"string","enum":["alta","anulacion"]},"chainIndex":{"type":"integer"},"prevHash":{"type":"string","nullable":true},"hash":{"type":"string"},"payload":{"nullable":true},"qrUrl":{"type":"string","nullable":true},"aeatStatus":{"type":"string","enum":["pending","sent","accepted","rejected","error"]},"aeatResponse":{"nullable":true},"sifVersion":{"type":"string"},"createdAt":{"type":"integer"}},"required":["id","invoiceId","recordType","chainIndex","prevHash","hash","qrUrl","aeatStatus","sifVersion","createdAt"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/verifactu/declaracion-responsable":{"get":{"tags":["Verifactu"],"summary":"Declaración responsable del SIF (art. 13 RD 1007/2023)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"SIF identification + responsible declaration","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"sif":{"type":"object","properties":{"nombreSistemaInformatico":{"type":"string"},"idSistemaInformatico":{"type":"string"},"version":{"type":"string"},"nombreProductor":{"type":"string"},"nifProductor":{"type":"string"},"tipoUsoPosibleSoloVerifactu":{"type":"string"},"tipoUsoPosibleMultiOT":{"type":"string"},"indicadorMultiplesOT":{"type":"string"}},"required":["nombreSistemaInformatico","idSistemaInformatico","version","nombreProductor","nifProductor","tipoUsoPosibleSoloVerifactu","tipoUsoPosibleMultiOT","indicadorMultiplesOT"]},"sifVersion":{"type":"string"},"modalidad":{"type":"string"},"normativa":{"type":"array","items":{"type":"string"}},"declaracion":{"type":"string"}},"required":["sif","sifVersion","modalidad","normativa","declaracion"]}},"required":["data"]}}}}}}},"/v1/verifactu/records/{id}/retry":{"post":{"tags":["Verifactu"],"summary":"Retry AEAT remission for a failed/pending record (admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Remission re-attempted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"invoiceId":{"type":"string"},"recordType":{"type":"string","enum":["alta","anulacion"]},"chainIndex":{"type":"integer"},"prevHash":{"type":"string","nullable":true},"hash":{"type":"string"},"payload":{"nullable":true},"qrUrl":{"type":"string","nullable":true},"aeatStatus":{"type":"string","enum":["pending","sent","accepted","rejected","error"]},"aeatResponse":{"nullable":true},"sifVersion":{"type":"string"},"createdAt":{"type":"integer"}},"required":["id","invoiceId","recordType","chainIndex","prevHash","hash","qrUrl","aeatStatus","sifVersion","createdAt"]},"result":{"type":"object","properties":{"status":{"type":"string","enum":["pending","sent","accepted","rejected","error"]},"sandbox":{"type":"boolean"},"detail":{"type":"string"}},"required":["status","sandbox"]}},"required":["data","result"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Record not retryable","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/invoices/{id}/verifactu-qr":{"get":{"tags":["Verifactu"],"summary":"Tributary QR (SVG) — AEAT cotejo URL of the invoice","description":"Server-side rendered QR (pure-TS encoder, byte mode, EC level M) whose payload is the AEAT verification URL persisted on the invoice alta record.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"QR as SVG","content":{"image/svg+xml":{"schema":{"type":"string"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/settings/verifactu":{"get":{"tags":["Verifactu"],"summary":"Get VERI*FACTU settings","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"VERI*FACTU settings","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"enabled":{"type":"boolean"},"nif":{"type":"string","nullable":true},"razonSocial":{"type":"string","nullable":true},"regime":{"type":"string","enum":["general","recargo_equivalencia"]},"siiExempt":{"type":"boolean"},"territory":{"type":"string","enum":["comun","araba","gipuzkoa","bizkaia"]}},"required":["enabled","nif","razonSocial","regime","siiExempt","territory"]}},"required":["data"]}}}},"404":{"description":"Tenant DB unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"put":{"tags":["Verifactu"],"summary":"Update VERI*FACTU settings","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"nif":{"type":"string","pattern":"^[A-Z0-9][0-9]{7}[A-Z0-9]$/i","example":"B12345678"},"razonSocial":{"type":"string","minLength":1,"maxLength":120,"example":"Mi Tienda S.L."},"regime":{"type":"string","enum":["general","recargo_equivalencia"],"default":"general"},"siiExempt":{"type":"boolean","default":false},"territory":{"type":"string","enum":["comun","araba","gipuzkoa","bizkaia"],"default":"comun"}},"required":["enabled"]}}}},"responses":{"200":{"description":"Settings updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"enabled":{"type":"boolean"},"nif":{"type":"string","nullable":true},"razonSocial":{"type":"string","nullable":true},"regime":{"type":"string","enum":["general","recargo_equivalencia"]},"siiExempt":{"type":"boolean"},"territory":{"type":"string","enum":["comun","araba","gipuzkoa","bizkaia"]}},"required":["enabled","nif","razonSocial","regime","siiExempt","territory"]}},"required":["data"]}}}},"404":{"description":"Tenant DB unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Invalid combination","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/verifactu/chain-audit":{"get":{"tags":["Verifactu"],"summary":"Audit the tenant VERI*FACTU chain (recompute every huella)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Chain verification result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"valid":{"type":"boolean"},"recordsChecked":{"type":"number"},"brokenAtChainIndex":{"type":"number","nullable":true},"reason":{"type":"string","nullable":true},"empty":{"type":"boolean"}},"required":["valid","recordsChecked","brokenAtChainIndex","reason","empty"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/verifactu/reclassify-sandbox":{"post":{"tags":["Verifactu"],"summary":"Reclassify dry-run (sandbox) records back to pending (admin)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Number of records reclassified","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"reclassified":{"type":"number"}},"required":["reclassified"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/verifactu/malformed-recipients":{"get":{"tags":["Verifactu"],"summary":"List pre-1.1.1 alta records with non-AEAT-conformant IDOtro (subsanación inventory)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","nullable":true,"minimum":0},"required":false,"name":"after","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"default":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Malformed recipient inventory (keyset by chain_index, ASC)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"count":{"type":"number"},"items":{"type":"array","items":{"type":"object","properties":{"recordId":{"type":"string"},"chainIndex":{"type":"number"},"invoiceId":{"type":"string"},"serial":{"type":"string","nullable":true},"sifVersion":{"type":"string"},"idOtro":{"type":"object","properties":{"codigoPais":{"type":"string"},"idType":{"type":"string"},"id":{"type":"string"}},"required":["codigoPais","idType","id"]},"suggested":{"type":"object","properties":{"codigoPais":{"type":"string"},"idType":{"type":"string","enum":["02","04"]}},"required":["codigoPais","idType"]}},"required":["recordId","chainIndex","invoiceId","serial","sifVersion","idOtro","suggested"]}},"nextAfter":{"type":"number","nullable":true}},"required":["count","items","nextAfter"]}},"required":["data"]}}}},"404":{"description":"Tenant DB unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tbai/records":{"get":{"tags":["TicketBAI"],"summary":"List TicketBAI records (keyset pagination by chain_index, DESC)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["pending","signed","sent","accepted","rejected","error"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","enum":["araba","gipuzkoa","bizkaia"]},"required":false,"name":"territory","in":"query"},{"schema":{"type":"integer","minimum":1},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Keyset-paginated TicketBAI record list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"invoiceId":{"type":"string"},"territory":{"type":"string","enum":["araba","gipuzkoa","bizkaia"]},"recordType":{"type":"string","enum":["alta","anulacion"]},"chainIndex":{"type":"integer"},"prevSignature":{"type":"string","nullable":true},"tbaiIdentifier":{"type":"string","nullable":true},"xmlR2Key":{"type":"string","nullable":true},"signatureValue":{"type":"string","nullable":true},"qrUrl":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","signed","sent","accepted","rejected","error"]},"authorityResponse":{"nullable":true},"createdAt":{"type":"integer"}},"required":["id","invoiceId","territory","recordType","chainIndex","prevSignature","tbaiIdentifier","xmlR2Key","signatureValue","qrUrl","status","createdAt"]}},"nextCursor":{"type":"integer","nullable":true}},"required":["data","nextCursor"]}}}},"404":{"description":"Tenant DB unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tbai/records/{id}":{"get":{"tags":["TicketBAI"],"summary":"Get one TicketBAI record","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Record detail","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"invoiceId":{"type":"string"},"territory":{"type":"string","enum":["araba","gipuzkoa","bizkaia"]},"recordType":{"type":"string","enum":["alta","anulacion"]},"chainIndex":{"type":"integer"},"prevSignature":{"type":"string","nullable":true},"tbaiIdentifier":{"type":"string","nullable":true},"xmlR2Key":{"type":"string","nullable":true},"signatureValue":{"type":"string","nullable":true},"qrUrl":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","signed","sent","accepted","rejected","error"]},"authorityResponse":{"nullable":true},"createdAt":{"type":"integer"}},"required":["id","invoiceId","territory","recordType","chainIndex","prevSignature","tbaiIdentifier","xmlR2Key","signatureValue","qrUrl","status","createdAt"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/tbai/records/{id}/retry":{"post":{"tags":["TicketBAI"],"summary":"Retry foral remission for a signed/error record (admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Remission re-attempted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"invoiceId":{"type":"string"},"territory":{"type":"string","enum":["araba","gipuzkoa","bizkaia"]},"recordType":{"type":"string","enum":["alta","anulacion"]},"chainIndex":{"type":"integer"},"prevSignature":{"type":"string","nullable":true},"tbaiIdentifier":{"type":"string","nullable":true},"xmlR2Key":{"type":"string","nullable":true},"signatureValue":{"type":"string","nullable":true},"qrUrl":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","signed","sent","accepted","rejected","error"]},"authorityResponse":{"nullable":true},"createdAt":{"type":"integer"}},"required":["id","invoiceId","territory","recordType","chainIndex","prevSignature","tbaiIdentifier","xmlR2Key","signatureValue","qrUrl","status","createdAt"]},"result":{"type":"object","properties":{"status":{"type":"string","enum":["pending","signed","sent","accepted","rejected","error"]},"sandbox":{"type":"boolean"},"detail":{"type":"string"}},"required":["status","sandbox"]}},"required":["data","result"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Record not retryable","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/einvoices":{"get":{"tags":["EInvoices"],"summary":"List B2B e-invoices (keyset pagination, newest first)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["issued","sent","registered_public","accepted","rejected","paid_partial","paid_full"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","enum":["facturae","ubl"]},"required":false,"name":"format","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Keyset-paginated e-invoice list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"invoiceId":{"type":"string"},"orderId":{"type":"string","nullable":true},"format":{"type":"string","enum":["facturae","ubl"]},"xmlR2Key":{"type":"string"},"signed":{"type":"boolean"},"status":{"type":"string","enum":["issued","sent","registered_public","accepted","rejected","paid_partial","paid_full"]},"statusHistory":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string","nullable":true,"enum":["issued","sent","registered_public","accepted","rejected","paid_partial","paid_full",null]},"to":{"type":"string","enum":["issued","sent","registered_public","accepted","rejected","paid_partial","paid_full"]},"at":{"type":"integer"},"actor":{"type":"string"},"note":{"type":"string"}},"required":["from","to","at","actor"]}},"buyerTaxId":{"type":"string","nullable":true},"dueAt":{"type":"integer","nullable":true},"lastStateNotifiedAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","invoiceId","orderId","format","xmlR2Key","signed","status","statusHistory","buyerTaxId","dueAt","lastStateNotifiedAt","createdAt","updatedAt"]}},"nextCursor":{"type":"string","nullable":true}},"required":["data","nextCursor"]}}}},"404":{"description":"Tenant DB unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/einvoices/{id}":{"get":{"tags":["EInvoices"],"summary":"Get one B2B e-invoice","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"E-invoice detail","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"invoiceId":{"type":"string"},"orderId":{"type":"string","nullable":true},"format":{"type":"string","enum":["facturae","ubl"]},"xmlR2Key":{"type":"string"},"signed":{"type":"boolean"},"status":{"type":"string","enum":["issued","sent","registered_public","accepted","rejected","paid_partial","paid_full"]},"statusHistory":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string","nullable":true,"enum":["issued","sent","registered_public","accepted","rejected","paid_partial","paid_full",null]},"to":{"type":"string","enum":["issued","sent","registered_public","accepted","rejected","paid_partial","paid_full"]},"at":{"type":"integer"},"actor":{"type":"string"},"note":{"type":"string"}},"required":["from","to","at","actor"]}},"buyerTaxId":{"type":"string","nullable":true},"dueAt":{"type":"integer","nullable":true},"lastStateNotifiedAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","invoiceId","orderId","format","xmlR2Key","signed","status","statusHistory","buyerTaxId","dueAt","lastStateNotifiedAt","createdAt","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/einvoices/{id}/status":{"post":{"tags":["EInvoices"],"summary":"Transition a B2B e-invoice state (admin)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","enum":["sent","registered_public","accepted","rejected","paid_partial","paid_full"]},"note":{"type":"string","maxLength":500}},"required":["to"]}}}},"responses":{"200":{"description":"State transitioned","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"invoiceId":{"type":"string"},"orderId":{"type":"string","nullable":true},"format":{"type":"string","enum":["facturae","ubl"]},"xmlR2Key":{"type":"string"},"signed":{"type":"boolean"},"status":{"type":"string","enum":["issued","sent","registered_public","accepted","rejected","paid_partial","paid_full"]},"statusHistory":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string","nullable":true,"enum":["issued","sent","registered_public","accepted","rejected","paid_partial","paid_full",null]},"to":{"type":"string","enum":["issued","sent","registered_public","accepted","rejected","paid_partial","paid_full"]},"at":{"type":"integer"},"actor":{"type":"string"},"note":{"type":"string"}},"required":["from","to","at","actor"]}},"buyerTaxId":{"type":"string","nullable":true},"dueAt":{"type":"integer","nullable":true},"lastStateNotifiedAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","invoiceId","orderId","format","xmlR2Key","signed","status","statusHistory","buyerTaxId","dueAt","lastStateNotifiedAt","createdAt","updatedAt"]},"publicCopy":{"type":"object","nullable":true,"properties":{"attempted":{"type":"boolean"},"sandbox":{"type":"boolean"},"ok":{"type":"boolean"},"detail":{"type":"string"}},"required":["attempted","sandbox","ok"]}},"required":["data","publicCopy"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Invalid transition","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/analytics/kpis-bundle":{"get":{"tags":["Analytics"],"summary":"Get all KPIs, sparklines, anomalies and trends in one request","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"from","in":"query"},{"schema":{"type":"string"},"required":true,"name":"to","in":"query"},{"schema":{"type":"string"},"required":false,"name":"compareFrom","in":"query"},{"schema":{"type":"string"},"required":false,"name":"compareTo","in":"query"}],"responses":{"200":{"description":"KPIs bundle","content":{"application/json":{"schema":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD"},"kpis":{"type":"object","properties":{"totalRevenue":{"type":"number"},"orderCount":{"type":"number"},"customerCount":{"type":"number"},"averageOrderValue":{"type":"number"},"conversionRate":{"type":"number"},"refundRate":{"type":"number"},"cartAbandonmentRate":{"type":"number"},"topProduct":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"},"revenue":{"type":"number"},"quantity":{"type":"number"},"image":{"type":"string"}},"required":["id","name","revenue","quantity"]}},"required":["totalRevenue","orderCount","customerCount","averageOrderValue","conversionRate","refundRate","cartAbandonmentRate","topProduct"]},"sparklines":{"type":"object","properties":{"totalRevenue":{"type":"array","items":{"type":"number"}},"orderCount":{"type":"array","items":{"type":"number"}},"averageOrderValue":{"type":"array","items":{"type":"number"}}},"required":["totalRevenue","orderCount","averageOrderValue"]},"anomalies":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"metric":{"type":"string"},"expected":{"type":"number"},"actual":{"type":"number"},"severity":{"type":"string","enum":["low","medium","high"]},"explanation":{"type":"string"}},"required":["date","metric","expected","actual","severity","explanation"]}},"trends":{"type":"object","properties":{"revenueTrend":{"type":"number"},"orderCountTrend":{"type":"number"},"customerCountTrend":{"type":"number"},"aovTrend":{"type":"number"},"conversionRateTrend":{"type":"number"},"refundRateTrend":{"type":"number"},"cartAbandonmentTrend":{"type":"number"}},"required":["revenueTrend","orderCountTrend","customerCountTrend","aovTrend","conversionRateTrend","refundRateTrend","cartAbandonmentTrend"]}},"required":["currency","kpis","sparklines","anomalies","trends"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/analytics/revenue":{"get":{"tags":["Analytics"],"summary":"Get revenue timeseries","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"from","in":"query"},{"schema":{"type":"string"},"required":true,"name":"to","in":"query"},{"schema":{"type":"string","enum":["hour","day","week","month"],"default":"day"},"required":false,"name":"granularity","in":"query"}],"responses":{"200":{"description":"Revenue series","content":{"application/json":{"schema":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD"},"series":{"type":"array","items":{"type":"object","properties":{"t":{"type":"string"},"revenue":{"type":"number"},"orderCount":{"type":"number"}},"required":["t","revenue","orderCount"]}},"total":{"type":"number"}},"required":["currency","series","total"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/analytics/timeseries":{"get":{"tags":["Analytics"],"summary":"Get multi-metric timeseries","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"from","in":"query"},{"schema":{"type":"string"},"required":true,"name":"to","in":"query"},{"schema":{"type":"string","enum":["hour","day","week","month"],"default":"day"},"required":false,"name":"granularity","in":"query"}],"responses":{"200":{"description":"Timeseries data","content":{"application/json":{"schema":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3,"example":"USD"},"granularity":{"type":"string"},"data":{"type":"array","items":{"type":"object","properties":{"t":{"type":"string"},"revenue":{"type":"number"},"orderCount":{"type":"number"},"customerCount":{"type":"number"},"refundCount":{"type":"number"}},"required":["t","revenue","orderCount","customerCount","refundCount"]}}},"required":["currency","granularity","data"]}}}},"400":{"description":"Range exceeds max for granularity","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status","detail"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/analytics/top-products":{"get":{"tags":["Analytics"],"summary":"Get top products by revenue","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"from","in":"query"},{"schema":{"type":"string"},"required":true,"name":"to","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":10},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Top products","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"revenue":{"type":"number"},"quantity":{"type":"number"},"image":{"type":"string"}},"required":["id","name","revenue","quantity"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/analytics/orders-by-status":{"get":{"tags":["Analytics"],"summary":"Get order counts grouped by status","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"from","in":"query"},{"schema":{"type":"string"},"required":true,"name":"to","in":"query"}],"responses":{"200":{"description":"Orders by status","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string"},"count":{"type":"number"},"percentage":{"type":"number"}},"required":["status","count","percentage"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/activity":{"get":{"tags":["Analytics"],"summary":"Get recent activity feed","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"integer","nullable":true},"required":false,"name":"since","in":"query"}],"responses":{"200":{"description":"Activity feed","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["order","customer","product","refund","system","rma","subscription","gift_card"]},"title":{"type":"string"},"description":{"type":"string"},"timestamp":{"type":"number"},"tenantId":{"type":"string"}},"required":["id","type","title","description","timestamp","tenantId"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/analytics/behavior":{"get":{"tags":["Analytics"],"summary":"First-party behavioural funnel (views → cart → order)","description":"Aggregates SPINE-B behavioural events into a views/cart/order funnel + per-product engagement. First-party, cookieless.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"2026-05-01"},"required":true,"name":"from","in":"query"},{"schema":{"type":"string","example":"2026-06-01"},"required":true,"name":"to","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Behavioural funnel","content":{"application/json":{"schema":{"type":"object","properties":{"totals":{"type":"object","properties":{"views":{"type":"integer"},"carts":{"type":"integer"},"orders":{"type":"integer"}},"required":["views","carts","orders"]},"rates":{"type":"object","properties":{"viewToCart":{"type":"number"},"cartToOrder":{"type":"number"},"viewToOrder":{"type":"number"}},"required":["viewToCart","cartToOrder","viewToOrder"]},"products":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string"},"name":{"type":"string"},"views":{"type":"integer"},"carts":{"type":"integer"},"orders":{"type":"integer"},"viewToCart":{"type":"number"},"cartToOrder":{"type":"number"},"viewToOrder":{"type":"number"}},"required":["productId","name","views","carts","orders","viewToCart","cartToOrder","viewToOrder"]}}},"required":["totals","rates","products"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/campaigns":{"get":{"tags":["Marketing Campaigns"],"summary":"List campaigns","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["draft","scheduled","sending","sent","cancelled","failed"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","maxLength":100},"required":false,"name":"search","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"List of campaigns","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"camp_01"},"tenant_id":{"type":"string"},"name":{"type":"string","example":"Spring Sale 2026"},"subject":{"type":"string","example":"🌸 Spring deals inside!"},"preview_text":{"type":"string","nullable":true},"from_name":{"type":"string","nullable":true},"from_email":{"type":"string","nullable":true,"format":"email"},"reply_to":{"type":"string","nullable":true,"format":"email"},"html_body":{"type":"string"},"plain_text_body":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","scheduled","sending","sent","cancelled","failed"]},"segment_id":{"type":"string","nullable":true},"send_mode":{"type":"string","enum":["now","scheduled"]},"scheduled_at":{"type":"integer","nullable":true},"sent_at":{"type":"integer","nullable":true},"recipient_count":{"type":"integer","default":0},"open_count":{"type":"integer","default":0},"click_count":{"type":"integer","default":0},"unsubscribe_count":{"type":"integer","default":0},"bounce_count":{"type":"integer","default":0},"created_by":{"type":"string","nullable":true},"created_at":{"type":"integer"},"updated_at":{"type":"integer"}},"required":["id","tenant_id","name","subject","html_body","status","send_mode","created_at","updated_at"]}},"total":{"type":"integer"},"page":{"type":"integer"},"per_page":{"type":"integer"}},"required":["data","total","page","per_page"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Marketing Campaigns"],"summary":"Create a campaign (status=draft)","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"example":"Spring Sale 2026"},"subject":{"type":"string","minLength":1,"maxLength":998,"example":"🌸 Spring deals inside!"},"preview_text":{"type":"string","maxLength":200},"from_name":{"type":"string","maxLength":100},"from_email":{"type":"string","format":"email"},"reply_to":{"type":"string","format":"email"},"html_body":{"type":"string","minLength":1},"plain_text_body":{"type":"string"},"segment_id":{"type":"string"},"send_mode":{"type":"string","enum":["now","scheduled"],"default":"now"}},"required":["name","subject","html_body"]}}}},"responses":{"201":{"description":"Campaign created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"camp_01"},"tenant_id":{"type":"string"},"name":{"type":"string","example":"Spring Sale 2026"},"subject":{"type":"string","example":"🌸 Spring deals inside!"},"preview_text":{"type":"string","nullable":true},"from_name":{"type":"string","nullable":true},"from_email":{"type":"string","nullable":true,"format":"email"},"reply_to":{"type":"string","nullable":true,"format":"email"},"html_body":{"type":"string"},"plain_text_body":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","scheduled","sending","sent","cancelled","failed"]},"segment_id":{"type":"string","nullable":true},"send_mode":{"type":"string","enum":["now","scheduled"]},"scheduled_at":{"type":"integer","nullable":true},"sent_at":{"type":"integer","nullable":true},"recipient_count":{"type":"integer","default":0},"open_count":{"type":"integer","default":0},"click_count":{"type":"integer","default":0},"unsubscribe_count":{"type":"integer","default":0},"bounce_count":{"type":"integer","default":0},"created_by":{"type":"string","nullable":true},"created_at":{"type":"integer"},"updated_at":{"type":"integer"}},"required":["id","tenant_id","name","subject","html_body","status","send_mode","created_at","updated_at"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/campaigns/{id}":{"get":{"tags":["Marketing Campaigns"],"summary":"Get a campaign by ID","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Campaign","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"camp_01"},"tenant_id":{"type":"string"},"name":{"type":"string","example":"Spring Sale 2026"},"subject":{"type":"string","example":"🌸 Spring deals inside!"},"preview_text":{"type":"string","nullable":true},"from_name":{"type":"string","nullable":true},"from_email":{"type":"string","nullable":true,"format":"email"},"reply_to":{"type":"string","nullable":true,"format":"email"},"html_body":{"type":"string"},"plain_text_body":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","scheduled","sending","sent","cancelled","failed"]},"segment_id":{"type":"string","nullable":true},"send_mode":{"type":"string","enum":["now","scheduled"]},"scheduled_at":{"type":"integer","nullable":true},"sent_at":{"type":"integer","nullable":true},"recipient_count":{"type":"integer","default":0},"open_count":{"type":"integer","default":0},"click_count":{"type":"integer","default":0},"unsubscribe_count":{"type":"integer","default":0},"bounce_count":{"type":"integer","default":0},"created_by":{"type":"string","nullable":true},"created_at":{"type":"integer"},"updated_at":{"type":"integer"}},"required":["id","tenant_id","name","subject","html_body","status","send_mode","created_at","updated_at"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Marketing Campaigns"],"summary":"Update a draft campaign","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"subject":{"type":"string","minLength":1,"maxLength":998},"preview_text":{"type":"string","nullable":true,"maxLength":200},"from_name":{"type":"string","nullable":true,"maxLength":100},"from_email":{"type":"string","nullable":true,"format":"email"},"reply_to":{"type":"string","nullable":true,"format":"email"},"html_body":{"type":"string","minLength":1},"plain_text_body":{"type":"string","nullable":true},"segment_id":{"type":"string","nullable":true},"send_mode":{"type":"string","enum":["now","scheduled"]}}}}}},"responses":{"200":{"description":"Campaign updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"camp_01"},"tenant_id":{"type":"string"},"name":{"type":"string","example":"Spring Sale 2026"},"subject":{"type":"string","example":"🌸 Spring deals inside!"},"preview_text":{"type":"string","nullable":true},"from_name":{"type":"string","nullable":true},"from_email":{"type":"string","nullable":true,"format":"email"},"reply_to":{"type":"string","nullable":true,"format":"email"},"html_body":{"type":"string"},"plain_text_body":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","scheduled","sending","sent","cancelled","failed"]},"segment_id":{"type":"string","nullable":true},"send_mode":{"type":"string","enum":["now","scheduled"]},"scheduled_at":{"type":"integer","nullable":true},"sent_at":{"type":"integer","nullable":true},"recipient_count":{"type":"integer","default":0},"open_count":{"type":"integer","default":0},"click_count":{"type":"integer","default":0},"unsubscribe_count":{"type":"integer","default":0},"bounce_count":{"type":"integer","default":0},"created_by":{"type":"string","nullable":true},"created_at":{"type":"integer"},"updated_at":{"type":"integer"}},"required":["id","tenant_id","name","subject","html_body","status","send_mode","created_at","updated_at"]}}}},"400":{"description":"Cannot edit non-draft campaign","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Marketing Campaigns"],"summary":"Delete a campaign (draft/scheduled/cancelled/failed only)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Campaign deleted"},"400":{"description":"Cannot delete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/campaigns/{id}/send-now":{"post":{"tags":["Marketing Campaigns"],"summary":"Send a draft campaign immediately (async via waitUntil)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"202":{"description":"Send dispatched","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"campaign_id":{"type":"string"}},"required":["message","campaign_id"]}}}},"400":{"description":"Cannot send","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/campaigns/{id}/schedule":{"post":{"tags":["Marketing Campaigns"],"summary":"Schedule a campaign for future send","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"scheduled_at":{"type":"string","format":"date-time","example":"2026-06-15T09:00:00Z"}},"required":["scheduled_at"]}}}},"responses":{"200":{"description":"Campaign scheduled","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"camp_01"},"tenant_id":{"type":"string"},"name":{"type":"string","example":"Spring Sale 2026"},"subject":{"type":"string","example":"🌸 Spring deals inside!"},"preview_text":{"type":"string","nullable":true},"from_name":{"type":"string","nullable":true},"from_email":{"type":"string","nullable":true,"format":"email"},"reply_to":{"type":"string","nullable":true,"format":"email"},"html_body":{"type":"string"},"plain_text_body":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","scheduled","sending","sent","cancelled","failed"]},"segment_id":{"type":"string","nullable":true},"send_mode":{"type":"string","enum":["now","scheduled"]},"scheduled_at":{"type":"integer","nullable":true},"sent_at":{"type":"integer","nullable":true},"recipient_count":{"type":"integer","default":0},"open_count":{"type":"integer","default":0},"click_count":{"type":"integer","default":0},"unsubscribe_count":{"type":"integer","default":0},"bounce_count":{"type":"integer","default":0},"created_by":{"type":"string","nullable":true},"created_at":{"type":"integer"},"updated_at":{"type":"integer"}},"required":["id","tenant_id","name","subject","html_body","status","send_mode","created_at","updated_at"]}}}},"400":{"description":"Invalid state or time","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/campaigns/{id}/cancel":{"post":{"tags":["Marketing Campaigns"],"summary":"Cancel a scheduled campaign","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Campaign cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"camp_01"},"tenant_id":{"type":"string"},"name":{"type":"string","example":"Spring Sale 2026"},"subject":{"type":"string","example":"🌸 Spring deals inside!"},"preview_text":{"type":"string","nullable":true},"from_name":{"type":"string","nullable":true},"from_email":{"type":"string","nullable":true,"format":"email"},"reply_to":{"type":"string","nullable":true,"format":"email"},"html_body":{"type":"string"},"plain_text_body":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","scheduled","sending","sent","cancelled","failed"]},"segment_id":{"type":"string","nullable":true},"send_mode":{"type":"string","enum":["now","scheduled"]},"scheduled_at":{"type":"integer","nullable":true},"sent_at":{"type":"integer","nullable":true},"recipient_count":{"type":"integer","default":0},"open_count":{"type":"integer","default":0},"click_count":{"type":"integer","default":0},"unsubscribe_count":{"type":"integer","default":0},"bounce_count":{"type":"integer","default":0},"created_by":{"type":"string","nullable":true},"created_at":{"type":"integer"},"updated_at":{"type":"integer"}},"required":["id","tenant_id","name","subject","html_body","status","send_mode","created_at","updated_at"]}}}},"400":{"description":"Cannot cancel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/campaigns/{id}/stats":{"get":{"tags":["Marketing Campaigns"],"summary":"Get campaign statistics","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Campaign stats","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"recipient_count":{"type":"integer"},"open_count":{"type":"integer"},"click_count":{"type":"integer"},"unsubscribe_count":{"type":"integer"},"bounce_count":{"type":"integer"},"open_rate":{"type":"number"},"click_rate":{"type":"number"},"unsubscribe_rate":{"type":"number"},"bounce_rate":{"type":"number"}},"required":["id","recipient_count","open_count","click_count","unsubscribe_count","bounce_count"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/campaigns/{id}/recipients":{"get":{"tags":["Marketing Campaigns"],"summary":"List campaign recipients with pagination","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["pending","sent","delivered","opened","clicked","bounced","unsubscribed","failed"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"List of recipients","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"campaign_id":{"type":"string"},"email":{"type":"string","format":"email"},"customer_id":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","sent","delivered","opened","clicked","bounced","unsubscribed","failed"]},"sent_at":{"type":"integer","nullable":true},"opened_at":{"type":"integer","nullable":true},"clicked_at":{"type":"integer","nullable":true},"message_id":{"type":"string","nullable":true},"error":{"type":"string","nullable":true},"created_at":{"type":"integer"}},"required":["id","campaign_id","email","status","created_at"]}},"total":{"type":"integer"},"page":{"type":"integer"},"per_page":{"type":"integer"}},"required":["data","total","page","per_page"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/ai/insights":{"post":{"tags":["AI"],"summary":"Stream AI-generated business insights","description":"Generates actionable insights as SSE typed events. Plan: growth+","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kpis":{"type":"object","additionalProperties":{"nullable":true}},"snapshot":{"type":"object","additionalProperties":{"nullable":true}},"locale":{"type":"string","default":"en"},"currency":{"type":"string","minLength":3,"maxLength":3,"default":"USD"}}}}}},"responses":{"200":{"description":"SSE stream of insight/done/error events","content":{"text/event-stream":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}},"402":{"description":"Plan upgrade required","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status","detail"]}}}}}}},"/v1/ai/copilot/chat":{"post":{"tags":["AI"],"summary":"Stream AI copilot chat with tool use","description":"SSE Anthropic verbatim passthrough including tool_use blocks. 6 server-side tool executors.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","additionalProperties":{"nullable":true}}}]}},"required":["role","content"]},"minItems":1},"conversationId":{"type":"string"}},"required":["messages"]}}}},"responses":{"200":{"description":"SSE stream of Anthropic verbatim events","content":{"text/event-stream":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/ai/copilot/history":{"get":{"tags":["AI"],"summary":"Get copilot conversation history","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"conversationId","in":"query"}],"responses":{"200":{"description":"Conversation history","content":{"application/json":{"schema":{"type":"object","properties":{"conversationId":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","additionalProperties":{"nullable":true}}}]}},"required":["role","content"]}},"updatedAt":{"type":"number"}},"required":["conversationId","messages","updatedAt"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["AI"],"summary":"Save copilot conversation history","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"conversationId":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","additionalProperties":{"nullable":true}}}]}},"required":["role","content"]},"minItems":1}},"required":["conversationId","messages"]}}}},"responses":{"200":{"description":"Saved","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}}}}},"/v1/ai/remove-bg":{"post":{"tags":["AI"],"summary":"Remove image background","description":"Removes the background from an image using @cf/bria/rmbg. Requires growth+ plan.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"image":{"type":"string","minLength":1,"maxLength":6990507,"example":"iVBORw0KGgoAAAANSUhEUgAA...","description":"Base64-encoded PNG or JPG image (max 5MB)"}},"required":["image"]}}}},"responses":{"200":{"description":"Background removed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"processedImage":{"type":"string","description":"Base64-encoded PNG with background removed"}},"required":["processedImage"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"402":{"description":"Plan upgrade required (growth+ only)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"429":{"description":"Rate limit exceeded (60 req/h per tenant)","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"AI inference error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"503":{"description":"AI binding not configured in this environment","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/ai/generate-description":{"post":{"tags":["AI"],"summary":"Generate AI product description with SEO meta","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"productId":{"type":"string","minLength":1},"tone":{"type":"string","enum":["professional","friendly","luxury","technical"]},"length":{"type":"string","enum":["short","medium","long"]},"keywords":{"type":"array","items":{"type":"string"},"maxItems":10}},"required":["productId"]}}}},"responses":{"200":{"description":"Generated","content":{"application/json":{"schema":{"type":"object","properties":{"description":{"type":"string"},"html":{"type":"string"},"seo_meta":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"keywords":{"type":"array","items":{"type":"string"}}},"required":["title","description","keywords"]}},"required":["description","html","seo_meta"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/ai/inventory-recommend":{"post":{"tags":["AI"],"summary":"AI-driven restock recommendations","security":[{"bearerAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"productId":{"type":"string","minLength":1},"threshold":{"type":"string","enum":["low","critical"]}}}}}},"responses":{"200":{"description":"Recommendations","content":{"application/json":{"schema":{"type":"object","properties":{"recommendations":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string"},"productName":{"type":"string"},"currentStock":{"type":"number"},"daysOfStock":{"type":"number"},"recommendedQuantity":{"type":"number"},"suggestedRestockDate":{"type":"string"},"reasoning":{"type":"string"}},"required":["productId","productName","currentStock","daysOfStock","recommendedQuantity","suggestedRestockDate","reasoning"]}}},"required":["recommendations"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/ai/customer-reply":{"post":{"tags":["AI"],"summary":"Draft 3 AI-suggested customer support replies","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"customerId":{"type":"string","minLength":1},"customerMessage":{"type":"string","minLength":1,"maxLength":4000},"context":{"type":"string","enum":["order_inquiry","complaint","general"]}},"required":["customerId","customerMessage"]}}}},"responses":{"200":{"description":"Replies","content":{"application/json":{"schema":{"type":"object","properties":{"replies":{"type":"array","items":{"type":"object","properties":{"tone":{"type":"string","enum":["professional","friendly","concise"]},"text":{"type":"string"}},"required":["tone","text"]}}},"required":["replies"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/ai/churn-risk-score":{"post":{"tags":["AI"],"summary":"Compute AI-powered churn risk score for a customer","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"customerId":{"type":"string","minLength":1},"includeReasoning":{"type":"boolean"}},"required":["customerId"]}}}},"responses":{"200":{"description":"Churn risk result","content":{"application/json":{"schema":{"type":"object","properties":{"riskScore":{"type":"number","minimum":0,"maximum":100},"riskLevel":{"type":"string","enum":["low","medium","high","critical"]},"factors":{"type":"array","items":{"type":"object","properties":{"factor":{"type":"string"},"weight":{"type":"number"},"reasoning":{"type":"string"}},"required":["factor","weight"]}},"recommendedActions":{"type":"array","items":{"type":"string"}},"computedAt":{"type":"string"},"cached":{"type":"boolean"}},"required":["riskScore","riskLevel","factors","recommendedActions","computedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/ai/churn-risk-score/bulk":{"post":{"tags":["AI"],"summary":"Bulk churn risk score for up to 50 customers","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"customerIds":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":50},"includeReasoning":{"type":"boolean"}},"required":["customerIds"]}}}},"responses":{"200":{"description":"Bulk results","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"customerId":{"type":"string"},"result":{"type":"object","properties":{"riskScore":{"type":"number","minimum":0,"maximum":100},"riskLevel":{"type":"string","enum":["low","medium","high","critical"]},"factors":{"type":"array","items":{"type":"object","properties":{"factor":{"type":"string"},"weight":{"type":"number"},"reasoning":{"type":"string"}},"required":["factor","weight"]}},"recommendedActions":{"type":"array","items":{"type":"string"}},"computedAt":{"type":"string"},"cached":{"type":"boolean"}},"required":["riskScore","riskLevel","factors","recommendedActions","computedAt"]},"error":{"type":"string"}},"required":["customerId"]}}},"required":["results"]}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/ai/churn-risk-score/cache/:customerId":{"delete":{"tags":["AI"],"summary":"Invalidate cached churn risk score for a customer","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"customerId","in":"path"}],"responses":{"200":{"description":"Cache cleared","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/ai/fraud-detection":{"post":{"tags":["AI"],"summary":"AI-powered fraud risk assessment for an order","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"orderId":{"type":"string","minLength":1},"includeReasoning":{"type":"boolean"}},"required":["orderId"]}}}},"responses":{"200":{"description":"Fraud detection result","content":{"application/json":{"schema":{"type":"object","properties":{"riskScore":{"type":"number","minimum":0,"maximum":100},"riskLevel":{"type":"string","enum":["low","medium","high","critical"]},"flags":{"type":"array","items":{"type":"object","properties":{"flag":{"type":"string"},"severity":{"type":"string","enum":["low","medium","high"]},"reasoning":{"type":"string"}},"required":["flag","severity"]}},"recommendedAction":{"type":"string","enum":["approve","review","hold","reject"]},"computedAt":{"type":"string"},"wasAutoHeld":{"type":"boolean"},"cached":{"type":"boolean"}},"required":["riskScore","riskLevel","flags","recommendedAction","computedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/ai/fraud-detection/cache/:orderId":{"delete":{"tags":["AI"],"summary":"Invalidate cached fraud detection result for an order","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"orderId","in":"path"}],"responses":{"200":{"description":"Cache cleared","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/ai/translate-products":{"post":{"tags":["AI"],"summary":"AI-translate product content into target locales","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"productId":{"type":"string","minLength":1},"targetLocales":{"type":"array","items":{"type":"string","minLength":2,"maxLength":10},"minItems":1,"maxItems":20},"fields":{"type":"array","items":{"type":"string","enum":["name","content"]}}},"required":["productId","targetLocales"]}}}},"responses":{"200":{"description":"Translated","content":{"application/json":{"schema":{"type":"object","properties":{"productId":{"type":"string"},"translations":{"type":"array","items":{"type":"object","properties":{"locale":{"type":"string"},"field":{"type":"string","enum":["name","content"]},"value":{"type":"string"}},"required":["locale","field","value"]}}},"required":["productId","translations"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/ai/flow-builder":{"post":{"tags":["AI"],"summary":"Generate a validated automation flow from natural language","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"description":{"type":"string","minLength":3,"maxLength":2000},"samplePayload":{"type":"object","additionalProperties":{"nullable":true}}},"required":["description"]}}}},"responses":{"200":{"description":"Flow","content":{"application/json":{"schema":{"type":"object","properties":{"flow":{"nullable":true},"dryRunMatched":{"type":"boolean"}}}}}},"400":{"description":"Could not produce a valid flow","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/ai/copilot/agent":{"post":{"tags":["AI"],"summary":"Multi-step agentic copilot (httpOnly-gated)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"nullable":true}}]}},"required":["role","content"]},"minItems":1},"maxIterations":{"type":"integer","minimum":1,"maximum":12}},"required":["messages"]}}}},"responses":{"200":{"description":"Answer + tool trace","content":{"application/json":{"schema":{"type":"object","properties":{"finalText":{"type":"string"},"steps":{"type":"array","items":{"type":"object","properties":{"tool":{"type":"string"},"input":{"type":"object","additionalProperties":{"nullable":true}},"result":{"type":"string"},"isError":{"type":"boolean"}},"required":["tool","input","result","isError"]}},"iterations":{"type":"integer"},"stopped":{"type":"string","enum":["completed","max_iterations"]}},"required":["finalText","steps","iterations","stopped"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"401":{"description":"Requires httpOnly session","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/v1/warehouses":{"get":{"tags":["Warehouses"],"summary":"List warehouses","parameters":[{"schema":{"type":"string","enum":["true","false"],"description":"Filter by active status"},"required":false,"description":"Filter by active status","name":"active","in":"query"}],"responses":{"200":{"description":"List of warehouses","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"wh_abc123"},"name":{"type":"string","example":"East Coast Warehouse"},"code":{"type":"string","example":"EC-01"},"address":{"type":"string","nullable":true,"example":"123 Main St"},"city":{"type":"string","nullable":true,"example":"New York"},"state":{"type":"string","nullable":true,"example":"NY"},"country":{"type":"string","example":"US"},"postalCode":{"type":"string","nullable":true,"example":"10001"},"isDefault":{"type":"integer","example":0},"isActive":{"type":"integer","example":1},"isFulfillmentCenter":{"type":"integer","example":1},"isPickupLocation":{"type":"integer","example":0},"latitude":{"type":"number","nullable":true,"example":40.7128},"longitude":{"type":"number","nullable":true,"example":-74.006},"createdAt":{"type":"integer","example":1700000000},"updatedAt":{"type":"integer","example":1700000000}},"required":["id","name","code","address","city","state","country","postalCode","isDefault","isActive","isFulfillmentCenter","isPickupLocation","latitude","longitude","createdAt","updatedAt"]}}},"required":["data"]}}}}}},"post":{"tags":["Warehouses"],"summary":"Create a warehouse","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"example":"East Coast Warehouse"},"code":{"type":"string","minLength":1,"maxLength":20,"example":"EC-01"},"address":{"type":"string","example":"123 Main St"},"city":{"type":"string","example":"New York"},"state":{"type":"string","example":"NY"},"country":{"type":"string","minLength":2,"maxLength":2,"example":"US"},"postalCode":{"type":"string","example":"10001"},"isDefault":{"type":"integer","minimum":0,"maximum":1,"default":0,"example":0},"isFulfillmentCenter":{"type":"integer","minimum":0,"maximum":1,"default":1,"example":1},"isPickupLocation":{"type":"integer","minimum":0,"maximum":1,"default":0,"example":0},"latitude":{"type":"number","example":40.7128},"longitude":{"type":"number","example":-74.006}},"required":["name","code","country"]}}}},"responses":{"201":{"description":"Warehouse created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","example":"wh_abc123"},"name":{"type":"string","example":"East Coast Warehouse"},"code":{"type":"string","example":"EC-01"},"address":{"type":"string","nullable":true,"example":"123 Main St"},"city":{"type":"string","nullable":true,"example":"New York"},"state":{"type":"string","nullable":true,"example":"NY"},"country":{"type":"string","example":"US"},"postalCode":{"type":"string","nullable":true,"example":"10001"},"isDefault":{"type":"integer","example":0},"isActive":{"type":"integer","example":1},"isFulfillmentCenter":{"type":"integer","example":1},"isPickupLocation":{"type":"integer","example":0},"latitude":{"type":"number","nullable":true,"example":40.7128},"longitude":{"type":"number","nullable":true,"example":-74.006},"createdAt":{"type":"integer","example":1700000000},"updatedAt":{"type":"integer","example":1700000000}},"required":["id","name","code","address","city","state","country","postalCode","isDefault","isActive","isFulfillmentCenter","isPickupLocation","latitude","longitude","createdAt","updatedAt"]}},"required":["data"]}}}},"409":{"description":"Code already in use"}}}},"/v1/v1/warehouses/:id":{"patch":{"tags":["Warehouses"],"summary":"Update a warehouse","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"example":"East Coast Warehouse"},"code":{"type":"string","minLength":1,"maxLength":20,"example":"EC-01"},"address":{"type":"string","example":"123 Main St"},"city":{"type":"string","example":"New York"},"state":{"type":"string","example":"NY"},"country":{"type":"string","minLength":2,"maxLength":2,"example":"US"},"postalCode":{"type":"string","example":"10001"},"isFulfillmentCenter":{"type":"integer","minimum":0,"maximum":1},"isPickupLocation":{"type":"integer","minimum":0,"maximum":1},"latitude":{"type":"number"},"longitude":{"type":"number"}}}}}},"responses":{"200":{"description":"Warehouse updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","example":"wh_abc123"},"name":{"type":"string","example":"East Coast Warehouse"},"code":{"type":"string","example":"EC-01"},"address":{"type":"string","nullable":true,"example":"123 Main St"},"city":{"type":"string","nullable":true,"example":"New York"},"state":{"type":"string","nullable":true,"example":"NY"},"country":{"type":"string","example":"US"},"postalCode":{"type":"string","nullable":true,"example":"10001"},"isDefault":{"type":"integer","example":0},"isActive":{"type":"integer","example":1},"isFulfillmentCenter":{"type":"integer","example":1},"isPickupLocation":{"type":"integer","example":0},"latitude":{"type":"number","nullable":true,"example":40.7128},"longitude":{"type":"number","nullable":true,"example":-74.006},"createdAt":{"type":"integer","example":1700000000},"updatedAt":{"type":"integer","example":1700000000}},"required":["id","name","code","address","city","state","country","postalCode","isDefault","isActive","isFulfillmentCenter","isPickupLocation","latitude","longitude","createdAt","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Warehouse not found"}}},"delete":{"tags":["Warehouses"],"summary":"Soft-delete a warehouse (sets is_active=false)","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Warehouse deactivated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Warehouse has active stock"},"404":{"description":"Warehouse not found"}}}},"/v1/v1/warehouses/:id/set-default":{"post":{"tags":["Warehouses"],"summary":"Set a warehouse as the default (atomic swap)","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Default warehouse updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","example":"wh_abc123"},"name":{"type":"string","example":"East Coast Warehouse"},"code":{"type":"string","example":"EC-01"},"address":{"type":"string","nullable":true,"example":"123 Main St"},"city":{"type":"string","nullable":true,"example":"New York"},"state":{"type":"string","nullable":true,"example":"NY"},"country":{"type":"string","example":"US"},"postalCode":{"type":"string","nullable":true,"example":"10001"},"isDefault":{"type":"integer","example":0},"isActive":{"type":"integer","example":1},"isFulfillmentCenter":{"type":"integer","example":1},"isPickupLocation":{"type":"integer","example":0},"latitude":{"type":"number","nullable":true,"example":40.7128},"longitude":{"type":"number","nullable":true,"example":-74.006},"createdAt":{"type":"integer","example":1700000000},"updatedAt":{"type":"integer","example":1700000000}},"required":["id","name","code","address","city","state","country","postalCode","isDefault","isActive","isFulfillmentCenter","isPickupLocation","latitude","longitude","createdAt","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Warehouse not found"}}}},"/v1/v1/inventory":{"get":{"tags":["Inventory"],"summary":"List stock levels across warehouses","parameters":[{"schema":{"type":"string","description":"Filter by variant"},"required":false,"description":"Filter by variant","name":"variantId","in":"query"},{"schema":{"type":"string","description":"Filter by product"},"required":false,"description":"Filter by product","name":"productId","in":"query"},{"schema":{"type":"string","description":"Filter by warehouse"},"required":false,"description":"Filter by warehouse","name":"warehouseId","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Only low stock rows"},"required":false,"description":"Only low stock rows","name":"low_stock","in":"query"}],"responses":{"200":{"description":"Inventory levels","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"warehouseId":{"type":"string"},"warehouseName":{"type":"string","nullable":true},"variantId":{"type":"string","nullable":true},"productId":{"type":"string","nullable":true},"availableQty":{"type":"integer"},"reservedQty":{"type":"integer"},"incomingQty":{"type":"integer"},"reorderPoint":{"type":"integer"},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","warehouseId","warehouseName","variantId","productId","availableQty","reservedQty","incomingQty","reorderPoint","createdAt","updatedAt"]}}},"required":["data"]}}}}}}},"/v1/v1/inventory/adjust":{"post":{"tags":["Inventory"],"summary":"Adjust stock in a warehouse (atomic + dual-write)","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"warehouseId":{"type":"string","description":"Target warehouse ID"},"variantId":{"type":"string","description":"Variant ID (mutually exclusive with productId)"},"productId":{"type":"string","description":"Product ID for simple products without variants"},"delta":{"type":"integer","description":"Positive to add stock, negative to remove","example":10},"reason":{"type":"string","minLength":1,"description":"Reason for adjustment","example":"Manual count correction"}},"required":["warehouseId","delta","reason"]}}}},"responses":{"200":{"description":"Updated stock location","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"warehouseId":{"type":"string"},"warehouseName":{"type":"string","nullable":true},"variantId":{"type":"string","nullable":true},"productId":{"type":"string","nullable":true},"availableQty":{"type":"integer"},"reservedQty":{"type":"integer"},"incomingQty":{"type":"integer"},"reorderPoint":{"type":"integer"},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","warehouseId","warehouseName","variantId","productId","availableQty","reservedQty","incomingQty","reorderPoint","createdAt","updatedAt"]}},"required":["data"]}}}},"400":{"description":"Insufficient stock or bad request"},"404":{"description":"Warehouse or product/variant not found"}}}},"/v1/v1/warehouses/:id/inventory":{"get":{"tags":["Inventory"],"summary":"Get all inventory for a specific warehouse","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Warehouse inventory","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"warehouseId":{"type":"string"},"warehouseName":{"type":"string","nullable":true},"variantId":{"type":"string","nullable":true},"productId":{"type":"string","nullable":true},"availableQty":{"type":"integer"},"reservedQty":{"type":"integer"},"incomingQty":{"type":"integer"},"reorderPoint":{"type":"integer"},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","warehouseId","warehouseName","variantId","productId","availableQty","reservedQty","incomingQty","reorderPoint","createdAt","updatedAt"]}}},"required":["data"]}}}},"404":{"description":"Warehouse not found"}}}},"/v1/v1/stock-transfers":{"get":{"tags":["Stock Transfers"],"summary":"List stock transfers","parameters":[{"schema":{"type":"string","enum":["draft","confirmed","in_transit","received","cancelled"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":100,"default":20},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"List of transfers","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"transferNumber":{"type":"string"},"fromWarehouseId":{"type":"string","nullable":true},"toWarehouseId":{"type":"string"},"status":{"type":"string","enum":["draft","confirmed","in_transit","received","cancelled"]},"notes":{"type":"string","nullable":true},"createdBy":{"type":"string","nullable":true},"shippedAt":{"type":"integer","nullable":true},"receivedAt":{"type":"integer","nullable":true},"cancelledAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"transferId":{"type":"string"},"variantId":{"type":"string","nullable":true},"productId":{"type":"string","nullable":true},"quantityRequested":{"type":"integer"},"quantityReceived":{"type":"integer"},"createdAt":{"type":"integer"}},"required":["id","transferId","variantId","productId","quantityRequested","quantityReceived","createdAt"]}}},"required":["id","transferNumber","fromWarehouseId","toWarehouseId","status","notes","createdBy","shippedAt","receivedAt","cancelledAt","createdAt","updatedAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"per_page":{"type":"number"}},"required":["page","per_page"]}},"required":["data","pagination"]}}}}}},"post":{"tags":["Stock Transfers"],"summary":"Create a draft stock transfer","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"fromWarehouseId":{"type":"string","description":"Source warehouse (null = external/supplier)"},"toWarehouseId":{"type":"string","description":"Destination warehouse"},"items":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string"},"productId":{"type":"string"},"quantity":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["quantity"]},"minItems":1,"description":"Items to transfer"},"notes":{"type":"string"}},"required":["toWarehouseId","items"]}}}},"responses":{"201":{"description":"Transfer created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"transferNumber":{"type":"string"},"fromWarehouseId":{"type":"string","nullable":true},"toWarehouseId":{"type":"string"},"status":{"type":"string","enum":["draft","confirmed","in_transit","received","cancelled"]},"notes":{"type":"string","nullable":true},"createdBy":{"type":"string","nullable":true},"shippedAt":{"type":"integer","nullable":true},"receivedAt":{"type":"integer","nullable":true},"cancelledAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"transferId":{"type":"string"},"variantId":{"type":"string","nullable":true},"productId":{"type":"string","nullable":true},"quantityRequested":{"type":"integer"},"quantityReceived":{"type":"integer"},"createdAt":{"type":"integer"}},"required":["id","transferId","variantId","productId","quantityRequested","quantityReceived","createdAt"]}}},"required":["id","transferNumber","fromWarehouseId","toWarehouseId","status","notes","createdBy","shippedAt","receivedAt","cancelledAt","createdAt","updatedAt"]}},"required":["data"]}}}},"400":{"description":"Invalid request"},"404":{"description":"Warehouse not found"}}}},"/v1/v1/stock-transfers/:id":{"get":{"tags":["Stock Transfers"],"summary":"Get a stock transfer with its items","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Transfer detail","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"transferNumber":{"type":"string"},"fromWarehouseId":{"type":"string","nullable":true},"toWarehouseId":{"type":"string"},"status":{"type":"string","enum":["draft","confirmed","in_transit","received","cancelled"]},"notes":{"type":"string","nullable":true},"createdBy":{"type":"string","nullable":true},"shippedAt":{"type":"integer","nullable":true},"receivedAt":{"type":"integer","nullable":true},"cancelledAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"transferId":{"type":"string"},"variantId":{"type":"string","nullable":true},"productId":{"type":"string","nullable":true},"quantityRequested":{"type":"integer"},"quantityReceived":{"type":"integer"},"createdAt":{"type":"integer"}},"required":["id","transferId","variantId","productId","quantityRequested","quantityReceived","createdAt"]}}},"required":["id","transferNumber","fromWarehouseId","toWarehouseId","status","notes","createdBy","shippedAt","receivedAt","cancelledAt","createdAt","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Transfer not found"}}}},"/v1/v1/stock-transfers/:id/confirm":{"post":{"tags":["Stock Transfers"],"summary":"Confirm a draft transfer (draft → confirmed)","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Transfer confirmed","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"transferNumber":{"type":"string"},"fromWarehouseId":{"type":"string","nullable":true},"toWarehouseId":{"type":"string"},"status":{"type":"string","enum":["draft","confirmed","in_transit","received","cancelled"]},"notes":{"type":"string","nullable":true},"createdBy":{"type":"string","nullable":true},"shippedAt":{"type":"integer","nullable":true},"receivedAt":{"type":"integer","nullable":true},"cancelledAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"transferId":{"type":"string"},"variantId":{"type":"string","nullable":true},"productId":{"type":"string","nullable":true},"quantityRequested":{"type":"integer"},"quantityReceived":{"type":"integer"},"createdAt":{"type":"integer"}},"required":["id","transferId","variantId","productId","quantityRequested","quantityReceived","createdAt"]}}},"required":["id","transferNumber","fromWarehouseId","toWarehouseId","status","notes","createdBy","shippedAt","receivedAt","cancelledAt","createdAt","updatedAt"]}},"required":["data"]}}}},"400":{"description":"Invalid status transition"},"404":{"description":"Transfer not found"}}}},"/v1/v1/stock-transfers/:id/ship":{"post":{"tags":["Stock Transfers"],"summary":"Mark transfer as shipped (confirmed → in_transit). Decrements from_warehouse stock.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Transfer in transit","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"transferNumber":{"type":"string"},"fromWarehouseId":{"type":"string","nullable":true},"toWarehouseId":{"type":"string"},"status":{"type":"string","enum":["draft","confirmed","in_transit","received","cancelled"]},"notes":{"type":"string","nullable":true},"createdBy":{"type":"string","nullable":true},"shippedAt":{"type":"integer","nullable":true},"receivedAt":{"type":"integer","nullable":true},"cancelledAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"transferId":{"type":"string"},"variantId":{"type":"string","nullable":true},"productId":{"type":"string","nullable":true},"quantityRequested":{"type":"integer"},"quantityReceived":{"type":"integer"},"createdAt":{"type":"integer"}},"required":["id","transferId","variantId","productId","quantityRequested","quantityReceived","createdAt"]}}},"required":["id","transferNumber","fromWarehouseId","toWarehouseId","status","notes","createdBy","shippedAt","receivedAt","cancelledAt","createdAt","updatedAt"]}},"required":["data"]}}}},"400":{"description":"Invalid status or insufficient stock"},"404":{"description":"Transfer not found"}}}},"/v1/v1/stock-transfers/:id/receive":{"post":{"tags":["Stock Transfers"],"summary":"Receive a transfer (in_transit → received). Increments to_warehouse stock.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","description":"stock_transfer_items.id"},"quantityReceived":{"type":"integer","minimum":0}},"required":["itemId","quantityReceived"]},"minItems":1}},"required":["items"]}}}},"responses":{"200":{"description":"Transfer received","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"transferNumber":{"type":"string"},"fromWarehouseId":{"type":"string","nullable":true},"toWarehouseId":{"type":"string"},"status":{"type":"string","enum":["draft","confirmed","in_transit","received","cancelled"]},"notes":{"type":"string","nullable":true},"createdBy":{"type":"string","nullable":true},"shippedAt":{"type":"integer","nullable":true},"receivedAt":{"type":"integer","nullable":true},"cancelledAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"transferId":{"type":"string"},"variantId":{"type":"string","nullable":true},"productId":{"type":"string","nullable":true},"quantityRequested":{"type":"integer"},"quantityReceived":{"type":"integer"},"createdAt":{"type":"integer"}},"required":["id","transferId","variantId","productId","quantityRequested","quantityReceived","createdAt"]}}},"required":["id","transferNumber","fromWarehouseId","toWarehouseId","status","notes","createdBy","shippedAt","receivedAt","cancelledAt","createdAt","updatedAt"]}},"required":["data"]}}}},"400":{"description":"Invalid status"},"404":{"description":"Transfer not found"}}}},"/v1/v1/stock-transfers/:id/cancel":{"post":{"tags":["Stock Transfers"],"summary":"Cancel a transfer (draft|confirmed only — not in_transit)","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Transfer cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"transferNumber":{"type":"string"},"fromWarehouseId":{"type":"string","nullable":true},"toWarehouseId":{"type":"string"},"status":{"type":"string","enum":["draft","confirmed","in_transit","received","cancelled"]},"notes":{"type":"string","nullable":true},"createdBy":{"type":"string","nullable":true},"shippedAt":{"type":"integer","nullable":true},"receivedAt":{"type":"integer","nullable":true},"cancelledAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"transferId":{"type":"string"},"variantId":{"type":"string","nullable":true},"productId":{"type":"string","nullable":true},"quantityRequested":{"type":"integer"},"quantityReceived":{"type":"integer"},"createdAt":{"type":"integer"}},"required":["id","transferId","variantId","productId","quantityRequested","quantityReceived","createdAt"]}}},"required":["id","transferNumber","fromWarehouseId","toWarehouseId","status","notes","createdBy","shippedAt","receivedAt","cancelledAt","createdAt","updatedAt"]}},"required":["data"]}}}},"400":{"description":"Invalid status — cannot cancel in_transit transfer"},"404":{"description":"Transfer not found"}}}},"/v1/v1/routing-rules":{"get":{"tags":["Fulfillment"],"summary":"List routing rules","responses":{"200":{"description":"List of routing rules ordered by priority","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"strategy":{"type":"string","enum":["default","nearest","highest_stock","lowest_cost","round_robin","manual"]},"priority":{"type":"number"},"isActive":{"type":"boolean"},"conditions":{"nullable":true},"warehouseIds":{"type":"array","nullable":true,"items":{"type":"string"}},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","name","strategy","priority","isActive","warehouseIds","createdAt","updatedAt"]}}},"required":["data"]}}}}}},"post":{"tags":["Fulfillment"],"summary":"Create a routing rule","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"example":"Default EU rule"},"strategy":{"type":"string","enum":["default","nearest","highest_stock","lowest_cost","round_robin","manual"],"example":"highest_stock"},"priority":{"type":"integer","default":0,"example":10},"isActive":{"type":"boolean","default":true},"conditions":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"warehouseIds":{"type":"array","nullable":true,"items":{"type":"string"}}},"required":["name","strategy"]}}}},"responses":{"201":{"description":"Routing rule created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"strategy":{"type":"string","enum":["default","nearest","highest_stock","lowest_cost","round_robin","manual"]},"priority":{"type":"number"},"isActive":{"type":"boolean"},"conditions":{"nullable":true},"warehouseIds":{"type":"array","nullable":true,"items":{"type":"string"}},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","name","strategy","priority","isActive","warehouseIds","createdAt","updatedAt"]}},"required":["data"]}}}}}}},"/v1/v1/routing-rules/:id":{"patch":{"tags":["Fulfillment"],"summary":"Update a routing rule","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"example":"Default EU rule"},"strategy":{"type":"string","enum":["default","nearest","highest_stock","lowest_cost","round_robin","manual"],"example":"highest_stock"},"priority":{"type":"integer","default":0,"example":10},"isActive":{"type":"boolean","default":true},"conditions":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"warehouseIds":{"type":"array","nullable":true,"items":{"type":"string"}}}}}}},"responses":{"200":{"description":"Routing rule updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"strategy":{"type":"string","enum":["default","nearest","highest_stock","lowest_cost","round_robin","manual"]},"priority":{"type":"number"},"isActive":{"type":"boolean"},"conditions":{"nullable":true},"warehouseIds":{"type":"array","nullable":true,"items":{"type":"string"}},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","name","strategy","priority","isActive","warehouseIds","createdAt","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Not found"}}},"delete":{"tags":["Fulfillment"],"summary":"Delete a routing rule","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Not found"}}}},"/v1/v1/routing-rules/reorder":{"post":{"tags":["Fulfillment"],"summary":"Bulk update routing rule priorities","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"rules":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"priority":{"type":"integer"}},"required":["id","priority"]},"minItems":1}},"required":["rules"]}}}},"responses":{"200":{"description":"Priorities updated","content":{"application/json":{"schema":{"type":"object","properties":{"updated":{"type":"number"}},"required":["updated"]}}}}}}},"/v1/v1/orders/:id/route":{"post":{"tags":["Fulfillment"],"summary":"Apply fulfillment routing to an order","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Routing applied","content":{"application/json":{"schema":{"type":"object","properties":{"fulfillments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentNumber":{"type":"string"},"warehouseId":{"type":"string"},"strategy":{"type":"string"},"itemCount":{"type":"number"}},"required":["id","fulfillmentNumber","warehouseId","strategy","itemCount"]}},"unfulfilled":{"type":"array","items":{"type":"object","properties":{"orderItemId":{"type":"string"},"requestedQty":{"type":"number"},"availableQty":{"type":"number"},"reason":{"type":"string"}},"required":["orderItemId","requestedQty","availableQty","reason"]}},"warning":{"type":"string"}},"required":["fulfillments","unfulfilled"]}}}},"404":{"description":"Order not found"}}}},"/v1/v1/orders/:id/fulfillments":{"get":{"tags":["Fulfillment"],"summary":"List fulfillments for an order","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Fulfillments list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentNumber":{"type":"string"},"orderId":{"type":"string"},"warehouseId":{"type":"string"},"shipmentId":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","picking","packed","shipped","delivered","cancelled","returned"]},"routingStrategy":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"packedAt":{"type":"number","nullable":true},"shippedAt":{"type":"number","nullable":true},"deliveredAt":{"type":"number","nullable":true},"cancelledAt":{"type":"number","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentId":{"type":"string"},"orderItemId":{"type":"string"},"quantity":{"type":"number"},"pickedQuantity":{"type":"number"},"createdAt":{"type":"number"}},"required":["id","fulfillmentId","orderItemId","quantity","pickedQuantity","createdAt"]}},"history":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentId":{"type":"string"},"fromStatus":{"type":"string","nullable":true},"toStatus":{"type":"string"},"changedBy":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"createdAt":{"type":"number"}},"required":["id","fulfillmentId","fromStatus","toStatus","changedBy","note","createdAt"]}}},"required":["id","fulfillmentNumber","orderId","warehouseId","shipmentId","status","routingStrategy","notes","packedAt","shippedAt","deliveredAt","cancelledAt","createdAt","updatedAt"]}}},"required":["data"]}}}},"404":{"description":"Order not found"}}},"post":{"tags":["Fulfillment"],"summary":"Manually create a fulfillment for an order","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"warehouseId":{"type":"string"},"items":{"type":"array","items":{"type":"object","properties":{"orderItemId":{"type":"string"},"quantity":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["orderItemId","quantity"]},"minItems":1},"notes":{"type":"string"}},"required":["warehouseId","items"]}}}},"responses":{"201":{"description":"Fulfillment created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentNumber":{"type":"string"},"orderId":{"type":"string"},"warehouseId":{"type":"string"},"shipmentId":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","picking","packed","shipped","delivered","cancelled","returned"]},"routingStrategy":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"packedAt":{"type":"number","nullable":true},"shippedAt":{"type":"number","nullable":true},"deliveredAt":{"type":"number","nullable":true},"cancelledAt":{"type":"number","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentId":{"type":"string"},"orderItemId":{"type":"string"},"quantity":{"type":"number"},"pickedQuantity":{"type":"number"},"createdAt":{"type":"number"}},"required":["id","fulfillmentId","orderItemId","quantity","pickedQuantity","createdAt"]}},"history":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentId":{"type":"string"},"fromStatus":{"type":"string","nullable":true},"toStatus":{"type":"string"},"changedBy":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"createdAt":{"type":"number"}},"required":["id","fulfillmentId","fromStatus","toStatus","changedBy","note","createdAt"]}}},"required":["id","fulfillmentNumber","orderId","warehouseId","shipmentId","status","routingStrategy","notes","packedAt","shippedAt","deliveredAt","cancelledAt","createdAt","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Order not found"}}}},"/v1/v1/fulfillments/:id":{"get":{"tags":["Fulfillment"],"summary":"Get fulfillment detail","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Fulfillment detail","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentNumber":{"type":"string"},"orderId":{"type":"string"},"warehouseId":{"type":"string"},"shipmentId":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","picking","packed","shipped","delivered","cancelled","returned"]},"routingStrategy":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"packedAt":{"type":"number","nullable":true},"shippedAt":{"type":"number","nullable":true},"deliveredAt":{"type":"number","nullable":true},"cancelledAt":{"type":"number","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentId":{"type":"string"},"orderItemId":{"type":"string"},"quantity":{"type":"number"},"pickedQuantity":{"type":"number"},"createdAt":{"type":"number"}},"required":["id","fulfillmentId","orderItemId","quantity","pickedQuantity","createdAt"]}},"history":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentId":{"type":"string"},"fromStatus":{"type":"string","nullable":true},"toStatus":{"type":"string"},"changedBy":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"createdAt":{"type":"number"}},"required":["id","fulfillmentId","fromStatus","toStatus","changedBy","note","createdAt"]}}},"required":["id","fulfillmentNumber","orderId","warehouseId","shipmentId","status","routingStrategy","notes","packedAt","shippedAt","deliveredAt","cancelledAt","createdAt","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Not found"}}},"patch":{"tags":["Fulfillment"],"summary":"Update fulfillment status or pick quantities","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","picking","packed","shipped","delivered","cancelled","returned"]},"notes":{"type":"string"},"pickedQuantityUpdates":{"type":"array","items":{"type":"object","properties":{"orderItemId":{"type":"string"},"pickedQuantity":{"type":"integer","minimum":0}},"required":["orderItemId","pickedQuantity"]}}}}}}},"responses":{"200":{"description":"Fulfillment updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentNumber":{"type":"string"},"orderId":{"type":"string"},"warehouseId":{"type":"string"},"shipmentId":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","picking","packed","shipped","delivered","cancelled","returned"]},"routingStrategy":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"packedAt":{"type":"number","nullable":true},"shippedAt":{"type":"number","nullable":true},"deliveredAt":{"type":"number","nullable":true},"cancelledAt":{"type":"number","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentId":{"type":"string"},"orderItemId":{"type":"string"},"quantity":{"type":"number"},"pickedQuantity":{"type":"number"},"createdAt":{"type":"number"}},"required":["id","fulfillmentId","orderItemId","quantity","pickedQuantity","createdAt"]}},"history":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentId":{"type":"string"},"fromStatus":{"type":"string","nullable":true},"toStatus":{"type":"string"},"changedBy":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"createdAt":{"type":"number"}},"required":["id","fulfillmentId","fromStatus","toStatus","changedBy","note","createdAt"]}}},"required":["id","fulfillmentNumber","orderId","warehouseId","shipmentId","status","routingStrategy","notes","packedAt","shippedAt","deliveredAt","cancelledAt","createdAt","updatedAt"]}},"required":["data"]}}}},"400":{"description":"Invalid transition"},"404":{"description":"Not found"}}}},"/v1/v1/fulfillments/:id/cancel":{"post":{"tags":["Fulfillment"],"summary":"Cancel a fulfillment and restock items","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Fulfillment cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentNumber":{"type":"string"},"orderId":{"type":"string"},"warehouseId":{"type":"string"},"shipmentId":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","picking","packed","shipped","delivered","cancelled","returned"]},"routingStrategy":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"packedAt":{"type":"number","nullable":true},"shippedAt":{"type":"number","nullable":true},"deliveredAt":{"type":"number","nullable":true},"cancelledAt":{"type":"number","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentId":{"type":"string"},"orderItemId":{"type":"string"},"quantity":{"type":"number"},"pickedQuantity":{"type":"number"},"createdAt":{"type":"number"}},"required":["id","fulfillmentId","orderItemId","quantity","pickedQuantity","createdAt"]}},"history":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"fulfillmentId":{"type":"string"},"fromStatus":{"type":"string","nullable":true},"toStatus":{"type":"string"},"changedBy":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"createdAt":{"type":"number"}},"required":["id","fulfillmentId","fromStatus","toStatus","changedBy","note","createdAt"]}}},"required":["id","fulfillmentNumber","orderId","warehouseId","shipmentId","status","routingStrategy","notes","packedAt","shippedAt","deliveredAt","cancelledAt","createdAt","updatedAt"]}},"required":["data"]}}}},"400":{"description":"Cannot cancel in current status"},"404":{"description":"Not found"}}}},"/v1/loyalty/program":{"get":{"tags":["Loyalty"],"summary":"Get tenant loyalty program config","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Loyalty program","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/LoyaltyProgram"}},"required":["data"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}}}},"put":{"tags":["Loyalty"],"summary":"Create or update loyalty program","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertLoyaltyProgram"}}}},"responses":{"200":{"description":"Upserted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProgram"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}}}}},"/v1/loyalty/tiers":{"get":{"tags":["Loyalty"],"summary":"List loyalty tiers","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Tiers","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LoyaltyTier"}}},"required":["data"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}}}},"post":{"tags":["Loyalty"],"summary":"Create a loyalty tier","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLoyaltyTier"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyTier"}}}},"404":{"description":"Program not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}}}}},"/v1/loyalty/tiers/{id}":{"patch":{"tags":["Loyalty"],"summary":"Update a loyalty tier","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLoyaltyTier"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyTier"}}}},"404":{"description":"Tier not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}}}},"delete":{"tags":["Loyalty"],"summary":"Delete a loyalty tier","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Tier not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}}}}},"/v1/customers/{id}/loyalty":{"get":{"tags":["Loyalty","Customers"],"summary":"Get customer loyalty balance and transactions","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Customer loyalty data","content":{"application/json":{"schema":{"type":"object","properties":{"loyalty":{"$ref":"#/components/schemas/CustomerLoyalty"},"transactions":{"type":"array","items":{"$ref":"#/components/schemas/LoyaltyTransaction"}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"}},"required":["page","limit","total","totalPages"]}},"required":["loyalty","transactions","pagination"]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}}}}},"/v1/loyalty/adjust":{"post":{"tags":["Loyalty"],"summary":"Manually adjust customer loyalty points","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyManualAdjust"}}}},"responses":{"200":{"description":"Points adjusted","content":{"application/json":{"schema":{"type":"object","properties":{"customerId":{"type":"string"},"newBalance":{"type":"integer"},"transaction":{"$ref":"#/components/schemas/LoyaltyTransaction"}},"required":["customerId","newBalance","transaction"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}}}}},"/v1/loyalty/transactions":{"get":{"tags":["Loyalty"],"summary":"List loyalty transactions","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"customerId","in":"query"},{"schema":{"type":"string","enum":["earned","redeemed","adjusted","expired","bonus"]},"required":false,"name":"type","in":"query"},{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Transactions","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LoyaltyTransaction"}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}}}}},"/v1/loyalty/stats":{"get":{"tags":["Loyalty"],"summary":"Loyalty program statistics","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Stats","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyStats"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoyaltyProblem"}}}}}}},"/v1/feature-flags":{"get":{"tags":["Feature Flags"],"summary":"List all feature flags","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Feature flags list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"enabledGlobally":{"type":"integer"},"rolloutPercentage":{"type":"integer"},"targetUserIds":{"type":"string","nullable":true},"targetSegmentIds":{"type":"string","nullable":true},"startsAt":{"type":"integer","nullable":true},"endsAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","key","name","enabledGlobally","rolloutPercentage","createdAt","updatedAt"]}}},"required":["data"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Feature Flags"],"summary":"Create a feature flag","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[a-z0-9_-]+$","example":"new_checkout_flow"},"name":{"type":"string","minLength":1,"maxLength":200,"example":"New Checkout Flow"},"description":{"type":"string"},"enabledGlobally":{"type":"integer","minimum":0,"maximum":1,"default":0},"rolloutPercentage":{"type":"integer","minimum":0,"maximum":100,"default":0},"targetUserIds":{"type":"array","items":{"type":"string"}},"targetSegmentIds":{"type":"array","items":{"type":"string"}},"startsAt":{"type":"integer"},"endsAt":{"type":"integer"}},"required":["key","name"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"enabledGlobally":{"type":"integer"},"rolloutPercentage":{"type":"integer"},"targetUserIds":{"type":"string","nullable":true},"targetSegmentIds":{"type":"string","nullable":true},"startsAt":{"type":"integer","nullable":true},"endsAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","key","name","enabledGlobally","rolloutPercentage","createdAt","updatedAt"]}},"required":["data"]}}}},"409":{"description":"Key already exists","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/feature-flags/evaluate":{"get":{"tags":["Feature Flags"],"summary":"Evaluate multiple feature flags for a subject","description":"Returns a map of flag key → boolean for each requested key. Applies 6-rule evaluation pipeline with KV cache (TTL 60s).","parameters":[{"schema":{"type":"string","minLength":1,"example":"cust_abc123"},"required":true,"name":"subject_id","in":"query"},{"schema":{"type":"string","enum":["customer","user","session"],"default":"customer"},"required":false,"name":"subject_type","in":"query"},{"schema":{"type":"string","minLength":1,"example":"flag_a,flag_b,flag_c"},"required":true,"name":"keys","in":"query"}],"responses":{"200":{"description":"Evaluation results","content":{"application/json":{"schema":{"type":"object","properties":{"flags":{"type":"object","additionalProperties":{"type":"boolean"}}},"required":["flags"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/feature-flags/{id}":{"get":{"tags":["Feature Flags"],"summary":"Get a feature flag by ID","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Feature flag","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"enabledGlobally":{"type":"integer"},"rolloutPercentage":{"type":"integer"},"targetUserIds":{"type":"string","nullable":true},"targetSegmentIds":{"type":"string","nullable":true},"startsAt":{"type":"integer","nullable":true},"endsAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","key","name","enabledGlobally","rolloutPercentage","createdAt","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Feature Flags"],"summary":"Update a feature flag","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200,"example":"New Checkout Flow"},"description":{"type":"string"},"enabledGlobally":{"type":"integer","minimum":0,"maximum":1,"default":0},"rolloutPercentage":{"type":"integer","minimum":0,"maximum":100,"default":0},"targetUserIds":{"type":"array","items":{"type":"string"}},"targetSegmentIds":{"type":"array","items":{"type":"string"}},"startsAt":{"type":"integer"},"endsAt":{"type":"integer"}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"enabledGlobally":{"type":"integer"},"rolloutPercentage":{"type":"integer"},"targetUserIds":{"type":"string","nullable":true},"targetSegmentIds":{"type":"string","nullable":true},"startsAt":{"type":"integer","nullable":true},"endsAt":{"type":"integer","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","key","name","enabledGlobally","rolloutPercentage","createdAt","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Feature Flags"],"summary":"Delete a feature flag","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/experiments":{"get":{"tags":["Experiments"],"summary":"List experiments","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["draft","running","paused","completed","archived"]},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"Experiments list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","running","paused","completed","archived"]},"variants":{"type":"string"},"trafficAllocation":{"type":"integer"},"primaryMetric":{"type":"string","nullable":true},"startedAt":{"type":"integer","nullable":true},"endedAt":{"type":"integer","nullable":true},"winnerVariant":{"type":"string","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","key","name","status","variants","trafficAllocation","createdAt","updatedAt"]}}},"required":["data"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Experiments"],"summary":"Create a new experiment","description":"Variants must sum to 100% weight.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[a-z0-9_-]+$","example":"checkout_button_color"},"name":{"type":"string","minLength":1,"maxLength":200,"example":"Checkout Button Color Test"},"description":{"type":"string"},"variants":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1},"name":{"type":"string","minLength":1},"weight":{"type":"integer","minimum":0,"maximum":100}},"required":["key","name","weight"]},"minItems":2,"example":[{"key":"control","name":"Control","weight":50},{"key":"treatment","name":"Treatment","weight":50}]},"trafficAllocation":{"type":"integer","minimum":1,"maximum":100,"default":100},"primaryMetric":{"type":"string"}},"required":["key","name","variants"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","running","paused","completed","archived"]},"variants":{"type":"string"},"trafficAllocation":{"type":"integer"},"primaryMetric":{"type":"string","nullable":true},"startedAt":{"type":"integer","nullable":true},"endedAt":{"type":"integer","nullable":true},"winnerVariant":{"type":"string","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","key","name","status","variants","trafficAllocation","createdAt","updatedAt"]}},"required":["data"]}}}},"409":{"description":"Key already exists","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/experiments/{id}":{"patch":{"tags":["Experiments"],"summary":"Update an experiment","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string"},"status":{"type":"string","enum":["draft","running","paused","completed","archived"]},"trafficAllocation":{"type":"integer","minimum":1,"maximum":100},"primaryMetric":{"type":"string"},"winnerVariant":{"type":"string"}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","running","paused","completed","archived"]},"variants":{"type":"string"},"trafficAllocation":{"type":"integer"},"primaryMetric":{"type":"string","nullable":true},"startedAt":{"type":"integer","nullable":true},"endedAt":{"type":"integer","nullable":true},"winnerVariant":{"type":"string","nullable":true},"createdAt":{"type":"integer"},"updatedAt":{"type":"integer"}},"required":["id","key","name","status","variants","trafficAllocation","createdAt","updatedAt"]}},"required":["data"]}}}},"400":{"description":"Invalid status transition","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/experiments/{id}/assign":{"post":{"tags":["Experiments"],"summary":"Assign a subject to a variant (idempotent)","description":"Returns the same variant for the same subject. Traffic allocation exclusion supported.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"subjectId":{"type":"string","minLength":1,"example":"cust_abc123"},"subjectType":{"type":"string","enum":["customer","user","session"],"default":"customer"}},"required":["subjectId"]}}}},"responses":{"200":{"description":"Assignment result (null variant = excluded by traffic allocation)","content":{"application/json":{"schema":{"type":"object","properties":{"variant":{"type":"string","nullable":true},"subjectId":{"type":"string"},"experimentId":{"type":"string"},"isNew":{"type":"boolean"}},"required":["variant","subjectId","experimentId","isNew"]}}}},"400":{"description":"Experiment not running","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Experiment not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/experiments/{id}/track":{"post":{"tags":["Experiments"],"summary":"Track an experiment event","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"subjectId":{"type":"string","minLength":1},"eventType":{"type":"string","minLength":1,"example":"conversion"},"value":{"type":"integer"}},"required":["subjectId","eventType"]}}}},"responses":{"201":{"description":"Event tracked","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}},"400":{"description":"No assignment found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Experiment not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/experiments/{id}/results":{"get":{"tags":["Experiments"],"summary":"Get experiment results with statistical analysis","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Experiment results","content":{"application/json":{"schema":{"type":"object","properties":{"variants":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"},"assignments":{"type":"integer"},"conversions":{"type":"integer"},"conversionRate":{"type":"number"},"revenueCents":{"type":"integer"},"lift":{"type":"number","nullable":true},"pValue":{"type":"number","nullable":true}},"required":["key","name","assignments","conversions","conversionRate","revenueCents"]}},"winner":{"type":"string","nullable":true},"confidence":{"type":"number"},"samplesPerVariantRequired":{"type":"integer"},"readyToDeclareWinner":{"type":"boolean"}},"required":["variants","winner","confidence","samplesPerVariantRequired","readyToDeclareWinner"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/experiments/{id}/sequential":{"get":{"tags":["Experiments"],"summary":"Anytime-valid (sequential / mSPRT) experiment results","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"},{"schema":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":1,"exclusiveMaximum":true},"required":false,"name":"alpha","in":"query"},{"schema":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":1,"exclusiveMaximum":true},"required":false,"name":"tau","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequentialResults"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/automations":{"get":{"tags":["Automation"],"summary":"List automation rules","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["order.created","order.updated","order.fulfilled","order.cancelled","order.refunded","payment.succeeded","payment.failed","customer.created","review.created","cart.abandoned","inventory.low"]},"required":false,"name":"trigger","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"enabled","in":"query"}],"responses":{"200":{"description":"Automation rules list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"trigger":{"type":"string"},"conditions":{"type":"object","properties":{"logic":{"type":"string","enum":["AND","OR"],"default":"AND"},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","minLength":1},"operator":{"type":"string","enum":["eq","neq","gt","gte","lt","lte","contains","not_contains","in","not_in"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]}}]}},"required":["field","operator","value"]},"maxItems":20,"default":[]}}},"actions":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["add_note"]},"params":{"type":"object","properties":{"content":{"type":"string","minLength":1,"maxLength":2000}},"required":["content"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["fire_webhook"]},"params":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["send_email"]},"params":{"type":"object","properties":{"to":{"type":"string","format":"email"},"subject":{"type":"string","minLength":1,"maxLength":300},"body":{"type":"string","minLength":1,"maxLength":20000}},"required":["subject","body"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["update_order_status"]},"params":{"type":"object","properties":{"status":{"type":"string","enum":["pending","pending_approval","pending_payment","confirmed","processing","shipped","delivered","cancelled","refunded"]}},"required":["status"]}},"required":["type","params"]}]}},"enabled":{"type":"boolean"},"runCount":{"type":"number"},"lastRunAt":{"type":"number","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","name","description","trigger","conditions","actions","enabled","runCount","lastRunAt","createdAt","updatedAt"]}}},"required":["data"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Automation"],"summary":"Create an automation rule","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":500},"trigger":{"type":"string","enum":["order.created","order.updated","order.fulfilled","order.cancelled","order.refunded","payment.succeeded","payment.failed","customer.created","review.created","cart.abandoned","inventory.low"]},"conditions":{"type":"object","properties":{"logic":{"type":"string","enum":["AND","OR"],"default":"AND"},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","minLength":1},"operator":{"type":"string","enum":["eq","neq","gt","gte","lt","lte","contains","not_contains","in","not_in"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]}}]}},"required":["field","operator","value"]},"maxItems":20,"default":[]}},"default":{"logic":"AND","conditions":[]}},"actions":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["add_note"]},"params":{"type":"object","properties":{"content":{"type":"string","minLength":1,"maxLength":2000}},"required":["content"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["fire_webhook"]},"params":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["send_email"]},"params":{"type":"object","properties":{"to":{"type":"string","format":"email"},"subject":{"type":"string","minLength":1,"maxLength":300},"body":{"type":"string","minLength":1,"maxLength":20000}},"required":["subject","body"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["update_order_status"]},"params":{"type":"object","properties":{"status":{"type":"string","enum":["pending","pending_approval","pending_payment","confirmed","processing","shipped","delivered","cancelled","refunded"]}},"required":["status"]}},"required":["type","params"]}]},"minItems":1,"maxItems":10},"enabled":{"type":"boolean","default":true}},"required":["name","trigger","actions"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"trigger":{"type":"string"},"conditions":{"type":"object","properties":{"logic":{"type":"string","enum":["AND","OR"],"default":"AND"},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","minLength":1},"operator":{"type":"string","enum":["eq","neq","gt","gte","lt","lte","contains","not_contains","in","not_in"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]}}]}},"required":["field","operator","value"]},"maxItems":20,"default":[]}}},"actions":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["add_note"]},"params":{"type":"object","properties":{"content":{"type":"string","minLength":1,"maxLength":2000}},"required":["content"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["fire_webhook"]},"params":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["send_email"]},"params":{"type":"object","properties":{"to":{"type":"string","format":"email"},"subject":{"type":"string","minLength":1,"maxLength":300},"body":{"type":"string","minLength":1,"maxLength":20000}},"required":["subject","body"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["update_order_status"]},"params":{"type":"object","properties":{"status":{"type":"string","enum":["pending","pending_approval","pending_payment","confirmed","processing","shipped","delivered","cancelled","refunded"]}},"required":["status"]}},"required":["type","params"]}]}},"enabled":{"type":"boolean"},"runCount":{"type":"number"},"lastRunAt":{"type":"number","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","name","description","trigger","conditions","actions","enabled","runCount","lastRunAt","createdAt","updatedAt"]}},"required":["data"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/automations/meta":{"get":{"tags":["Automation"],"summary":"Automation builder catalog (triggers, actions, operators)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Static catalog for the admin automation builder UI","content":{"application/json":{"schema":{"type":"object","properties":{"triggers":{"type":"array","items":{"type":"string"}},"actions":{"type":"array","items":{"type":"string"}},"operators":{"type":"array","items":{"type":"string"}}},"required":["triggers","actions","operators"]}}}}}}},"/v1/automations/{id}":{"get":{"tags":["Automation"],"summary":"Get an automation rule by ID","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Automation rule","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"trigger":{"type":"string"},"conditions":{"type":"object","properties":{"logic":{"type":"string","enum":["AND","OR"],"default":"AND"},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","minLength":1},"operator":{"type":"string","enum":["eq","neq","gt","gte","lt","lte","contains","not_contains","in","not_in"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]}}]}},"required":["field","operator","value"]},"maxItems":20,"default":[]}}},"actions":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["add_note"]},"params":{"type":"object","properties":{"content":{"type":"string","minLength":1,"maxLength":2000}},"required":["content"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["fire_webhook"]},"params":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["send_email"]},"params":{"type":"object","properties":{"to":{"type":"string","format":"email"},"subject":{"type":"string","minLength":1,"maxLength":300},"body":{"type":"string","minLength":1,"maxLength":20000}},"required":["subject","body"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["update_order_status"]},"params":{"type":"object","properties":{"status":{"type":"string","enum":["pending","pending_approval","pending_payment","confirmed","processing","shipped","delivered","cancelled","refunded"]}},"required":["status"]}},"required":["type","params"]}]}},"enabled":{"type":"boolean"},"runCount":{"type":"number"},"lastRunAt":{"type":"number","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","name","description","trigger","conditions","actions","enabled","runCount","lastRunAt","createdAt","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Automation"],"summary":"Update an automation rule","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":500},"trigger":{"type":"string","enum":["order.created","order.updated","order.fulfilled","order.cancelled","order.refunded","payment.succeeded","payment.failed","customer.created","review.created","cart.abandoned","inventory.low"]},"conditions":{"type":"object","properties":{"logic":{"type":"string","enum":["AND","OR"],"default":"AND"},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","minLength":1},"operator":{"type":"string","enum":["eq","neq","gt","gte","lt","lte","contains","not_contains","in","not_in"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]}}]}},"required":["field","operator","value"]},"maxItems":20,"default":[]}},"default":{"logic":"AND","conditions":[]}},"actions":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["add_note"]},"params":{"type":"object","properties":{"content":{"type":"string","minLength":1,"maxLength":2000}},"required":["content"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["fire_webhook"]},"params":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["send_email"]},"params":{"type":"object","properties":{"to":{"type":"string","format":"email"},"subject":{"type":"string","minLength":1,"maxLength":300},"body":{"type":"string","minLength":1,"maxLength":20000}},"required":["subject","body"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["update_order_status"]},"params":{"type":"object","properties":{"status":{"type":"string","enum":["pending","pending_approval","pending_payment","confirmed","processing","shipped","delivered","cancelled","refunded"]}},"required":["status"]}},"required":["type","params"]}]},"minItems":1,"maxItems":10},"enabled":{"type":"boolean","default":true}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"trigger":{"type":"string"},"conditions":{"type":"object","properties":{"logic":{"type":"string","enum":["AND","OR"],"default":"AND"},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","minLength":1},"operator":{"type":"string","enum":["eq","neq","gt","gte","lt","lte","contains","not_contains","in","not_in"]},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]}}]}},"required":["field","operator","value"]},"maxItems":20,"default":[]}}},"actions":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["add_note"]},"params":{"type":"object","properties":{"content":{"type":"string","minLength":1,"maxLength":2000}},"required":["content"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["fire_webhook"]},"params":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["send_email"]},"params":{"type":"object","properties":{"to":{"type":"string","format":"email"},"subject":{"type":"string","minLength":1,"maxLength":300},"body":{"type":"string","minLength":1,"maxLength":20000}},"required":["subject","body"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["update_order_status"]},"params":{"type":"object","properties":{"status":{"type":"string","enum":["pending","pending_approval","pending_payment","confirmed","processing","shipped","delivered","cancelled","refunded"]}},"required":["status"]}},"required":["type","params"]}]}},"enabled":{"type":"boolean"},"runCount":{"type":"number"},"lastRunAt":{"type":"number","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","name","description","trigger","conditions","actions","enabled","runCount","lastRunAt","createdAt","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Automation"],"summary":"Delete an automation rule","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/automations/{id}/test":{"post":{"tags":["Automation"],"summary":"Dry-run an automation rule against a sample payload (no actions executed)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"payload":{"type":"object","additionalProperties":{"nullable":true},"default":{}}}}}}},"responses":{"200":{"description":"Dry-run result — actions are NOT executed","content":{"application/json":{"schema":{"type":"object","properties":{"matched":{"type":"boolean"},"wouldRunActions":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["add_note"]},"params":{"type":"object","properties":{"content":{"type":"string","minLength":1,"maxLength":2000}},"required":["content"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["fire_webhook"]},"params":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["send_email"]},"params":{"type":"object","properties":{"to":{"type":"string","format":"email"},"subject":{"type":"string","minLength":1,"maxLength":300},"body":{"type":"string","minLength":1,"maxLength":20000}},"required":["subject","body"]}},"required":["type","params"]},{"type":"object","properties":{"type":{"type":"string","enum":["update_order_status"]},"params":{"type":"object","properties":{"status":{"type":"string","enum":["pending","pending_approval","pending_payment","confirmed","processing","shipped","delivered","cancelled","refunded"]}},"required":["status"]}},"required":["type","params"]}]}}},"required":["matched","wouldRunActions"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/automations/{id}/runs":{"get":{"tags":["Automation"],"summary":"List automation runs for a rule (newest first)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","default":"1"},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","default":"20"},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Automation runs list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"ruleId":{"type":"string"},"trigger":{"type":"string"},"status":{"type":"string","enum":["matched","skipped","failed"]},"actionsRun":{"type":"array","nullable":true,"items":{"nullable":true}},"error":{"type":"string","nullable":true},"createdAt":{"type":"integer"}},"required":["id","ruleId","trigger","status","actionsRun","error","createdAt"]}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"perPage":{"type":"integer"},"total":{"type":"integer"}},"required":["page","perPage","total"]}},"required":["data","pagination"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/metafield-definitions":{"get":{"tags":["Metafield Definitions"],"summary":"List metafield definitions","description":"Lists typed metafield definitions, ordered by owner_type, namespace, position. RBAC: metafields.manage.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["product","customer"],"description":"Filter to a single owner type","example":"product"},"required":false,"description":"Filter to a single owner type","name":"owner_type","in":"query"}],"responses":{"200":{"description":"Definitions","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MetafieldDefinition"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Metafield Definitions"],"summary":"Create a metafield definition","description":"Creates a typed metafield definition. 409 if a definition for (owner_type, namespace, key) already exists. RBAC: metafields.manage.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"owner_type":{"type":"string","enum":["product","customer"],"example":"product"},"namespace":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9_.-]+$","example":"specs"},"key":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9_.-]+$","example":"material"},"name":{"type":"string","minLength":1,"maxLength":120,"example":"Material"},"type":{"type":"string","enum":["string","integer","number","boolean","json","date","url","color","money","rich_text"],"default":"string"},"description":{"type":"string","nullable":true,"maxLength":500},"validations":{"$ref":"#/components/schemas/MetafieldValidations"},"position":{"type":"integer","minimum":0,"default":0}},"required":["owner_type","namespace","key","name"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MetafieldDefinition"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"409":{"description":"Duplicate","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/metafield-definitions/{id}":{"get":{"tags":["Metafield Definitions"],"summary":"Get a metafield definition by ID","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Definition","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MetafieldDefinition"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Metafield Definitions"],"summary":"Update a metafield definition","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"type":{"type":"string","enum":["string","integer","number","boolean","json","date","url","color","money","rich_text"]},"description":{"type":"string","nullable":true,"maxLength":500},"validations":{"$ref":"#/components/schemas/MetafieldValidations"},"position":{"type":"integer","minimum":0}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MetafieldDefinition"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Metafield Definitions"],"summary":"Delete a metafield definition","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/search/synonyms":{"get":{"tags":["Search Merchandising"],"summary":"List search synonym groups","description":"Lists synonym groups used to expand live-search queries. RBAC: search.manage.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Synonyms","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SearchSynonym"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Search Merchandising"],"summary":"Create a synonym group","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"terms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64},"minItems":2,"maxItems":50,"example":["sneakers","trainers","kicks"]},"type":{"type":"string","enum":["oneway","twoway"],"default":"twoway"}},"required":["terms"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SearchSynonym"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/search/synonyms/{id}":{"get":{"tags":["Search Merchandising"],"summary":"Get a synonym group by ID","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Synonym","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SearchSynonym"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Search Merchandising"],"summary":"Update a synonym group","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"terms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64},"minItems":2,"maxItems":50},"type":{"type":"string","enum":["oneway","twoway"]}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SearchSynonym"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Search Merchandising"],"summary":"Delete a synonym group","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/search/boost-rules":{"get":{"tags":["Search Merchandising"],"summary":"List boost/bury rules","description":"Lists boost/bury rules ordered by position. RBAC: search.manage.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Boost rules","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SearchBoostRule"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"post":{"tags":["Search Merchandising"],"summary":"Create a boost/bury rule","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query_match":{"type":"string","nullable":true,"minLength":1,"maxLength":200,"example":"shoes"},"product_match":{"type":"array","nullable":true,"items":{"type":"string","minLength":1},"minItems":1,"maxItems":500},"action":{"type":"string","enum":["boost","bury"],"default":"boost"},"weight":{"type":"integer","minimum":0,"maximum":1000000,"default":100},"position":{"type":"integer","minimum":0,"default":0},"is_active":{"type":"boolean","default":true}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SearchBoostRule"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/search/boost-rules/{id}":{"get":{"tags":["Search Merchandising"],"summary":"Get a boost/bury rule by ID","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Boost rule","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SearchBoostRule"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Search Merchandising"],"summary":"Update a boost/bury rule","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query_match":{"type":"string","nullable":true,"minLength":1,"maxLength":200},"product_match":{"type":"array","nullable":true,"items":{"type":"string","minLength":1},"minItems":1,"maxItems":500},"action":{"type":"string","enum":["boost","bury"]},"weight":{"type":"integer","minimum":0,"maximum":1000000},"position":{"type":"integer","minimum":0},"is_active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SearchBoostRule"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Search Merchandising"],"summary":"Delete a boost/bury rule","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/search/analytics":{"get":{"tags":["Search Merchandising"],"summary":"Search analytics summary","description":"Summarizes top queries and zero-result queries from the search_queries table (best-effort; empty if the table is absent). RBAC: search.manage.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Analytics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchAnalytics"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/autopilot/actions":{"get":{"tags":["Store Autopilot"],"summary":"List autopilot actions","description":"Lists proposed/decided autopilot actions for the tenant, newest first. Filterable by status and actionType. RBAC: manage (admin + owner).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["pending","approved","auto_applied","reverted","dismissed"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","enum":["hide_from_search","create_restock_suggestion","flag_order_for_review","apply_safety_discount"]},"required":false,"name":"actionType","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"perPage","in":"query"}],"responses":{"200":{"description":"Actions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAutopilotActionsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotError"}}}}}}},"/v1/autopilot/actions/{id}/approve":{"post":{"tags":["Store Autopilot"],"summary":"Approve and apply an autopilot action","description":"Applies the reversible domain mutation for a pending action and transitions it to `approved`. Idempotent re-approval of an already-applied row is a no-op (409). RBAC: manage.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Applied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotAction"}}}},"400":{"description":"Mutation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotError"}}}},"409":{"description":"Wrong state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotError"}}}}}}},"/v1/autopilot/actions/{id}/revert":{"post":{"tags":["Store Autopilot"],"summary":"Revert an applied autopilot action","description":"Restores the domain state from the snapshot captured at apply time and transitions the action to `reverted`. Only `approved` / `auto_applied` actions are revertible. Idempotent. RBAC: manage.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Reverted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotAction"}}}},"400":{"description":"Revert failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotError"}}}},"409":{"description":"Wrong state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotError"}}}}}}},"/v1/autopilot/actions/{id}/dismiss":{"post":{"tags":["Store Autopilot"],"summary":"Dismiss a pending autopilot action","description":"Marks a pending action as `dismissed` without applying any mutation. Only pending actions can be dismissed. RBAC: manage.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Dismissed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotAction"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotError"}}}},"409":{"description":"Wrong state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotError"}}}}}}},"/v1/autopilot/policy":{"get":{"tags":["Store Autopilot"],"summary":"Get the autopilot governance policy","description":"Returns the per-tenant governance policy controlling auto-apply (max impact, min confidence, allowlisted action types). Defaults apply when unset. RBAC: manage.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Policy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotPolicy"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotError"}}}}}},"put":{"tags":["Store Autopilot"],"summary":"Update the autopilot governance policy","description":"Upserts the per-tenant governance policy. RBAC: manage.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotPolicy"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotPolicy"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotError"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutopilotError"}}}}}}},"/v1/companies":{"get":{"tags":["B2B Companies"],"summary":"List companies","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["active","pending","blocked"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"search","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Companies","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Company"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"post":{"tags":["B2B Companies"],"summary":"Create a company","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCompanyBody"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Company"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/companies/by-customer/{customerId}":{"get":{"tags":["B2B Companies"],"summary":"Resolve a customer to their company + B2B pricing","description":"Maps a customer → their active company → default price list + applicable shared catalog. Non-B2B customers resolve to all-null.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"customerId","in":"path"}],"responses":{"200":{"description":"Resolution","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"customer_id":{"type":"string"},"company_id":{"type":"string","nullable":true},"price_list_id":{"type":"string","nullable":true},"shared_catalog_id":{"type":"string","nullable":true}},"required":["customer_id","company_id","price_list_id","shared_catalog_id"]}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/companies/{id}":{"get":{"tags":["B2B Companies"],"summary":"Get a company","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Company","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Company"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"patch":{"tags":["B2B Companies"],"summary":"Update a company","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCompanyBody"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Company"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"delete":{"tags":["B2B Companies"],"summary":"Delete a company","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/companies/{id}/users":{"get":{"tags":["B2B Companies"],"summary":"List company users","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Users","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CompanyUser"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"post":{"tags":["B2B Companies"],"summary":"Add a user to a company","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCompanyUserBody"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CompanyUser"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"409":{"description":"Duplicate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/companies/{id}/users/{userId}":{"patch":{"tags":["B2B Companies"],"summary":"Update a company user","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"userId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCompanyUserBody"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CompanyUser"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"delete":{"tags":["B2B Companies"],"summary":"Remove a user from a company","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"userId","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/companies/{id}/shared-catalogs":{"get":{"tags":["B2B Companies"],"summary":"List shared catalogs visible to a company","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Catalogs","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CompanyCatalog"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/shared-catalogs":{"get":{"tags":["B2B Companies"],"summary":"List shared catalogs","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Catalogs","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SharedCatalog"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"post":{"tags":["B2B Companies"],"summary":"Create a shared catalog","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSharedCatalogBody"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SharedCatalog"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/shared-catalogs/{id}":{"get":{"tags":["B2B Companies"],"summary":"Get a shared catalog","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Catalog","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SharedCatalog"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"patch":{"tags":["B2B Companies"],"summary":"Update a shared catalog","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSharedCatalogBody"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SharedCatalog"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"delete":{"tags":["B2B Companies"],"summary":"Delete a shared catalog","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/shared-catalogs/{id}/companies":{"get":{"tags":["B2B Companies"],"summary":"List companies assigned to a shared catalog","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Assigned companies","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"shared_catalog_id":{"type":"string"},"company_id":{"type":"string"}},"required":["id","shared_catalog_id","company_id"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"put":{"tags":["B2B Companies"],"summary":"Assign companies to a shared catalog","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignCompaniesBody"}}}},"responses":{"200":{"description":"Assigned","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"shared_catalog_id":{"type":"string"},"company_id":{"type":"string"}},"required":["id","shared_catalog_id","company_id"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/shared-catalogs/{id}/products":{"get":{"tags":["B2B Companies"],"summary":"List a shared catalog product-visibility set","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Products","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"shared_catalog_id":{"type":"string"},"product_id":{"type":"string"},"is_visible":{"type":"boolean"}},"required":["id","shared_catalog_id","product_id","is_visible"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"put":{"tags":["B2B Companies"],"summary":"Set product visibility on a shared catalog","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetCatalogProductsBody"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"shared_catalog_id":{"type":"string"},"product_id":{"type":"string"},"is_visible":{"type":"boolean"}},"required":["id","shared_catalog_id","product_id","is_visible"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/requisition-lists":{"get":{"tags":["B2B Companies"],"summary":"List requisition lists","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"company_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"customer_id","in":"query"}],"responses":{"200":{"description":"Lists","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RequisitionList"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"post":{"tags":["B2B Companies"],"summary":"Create a requisition list","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRequisitionListBody"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RequisitionList"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Company not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/requisition-lists/{id}":{"get":{"tags":["B2B Companies"],"summary":"Get a requisition list","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"List","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RequisitionList"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"patch":{"tags":["B2B Companies"],"summary":"Rename a requisition list","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRequisitionListBody"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RequisitionList"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"delete":{"tags":["B2B Companies"],"summary":"Delete a requisition list","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/requisition-lists/{id}/items":{"get":{"tags":["B2B Companies"],"summary":"List requisition list items","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Items","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RequisitionListItem"}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"post":{"tags":["B2B Companies"],"summary":"Add an item to a requisition list","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRequisitionListItemBody"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RequisitionListItem"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/requisition-lists/{id}/items/{itemId}":{"patch":{"tags":["B2B Companies"],"summary":"Update a requisition list item quantity","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"itemId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRequisitionListItemBody"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RequisitionListItem"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}},"delete":{"tags":["B2B Companies"],"summary":"Remove a requisition list item","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"itemId","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/requisition-lists/{id}/add-to-cart-ready":{"post":{"tags":["B2B Companies"],"summary":"Resolve a requisition list to cart-ready items at current prices","description":"Resolves the list owner customer → B2B price list (company default / shared catalog), then prices each item (price_list > variant > base). Returns line totals + a grand total in cents.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Resolved cart","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"requisition_list_id":{"type":"string"},"price_list_id":{"type":"string","nullable":true},"shared_catalog_id":{"type":"string","nullable":true},"items":{"type":"array","items":{"type":"object","properties":{"product_id":{"type":"string"},"variant_id":{"type":"string","nullable":true},"quantity":{"type":"integer"},"unit_price_cents":{"type":"integer"},"line_total_cents":{"type":"integer"},"price_source":{"type":"string","enum":["price_list","variant","base"]}},"required":["product_id","variant_id","quantity","unit_price_cents","line_total_cents","price_source"]}},"total_cents":{"type":"integer"}},"required":["requisition_list_id","price_list_id","shared_catalog_id","items","total_cents"]}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bProblem"}}}}}}},"/v1/v1/markets":{"get":{"tags":["Markets"],"summary":"List markets","parameters":[{"schema":{"type":"string","enum":["true","false"],"description":"Filter by active flag"},"required":false,"description":"Filter by active flag","name":"active","in":"query"}],"responses":{"200":{"description":"List of markets ordered by default first","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Market"}}},"required":["data"]}}}}}},"post":{"tags":["Markets"],"summary":"Create a market","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMarketBody"}}}},"responses":{"201":{"description":"Market created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Market"}},"required":["data"]}}}},"409":{"description":"Handle already in use"}}}},"/v1/v1/markets/{id}":{"get":{"tags":["Markets"],"summary":"Get a market by id or handle","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Market detail","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Market"}},"required":["data"]}}}},"404":{"description":"Market not found"}}},"patch":{"tags":["Markets"],"summary":"Update a market","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMarketBody"}}}},"responses":{"200":{"description":"Market updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Market"}},"required":["data"]}}}},"404":{"description":"Market not found"}}},"delete":{"tags":["Markets"],"summary":"Delete a market","description":"Hard delete. The default market cannot be deleted while it is the only/default market.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Market deleted"},"400":{"description":"Cannot delete the default market"},"404":{"description":"Market not found"}}}},"/v1/agent-keys":{"get":{"tags":["Agent Keys"],"summary":"List registered agent keys (AP2 PKI)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Keys","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentKeyList"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Agent Keys"],"summary":"Register an agent public key (AP2 PKI)","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterAgentKeyBody"}}}},"responses":{"201":{"description":"Registered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentKey"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Key id already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/agent-keys/{keyId}":{"delete":{"tags":["Agent Keys"],"summary":"Revoke an agent key (kill-switch)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"keyId","in":"path"}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentKey"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Agent Keys"],"summary":"Update an agent key status","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"keyId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["active","revoked"]}},"required":["status"]}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentKey"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/admin/relevance/eval":{"post":{"tags":["Admin"],"summary":"Evaluate search relevance (NDCG per mode)","description":"Builds the tenant catalog index and scores a graded golden query set with NDCG@10 / Recall@20 / MRR per retrieval mode (text always; vector/hybrid when Vectorize is bound). Returns per-mode + per-query breakdown and a hybrid-vs-text delta.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"goldenSet":{"type":"array","items":{"type":"object","properties":{"query":{"type":"string","minLength":1,"example":"wireless headphones"},"relevantDocIds":{"type":"object","additionalProperties":{"type":"number"},"example":{"prod_01":3,"prod_02":1},"description":"docId → graded gain (0–3)"}},"required":["query","relevantDocIds"]},"minItems":1,"description":"Inline graded golden set. When omitted, the stored tenant set (or built-in default) is used."}}}}}},"responses":{"200":{"description":"Relevance evaluation report","content":{"application/json":{"schema":{"type":"object","properties":{"ndcgK":{"type":"number"},"recallK":{"type":"number"},"catalogSize":{"type":"number"},"queryCount":{"type":"number"},"goldenSetSource":{"type":"string","enum":["inline","stored","default"]},"modes":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"measurable":{"type":"boolean"},"reason":{"type":"string"},"ndcg10":{"type":"number","nullable":true},"recall20":{"type":"number","nullable":true},"mrr":{"type":"number","nullable":true},"perQuery":{"type":"array","nullable":true,"items":{"type":"object","properties":{"query":{"type":"string"},"ndcg10":{"type":"number"},"recall20":{"type":"number"},"rr":{"type":"number"},"ranked":{"type":"array","items":{"type":"string"}}},"required":["query","ndcg10","recall20","rr","ranked"]}}},"required":["name","measurable","ndcg10","recall20","mrr","perQuery"]}},"bestMode":{"type":"object","nullable":true,"properties":{"name":{"type":"string"},"ndcg10":{"type":"number"}},"required":["name","ndcg10"]},"hybridVsTextDelta":{"type":"number","nullable":true},"generatedAt":{"type":"string"}},"required":["ndcgK","recallK","catalogSize","queryCount","goldenSetSource","modes","bestMode","hybridVsTextDelta","generatedAt"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/admin/relevance/golden-set":{"get":{"tags":["Admin"],"summary":"Get the relevance golden set","description":"Returns the tenant-curated graded golden query set (empty array when none is stored).","responses":{"200":{"description":"Golden set","content":{"application/json":{"schema":{"type":"object","properties":{"goldenSet":{"type":"array","items":{"type":"object","properties":{"query":{"type":"string","minLength":1,"example":"wireless headphones"},"relevantDocIds":{"type":"object","additionalProperties":{"type":"number"},"example":{"prod_01":3,"prod_02":1},"description":"docId → graded gain (0–3)"}},"required":["query","relevantDocIds"]},"description":"Graded golden query set."}},"required":["goldenSet"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}},"put":{"tags":["Admin"],"summary":"Replace the relevance golden set","description":"Upserts the tenant-curated graded golden query set (singleton).","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"goldenSet":{"type":"array","items":{"type":"object","properties":{"query":{"type":"string","minLength":1,"example":"wireless headphones"},"relevantDocIds":{"type":"object","additionalProperties":{"type":"number"},"example":{"prod_01":3,"prod_02":1},"description":"docId → graded gain (0–3)"}},"required":["query","relevantDocIds"]},"minItems":1,"description":"Graded golden query set (>= 1 query)."}},"required":["goldenSet"]}}}},"responses":{"200":{"description":"Saved golden set","content":{"application/json":{"schema":{"type":"object","properties":{"goldenSet":{"type":"array","items":{"type":"object","properties":{"query":{"type":"string","minLength":1,"example":"wireless headphones"},"relevantDocIds":{"type":"object","additionalProperties":{"type":"number"},"example":{"prod_01":3,"prod_02":1},"description":"docId → graded gain (0–3)"}},"required":["query","relevantDocIds"]},"description":"Graded golden query set."}},"required":["goldenSet"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"},"detail":{"type":"string"}},"required":["type","title","status"]}}}}}}},"/v1/migration/jobs":{"post":{"tags":["Migration"],"summary":"Create a store-migration job","description":"Creates a migration job for importing a PrestaShop (SQL dump) or WooCommerce (CSV) store into a CANDIDATE database. Upload source files next, then start the job.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMigrationJobBody"}}}},"responses":{"201":{"description":"Job created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MigrationJob"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"tags":["Migration"],"summary":"List migration jobs","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"per_page","in":"query"},{"schema":{"type":"string","enum":["created","uploading","parsing","importing","dry_run_ready","promoting","promoted","discarding","discarded","failed"]},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"Paginated job list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MigrationJob"}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]}},"required":["data","pagination"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/migration/jobs/:id":{"get":{"tags":["Migration"],"summary":"Get a migration job (report + progress)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Job detail","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MigrationJob"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/migration/jobs/:id/upload":{"post":{"tags":["Migration"],"summary":"Upload a source export file for a migration job","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"},"kind":{"type":"string","enum":["dump","products","customers","orders"]}}}}}},"responses":{"200":{"description":"File stored","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MigrationJob"}},"required":["data"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Job is not accepting uploads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/migration/jobs/:id/start":{"post":{"tags":["Migration"],"summary":"Start importing into the candidate database","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"202":{"description":"Import started","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["created","uploading","parsing","importing","dry_run_ready","promoting","promoted","discarding","discarded","failed"]}},"required":["id","status"]}},"required":["data"]}}}},"400":{"description":"Missing source files","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Job already running or finished","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/migration/jobs/:id/promote":{"post":{"tags":["Migration"],"summary":"Promote the candidate DB to live (swaps tenants.db_url)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Promoted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MigrationJob"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Job is not in dry_run_ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/migration/jobs/:id/rollback":{"post":{"tags":["Migration"],"summary":"Roll back a promoted migration (restores the previous db_url)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Rolled back","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MigrationJob"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Job is not promoted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/migration/jobs/:id/discard":{"post":{"tags":["Migration"],"summary":"Discard the candidate DB (deletes it in Turso)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Discarded","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MigrationJob"}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Job cannot be discarded in its current status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/v1/marketplaces":{"get":{"tags":["Marketplaces"],"summary":"List marketplace connections","description":"Connection health per provider (last feed / last sync / last error). Credentials are write-only and NEVER returned.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Marketplace connections","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string","enum":["amazon","miravia","tiktok"],"example":"amazon"},"isActive":{"type":"number"},"isTestMode":{"type":"number"},"config":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"hasCredentials":{"type":"boolean","enum":[true]},"lastFeedAt":{"type":"number","nullable":true},"lastFeedR2Key":{"type":"string","nullable":true},"lastSyncAt":{"type":"number","nullable":true},"lastError":{"type":"string","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","provider","isActive","isTestMode","config","hasCredentials","lastFeedAt","lastFeedR2Key","lastSyncAt","lastError","createdAt","updatedAt"]}}},"required":["data"]}}}}}}},"/v1/marketplaces/:provider/connection":{"post":{"tags":["Marketplaces"],"summary":"Connect a marketplace","description":"Creates the tenant connection for a provider (one per provider). Credentials are AES-GCM encrypted before storage and never returned.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["amazon","miravia","tiktok"],"example":"amazon"},"required":true,"name":"provider","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"credentials":{"type":"object","additionalProperties":{"type":"string"},"example":{"accessToken":"atza|EXAMPLE","sellerId":"A2EXAMPLE"}},"config":{"type":"object","additionalProperties":{"nullable":true}},"isActive":{"type":"boolean","default":true},"isTestMode":{"type":"boolean","default":true}},"required":["credentials"]}}}},"responses":{"201":{"description":"Connection created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string","enum":["amazon","miravia","tiktok"],"example":"amazon"},"isActive":{"type":"number"},"isTestMode":{"type":"number"},"config":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"hasCredentials":{"type":"boolean","enum":[true]},"lastFeedAt":{"type":"number","nullable":true},"lastFeedR2Key":{"type":"string","nullable":true},"lastSyncAt":{"type":"number","nullable":true},"lastError":{"type":"string","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","provider","isActive","isTestMode","config","hasCredentials","lastFeedAt","lastFeedR2Key","lastSyncAt","lastError","createdAt","updatedAt"]}},"required":["data"]}}}},"409":{"description":"Provider already connected","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}},"patch":{"tags":["Marketplaces"],"summary":"Update a marketplace connection","description":"Partial update. When `credentials` is present they are re-encrypted (rotation); when absent the stored ciphertext is preserved untouched. Credentials are never returned.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["amazon","miravia","tiktok"],"example":"amazon"},"required":true,"name":"provider","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"credentials":{"type":"object","additionalProperties":{"type":"string"},"example":{"accessToken":"atza|EXAMPLE","sellerId":"A2EXAMPLE"}},"config":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"isActive":{"type":"boolean"},"isTestMode":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Connection updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string","enum":["amazon","miravia","tiktok"],"example":"amazon"},"isActive":{"type":"number"},"isTestMode":{"type":"number"},"config":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"hasCredentials":{"type":"boolean","enum":[true]},"lastFeedAt":{"type":"number","nullable":true},"lastFeedR2Key":{"type":"string","nullable":true},"lastSyncAt":{"type":"number","nullable":true},"lastError":{"type":"string","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","provider","isActive","isTestMode","config","hasCredentials","lastFeedAt","lastFeedR2Key","lastSyncAt","lastError","createdAt","updatedAt"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}},"delete":{"tags":["Marketplaces"],"summary":"Disconnect a marketplace","description":"Hard-deletes the connection (the encrypted credentials are destroyed with the row).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["amazon","miravia","tiktok"],"example":"amazon"},"required":true,"name":"provider","in":"path"}],"responses":{"200":{"description":"Connection deleted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]}},"required":["deleted"]}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}},"/v1/marketplaces/:provider/feed/generate":{"post":{"tags":["Marketplaces"],"summary":"Generate a marketplace product feed","description":"Builds the full catalog feed (active products, multi-warehouse stock, exact decimal money) in the provider format (amazon=tsv, miravia=xml, tiktok=jsonl; overridable), stores it in R2 under marketplaces/{tenantId}/{provider}/ and returns an HMAC-signed download URL.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["amazon","miravia","tiktok"],"example":"amazon"},"required":true,"name":"provider","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"format":{"type":"string","enum":["jsonl","tsv","xml"]}}}}}},"responses":{"200":{"description":"Feed generated and uploaded","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"provider":{"type":"string","enum":["amazon","miravia","tiktok"],"example":"amazon"},"format":{"type":"string","enum":["jsonl","tsv","xml"]},"itemCount":{"type":"number"},"r2Key":{"type":"string"},"downloadUrl":{"type":"string"},"generatedAt":{"type":"number"}},"required":["provider","format","itemCount","r2Key","downloadUrl","generatedAt"]}},"required":["data"]}}}},"400":{"description":"Connection inactive","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}},"404":{"description":"No connection for provider","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"number"}},"required":["type","title","status"]}}}}}}}}}