{"openapi":"3.1.0","info":{"title":"Morelina Shop API","version":"1.0.0","description":"Borse, gioielli e accessori fatti a mano a Firenze da Silvia Favilla. Flusso d'acquisto per persone e agenti: 1) GET /api/catalog  2) GET /api/promo  3) POST /api/cart/quote  4) POST /api/orders (con header Idempotency-Key) 5) la cliente paga: payment.type=\"stripe\" → Stripe Embedded Checkout con clientSecret; \"bank\" → bonifico con causale. I prezzi sono sempre calcolati dal server. I pezzi con unique=true esistono in un solo esemplare.","contact":{"email":"morelinadesign@gmail.com"}},"servers":[{"url":"https://morelina.pages.dev"}],"paths":{"/api/catalog":{"get":{"operationId":"listProducts","summary":"Catalogo con filtri","parameters":[{"name":"type","in":"query","schema":{"enum":["borse","gioielli","accessori"]}},{"name":"min","in":"query","schema":{"type":"number"}},{"name":"max","in":"query","schema":{"type":"number"}},{"name":"collection","in":"query","schema":{"type":"string"}},{"name":"unique","in":"query","schema":{"enum":["1"]}},{"name":"q","in":"query","schema":{"type":"string"},"description":"ricerca testuale"},{"name":"sort","in":"query","schema":{"enum":["new","price-asc","price-desc","name"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"integer"},"count":{"type":"integer"},"items":{"type":"array","items":{"$ref":"#/components/schemas/Product"}}}}}}}}}},"/api/catalog/{slug}":{"get":{"operationId":"getProduct","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"404":{"description":"Errore","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/promo":{"get":{"operationId":"getPromo","summary":"Promozione attiva. Con inviteOnly=true i codici non sono pubblici: si ricevono con il link d'invito","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Promo"}}}}}}},"/api/promo/invite":{"get":{"operationId":"checkInvite","summary":"Verifica un codice d'invito Family & Friends (dal link ?invito=CODICE)","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean"},"code":{"type":"string"},"tier":{"enum":["public","email"]},"percent":{"type":"integer"},"opensAt":{"type":"string"},"end":{"type":"string"},"open":{"type":"boolean"}}}}}}}}},"/api/shop":{"get":{"operationId":"getShopInfo","summary":"Spedizioni, showroom, metodi di pagamento","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/cart/quote":{"post":{"operationId":"quoteCart","summary":"Prezzo del carrello con sconto e spedizione","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"422":{"description":"Errore","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/subscribe":{"post":{"operationId":"subscribe","summary":"Iscrizione con consenso: restituisce il codice sconto riservato se la promo è attiva","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","consent"],"properties":{"email":{"type":"string","format":"email"},"consent":{"const":true},"source":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"code":{"type":"string"},"percent":{"type":"integer"}}}}}},"422":{"description":"Errore","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Errore","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/orders":{"post":{"operationId":"placeOrder","summary":"Crea l'ordine (inviato a Silvia) e avvia il pagamento","parameters":[{"name":"Idempotency-Key","in":"header","schema":{"type":"string","maxLength":80},"description":"consigliato: ripetere la richiesta non crea un secondo ordine"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderInput"}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"order":{"$ref":"#/components/schemas/Order"},"token":{"type":"string","description":"serve per leggere lo stato dell'ordine"},"payment":{"$ref":"#/components/schemas/Payment"}}}}}},"409":{"description":"Errore","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Errore","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Errore","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/orders/{id}":{"get":{"operationId":"getOrder","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"token","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"404":{"description":"Errore","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"array","items":{"type":"string"}}}},"Product":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"price":{"type":"number","description":"EUR, prezzo di listino"},"unique":{"type":"boolean"},"sold":{"type":"boolean"},"type":{"type":"string"},"collection":{"type":"string"},"desc":{"type":"string"},"images":{"type":"array","items":{"type":"string"}}}},"Promo":{"type":"object","properties":{"active":{"type":"boolean"},"inviteOnly":{"type":"boolean"},"phase":{"enum":["off","before","active","ended"]},"end":{"type":"string"},"daysLeft":{"type":"integer"},"shipBy":{"type":"string"},"shipOpen":{"type":"boolean"},"public":{"type":"object","properties":{"percent":{"type":"integer"},"code":{"type":"string"}}},"email":{"type":"object","properties":{"enabled":{"type":"boolean"},"percent":{"type":"integer"}}}}},"CartInput":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"type":"object","required":["slug"],"properties":{"slug":{"type":"string"},"qty":{"type":"integer","minimum":1,"maximum":5}}}},"code":{"type":"string"},"country":{"type":"string","description":"ISO 3166-1 alpha-2, default IT"}}},"Quote":{"type":"object","properties":{"lines":{"type":"array","items":{"type":"object"}},"problems":{"type":"array","items":{"type":"object"}},"codeStatus":{"enum":["none","applied","invalid","expired"]},"percent":{"type":"integer"},"subtotal":{"type":"number"},"discount":{"type":"number"},"shipping":{"type":"object"},"total":{"type":"number"}}},"OrderInput":{"allOf":[{"$ref":"#/components/schemas/CartInput"},{"type":"object","required":["customer","shipping","paymentMethod","acceptTerms"],"properties":{"customer":{"type":"object","required":["firstName","lastName","email","phone"],"properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"}}},"shipping":{"type":"object","required":["address","city","zip","country"],"properties":{"address":{"type":"string"},"city":{"type":"string"},"zip":{"type":"string"},"province":{"type":"string"},"country":{"type":"string"}}},"notes":{"type":"string","maxLength":500},"paymentMethod":{"enum":["online","bank"]},"acceptTerms":{"const":true},"marketing":{"type":"boolean"}}}]},"Order":{"type":"object","properties":{"id":{"type":"string"},"number":{"type":"string"},"status":{"enum":["awaiting_payment","awaiting_transfer","paid","shipped","cancelled","expired"]},"total":{"type":"number"},"lines":{"type":"array","items":{"type":"object"}}}},"Payment":{"oneOf":[{"type":"object","properties":{"type":{"const":"stripe"},"clientSecret":{"type":"string"},"publishableKey":{"type":"string"}}},{"type":"object","properties":{"type":{"const":"bank"},"iban":{"type":"string"},"holder":{"type":"string"},"reference":{"type":"string"},"holdHours":{"type":"integer"}}},{"type":"object","properties":{"type":{"const":"mock"}},"description":"solo ambiente di prova"}]}}}}