{
  "openapi": "3.1.0",
  "info": {
    "title": "Syncore API",
    "version": "1.0.0",
    "description": "REST API για πελάτες του Syncore. Κάθε token ανήκει σε έναν χρήστη και βλέπει μόνο τα δεδομένα της δικής του επιχείρησης. Τα tokens δημιουργούνται στο Προφίλ με δικαιώματα (abilities). Όριο αιτημάτων ανά λεπτό ανάλογα με το πλάνο, και προαιρετικά χαμηλότερο όριο ανά token (429 με Retry-After όταν ξεπεραστεί)."
  },
  "servers": [{ "url": "/api/v1" }],
  "security": [{ "bearerAuth": [] }],
  "tags": [
    { "name": "Products" }, { "name": "Inventory" }, { "name": "Orders" }, { "name": "Suppliers" },
    { "name": "Channels" }, { "name": "Price rules" }, { "name": "Prices" }, { "name": "Invoices" }, { "name": "Webhooks" }
  ],
  "paths": {
    "/products": {
      "get": {
        "tags": ["Products"], "summary": "Λίστα προϊόντων", "x-ability": "products:read",
        "parameters": [
          { "$ref": "#/components/parameters/page" }, { "$ref": "#/components/parameters/per_page" },
          { "name": "search", "in": "query", "description": "SKU ή όνομα", "schema": { "type": "string" } },
          { "name": "sku", "in": "query", "description": "SKUs χωρισμένα με κόμμα", "schema": { "type": "string" } },
          { "name": "supplier_id", "in": "query", "schema": { "type": "integer" } },
          { "name": "enabled", "in": "query", "schema": { "type": "integer", "enum": [0, 1] } },
          { "name": "stock_status", "in": "query", "schema": { "type": "string", "enum": ["in_stock", "low_stock", "out_of_stock"] } }
        ],
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProductPage" } } } }, "403": { "$ref": "#/components/responses/Forbidden" }, "429": { "$ref": "#/components/responses/TooMany" } }
      }
    },
    "/products/{id}": {
      "parameters": [{ "$ref": "#/components/parameters/id" }],
      "get": {
        "tags": ["Products"], "summary": "Ένα προϊόν", "x-ability": "products:read",
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Product" } } } } } }, "404": { "$ref": "#/components/responses/NotFound" } }
      },
      "patch": {
        "tags": ["Products"], "summary": "Ενεργό / χειροκίνητη τιμή", "x-ability": "products:write (+ prices:write για manual_price)",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": {
          "enabled": { "type": "boolean" },
          "manual_price": { "type": ["number", "null"], "description": "null = επιστροφή στους κανόνες τιμών" }
        } } } } },
        "responses": { "200": { "description": "OK" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/Invalid" } }
      }
    },
    "/inventory": {
      "get": {
        "tags": ["Inventory"], "summary": "Δικό σου απόθεμα", "x-ability": "inventory:read",
        "parameters": [{ "$ref": "#/components/parameters/page" }, { "$ref": "#/components/parameters/per_page" }, { "name": "search", "in": "query", "schema": { "type": "string" } }],
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/InventoryItem" } }, "meta": { "$ref": "#/components/schemas/Meta" } } } } } } }
      }
    },
    "/inventory/{sku}": {
      "put": {
        "tags": ["Inventory"], "summary": "Ορισμός αποθέματος για ένα SKU", "x-ability": "inventory:write",
        "parameters": [{ "name": "sku", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["quantity"], "properties": { "quantity": { "type": "integer", "minimum": 0 }, "notes": { "type": "string" } } } } } },
        "responses": { "200": { "description": "OK" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/Invalid" } }
      }
    },
    "/inventory/bulk": {
      "post": {
        "tags": ["Inventory"], "summary": "Μαζική ενημέρωση (έως 500)", "x-ability": "inventory:write",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["items"], "properties": { "items": { "type": "array", "maxItems": 500, "items": { "type": "object", "required": ["sku", "quantity"], "properties": { "sku": { "type": "string" }, "quantity": { "type": "integer", "minimum": 0 } } } } } } } } },
        "responses": { "200": { "description": "updated / failed / not_found λίστες SKU" } }
      }
    },
    "/orders": {
      "get": {
        "tags": ["Orders"], "summary": "Λίστα παραγγελιών", "x-ability": "orders:read",
        "parameters": [
          { "$ref": "#/components/parameters/page" }, { "$ref": "#/components/parameters/per_page" },
          { "name": "status", "in": "query", "schema": { "$ref": "#/components/schemas/OrderStatus" } },
          { "name": "source_channel", "in": "query", "schema": { "type": "string" } },
          { "name": "search", "in": "query", "schema": { "type": "string" } },
          { "name": "placed_from", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "placed_to", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "updated_since", "in": "query", "schema": { "type": "string", "format": "date-time" } }
        ],
        "responses": { "200": { "description": "OK" } }
      },
      "post": {
        "tags": ["Orders"], "summary": "Νέα παραγγελία από το δικό σου κατάστημα (idempotent στο external_ref)", "x-ability": "orders:write",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OrderCreate" } } } },
        "responses": { "201": { "description": "Δημιουργήθηκε" }, "200": { "description": "Υπήρχε ήδη (ίδιο external_ref)" }, "422": { "$ref": "#/components/responses/Invalid" } }
      }
    },
    "/orders/{id}": {
      "parameters": [{ "$ref": "#/components/parameters/id" }],
      "get": {
        "tags": ["Orders"], "summary": "Μία παραγγελία με γραμμές", "x-ability": "orders:read",
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Order" } } } } } }, "404": { "$ref": "#/components/responses/NotFound" } }
      }
    },
    "/orders/{id}/status": {
      "parameters": [{ "$ref": "#/components/parameters/id" }],
      "patch": {
        "tags": ["Orders"], "summary": "Αλλαγή κατάστασης (επόμενο βήμα ή ακύρωση)", "x-ability": "orders:write",
        "description": "pending → processing → shipped → completed· cancelled από κάθε μη τελική κατάσταση. Άλλη μετάβαση: 422 με allowed.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["status"], "properties": { "status": { "type": "string", "enum": ["processing", "shipped", "completed", "cancelled"] } } } } } },
        "responses": { "200": { "description": "OK" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/Invalid" } }
      }
    },
    "/orders/{id}/shipment": {
      "parameters": [{ "$ref": "#/components/parameters/id" }],
      "post": {
        "tags": ["Orders"], "summary": "Αποστολή με μεταφορική και αριθμό αποστολής", "x-ability": "orders:write",
        "description": "Η παραγγελία γίνεται shipped και η μεταφορική/αριθμός αποστολής στέλνονται (στην ουρά) στο κανάλι προέλευσης (Skroutz, Shopflix, eMAG, Trendyol, Temu, TikTok Shop). Η πρόοδος φαίνεται στο shipment.push_status (pending, success, failed, skipped). Επανάληψη με τα ίδια στοιχεία ξαναδοκιμάζει μόνο αν δεν έχει πετύχει.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["courier", "tracking_number"], "properties": { "courier": { "type": "string", "maxLength": 64 }, "tracking_number": { "type": "string", "maxLength": 128 } } } } } },
        "responses": { "200": { "description": "OK" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/Invalid" } }
      }
    },
    "/suppliers": {
      "get": { "tags": ["Suppliers"], "summary": "Οι προμηθευτές σου", "x-ability": "suppliers:read", "responses": { "200": { "description": "OK" } } }
    },
    "/channels": {
      "get": { "tags": ["Channels"], "summary": "Κανάλια πώλησης", "x-ability": "channels:read", "responses": { "200": { "description": "OK" } } }
    },
    "/feeds": {
      "get": { "tags": ["Channels"], "summary": "Διευθύνσεις feeds ανά κανάλι", "x-ability": "feeds:read", "responses": { "200": { "description": "OK" } } }
    },
    "/price-rules": {
      "get": { "tags": ["Price rules"], "summary": "Κανόνες τιμών", "x-ability": "prices:read", "parameters": [{ "$ref": "#/components/parameters/page" }, { "$ref": "#/components/parameters/per_page" }], "responses": { "200": { "description": "OK" } } },
      "post": {
        "tags": ["Price rules"], "summary": "Νέος κανόνας", "x-ability": "prices:write",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PriceRuleInput" } } } },
        "responses": { "201": { "description": "Δημιουργήθηκε" }, "422": { "$ref": "#/components/responses/Invalid" } }
      }
    },
    "/price-rules/{id}": {
      "parameters": [{ "$ref": "#/components/parameters/id" }],
      "get": { "tags": ["Price rules"], "summary": "Ένας κανόνας", "x-ability": "prices:read", "responses": { "200": { "description": "OK" }, "404": { "$ref": "#/components/responses/NotFound" } } },
      "patch": {
        "tags": ["Price rules"], "summary": "Αλλαγή (μερική)", "x-ability": "prices:write",
        "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PriceRuleInput" } } } },
        "responses": { "200": { "description": "OK" }, "404": { "$ref": "#/components/responses/NotFound" }, "422": { "$ref": "#/components/responses/Invalid" } }
      },
      "delete": { "tags": ["Price rules"], "summary": "Διαγραφή", "x-ability": "prices:write", "responses": { "204": { "description": "Διαγράφηκε" }, "404": { "$ref": "#/components/responses/NotFound" } } }
    },
    "/webhooks": {
      "get": { "tags": ["Webhooks"], "summary": "Webhook endpoints", "x-ability": "webhooks:manage", "responses": { "200": { "description": "OK" } } },
      "post": {
        "tags": ["Webhooks"], "summary": "Νέο endpoint (το secret επιστρέφεται μία φορά)", "x-ability": "webhooks:manage",
        "description": "Κάθε αποστολή: POST JSON {id, event, created_at, data} με headers X-Syncore-Event, X-Syncore-Delivery, X-Syncore-Timestamp και X-Syncore-Signature = sha256=HEX(HMAC-SHA256(secret, timestamp + '.' + body)). Μη-2xx απάντηση ξαναδοκιμάζεται (1, 5, 30 λεπτά, 2 ώρες). stock.low: μία φορά όταν το απόθεμα πέφτει στο όριο χαμηλού αποθέματος (data: product_id, sku, quantity, quantity_before, reserved, threshold). feed.generated: data: channel, trigger, products_count, file_size, feed_url, generated_at.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["url", "events"], "properties": {
          "url": { "type": "string", "format": "uri", "description": "δημόσια https διεύθυνση" },
          "events": { "type": "array", "items": { "type": "string", "enum": ["order.created", "order.updated", "product.updated", "stock.changed", "stock.low", "feed.generated"] } }
        } } } } },
        "responses": { "201": { "description": "Δημιουργήθηκε (περιέχει secret)" }, "422": { "$ref": "#/components/responses/Invalid" } }
      }
    },
    "/webhooks/{id}": {
      "parameters": [{ "$ref": "#/components/parameters/id" }],
      "delete": { "tags": ["Webhooks"], "summary": "Διαγραφή endpoint", "x-ability": "webhooks:manage", "responses": { "204": { "description": "Διαγράφηκε" }, "404": { "$ref": "#/components/responses/NotFound" } } }
    },
    "/webhooks/{id}/rotate-secret": {
      "parameters": [{ "$ref": "#/components/parameters/id" }],
      "post": { "tags": ["Webhooks"], "summary": "Νέο secret υπογραφής (επιστρέφεται μία φορά· το παλιό παύει αμέσως)", "x-ability": "webhooks:manage", "responses": { "200": { "description": "OK (περιέχει secret)" }, "404": { "$ref": "#/components/responses/NotFound" } } }
    },
    "/prices": {
      "get": {
        "tags": ["Prices"], "summary": "Τελικές τιμές πώλησης", "x-ability": "prices:read",
        "parameters": [
          { "$ref": "#/components/parameters/page" }, { "$ref": "#/components/parameters/per_page" },
          { "name": "sku", "in": "query", "description": "SKUs χωρισμένα με κόμμα", "schema": { "type": "string" } },
          { "name": "supplier_id", "in": "query", "schema": { "type": "integer" } }
        ],
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Price" } }, "meta": { "$ref": "#/components/schemas/Meta" }, "links": { "type": "object" } } } } } } }
      }
    },
    "/invoices": {
      "get": {
        "tags": ["Invoices"], "summary": "Παραστατικά Oxygen (τιμολόγια, αποδείξεις, πιστωτικά)", "x-ability": "invoices:read",
        "parameters": [
          { "$ref": "#/components/parameters/page" }, { "$ref": "#/components/parameters/per_page" },
          { "name": "status", "in": "query", "schema": { "type": "string", "enum": ["pending", "issued", "failed"] } },
          { "name": "kind", "in": "query", "schema": { "type": "string", "enum": ["invoice", "credit_note"] } },
          { "name": "order_id", "in": "query", "schema": { "type": "integer" } }
        ],
        "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Invoice" } }, "meta": { "$ref": "#/components/schemas/Meta" }, "links": { "type": "object" } } } } } } }
      }
    },
    "/invoices/{id}": {
      "parameters": [{ "$ref": "#/components/parameters/id" }],
      "get": { "tags": ["Invoices"], "summary": "Ένα παραστατικό (pdf_url: σύνδεσμος προβολής/PDF του Oxygen)", "x-ability": "invoices:read", "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Invoice" } } } } } }, "404": { "$ref": "#/components/responses/NotFound" } } }
    }
  },
  "components": {
    "securitySchemes": { "bearerAuth": { "type": "http", "scheme": "bearer", "description": "Token από Προφίλ → API tokens" } },
    "parameters": {
      "id": { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } },
      "page": { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1 } },
      "per_page": { "name": "per_page", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 25 } }
    },
    "responses": {
      "Forbidden": { "description": "Το token δεν έχει το απαιτούμενο δικαίωμα" },
      "NotFound": { "description": "Δεν βρέθηκε (ή ανήκει σε άλλη επιχείρηση)" },
      "Invalid": { "description": "Λάθος δεδομένα: {message, errors}" },
      "TooMany": { "description": "Ξεπεράστηκε το όριο αιτημάτων· δες Retry-After" }
    },
    "schemas": {
      "Meta": { "type": "object", "properties": { "current_page": { "type": "integer" }, "per_page": { "type": "integer" }, "total": { "type": "integer" }, "last_page": { "type": "integer" } } },
      "Product": { "type": "object", "properties": {
        "id": { "type": "integer" }, "sku": { "type": "string" }, "ean": { "type": ["string", "null"] }, "name": { "type": "string" }, "brand": { "type": ["string", "null"] },
        "supplier": { "type": ["object", "null"], "properties": { "id": { "type": "integer" }, "name": { "type": "string" } } },
        "base_price": { "type": ["number", "null"] }, "final_price": { "type": ["number", "null"] }, "manual_price": { "type": "boolean" },
        "enabled": { "type": "boolean" }, "supplier_stock": { "type": "integer" }, "variant_count": { "type": "integer" }, "updated_at": { "type": ["string", "null"], "format": "date-time" }
      } },
      "ProductPage": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Product" } }, "meta": { "$ref": "#/components/schemas/Meta" }, "links": { "type": "object" } } },
      "InventoryItem": { "type": "object", "properties": { "product_id": { "type": "integer" }, "sku": { "type": "string" }, "name": { "type": "string" }, "quantity": { "type": "integer" }, "reserved": { "type": "integer" }, "last_sync_at": { "type": ["string", "null"], "format": "date-time" } } },
      "Price": { "type": "object", "properties": { "product_id": { "type": "integer" }, "sku": { "type": "string" }, "base_price": { "type": ["number", "null"] }, "final_price": { "type": ["number", "null"] }, "manual_price": { "type": "boolean" }, "price_rule_id": { "type": ["integer", "null"] }, "updated_at": { "type": ["string", "null"], "format": "date-time" } } },
      "Invoice": { "type": "object", "properties": {
        "id": { "type": "integer" }, "order_id": { "type": ["integer", "null"] }, "kind": { "type": "string", "enum": ["invoice", "credit_note"] }, "status": { "type": "string", "enum": ["pending", "issued", "failed"] },
        "document_type": { "type": ["string", "null"] }, "mydata_type": { "type": ["string", "null"] }, "number": { "type": ["string", "null"] }, "mark": { "type": ["string", "null"] },
        "total": { "type": ["number", "null"] }, "is_paid": { "type": ["boolean", "null"] }, "pdf_url": { "type": ["string", "null"], "format": "uri" }, "error": { "type": ["string", "null"] },
        "issued_at": { "type": ["string", "null"], "format": "date-time" }, "created_at": { "type": ["string", "null"], "format": "date-time" }
      } },
      "OrderStatus": { "type": "string", "enum": ["pending", "processing", "shipped", "completed", "cancelled", "refunded"] },
      "Order": { "type": "object", "properties": {
        "id": { "type": "integer" }, "order_number": { "type": ["string", "null"] }, "external_ref": { "type": ["string", "null"] }, "source_channel": { "type": "string" },
        "status": { "$ref": "#/components/schemas/OrderStatus" }, "currency": { "type": "string" }, "subtotal": { "type": "number" }, "shipping_cost": { "type": "number" }, "total_amount": { "type": "number" },
        "customer": { "type": "object", "properties": { "name": { "type": ["string", "null"] }, "email": { "type": ["string", "null"] }, "phone": { "type": ["string", "null"] } } },
        "items": { "type": "array", "items": { "type": "object", "properties": { "product_id": { "type": ["integer", "null"] }, "sku": { "type": "string" }, "name": { "type": "string" }, "quantity": { "type": "integer" }, "unit_price": { "type": "number" }, "total_price": { "type": "number" } } } }
      } },
      "OrderCreate": { "type": "object", "required": ["external_ref", "items"], "properties": {
        "external_ref": { "type": "string", "description": "ο κωδικός της παραγγελίας στο κατάστημά σου" },
        "order_number": { "type": "string" }, "currency": { "type": "string", "default": "EUR" }, "shipping_cost": { "type": "number" },
        "payment_method": { "type": "string" }, "notes": { "type": "string" }, "placed_at": { "type": "string", "format": "date-time" },
        "customer": { "type": "object", "properties": { "name": { "type": "string" }, "email": { "type": "string" }, "phone": { "type": "string" } } },
        "shipping_address": { "type": "object", "additionalProperties": { "type": "string" } },
        "billing_address": { "type": "object", "additionalProperties": { "type": "string" } },
        "items": { "type": "array", "minItems": 1, "maxItems": 500, "items": { "type": "object", "required": ["sku", "quantity", "unit_price"], "properties": { "sku": { "type": "string" }, "name": { "type": "string" }, "quantity": { "type": "integer", "minimum": 1 }, "unit_price": { "type": "number" } } } }
      } },
      "PriceRuleInput": { "type": "object", "properties": {
        "name": { "type": "string" }, "description": { "type": "string" },
        "rule_type": { "type": "integer", "enum": [1, 2, 3], "description": "1 ποσοστό, 2 σταθερό ποσό, 3 σταθερή τιμή" },
        "value": { "type": "number", "minimum": 0 },
        "price_rule_scope": { "type": "integer", "enum": [1, 2, 3, 4], "description": "1 όλα, 2 προμηθευτής, 3 κατηγορία, 4 προϊόν" },
        "global_supplier_id": { "type": "integer" }, "global_category_id": { "type": "integer" }, "global_product_id": { "type": "integer" },
        "rule_conditions": { "type": "boolean" }, "price_comparison": { "type": "integer", "enum": [1, 2], "description": "1 μικρότερη από, 2 μεγαλύτερη από" },
        "price_threshold": { "type": "number" }, "is_enabled": { "type": "boolean" }
      } }
    }
  }
}
