{
  "openapi": "3.1.0",
  "info": {
    "title": "FireFeed Web API",
    "version": "0.0.1",
    "description": "API REST pubbliche del frontend FireFeed (Next.js App Router). Generato automaticamente dagli schemi Zod via @asteasolutions/zod-to-openapi."
  },
  "servers": [
    {
      "url": "https://exp.fire-feed.com"
    }
  ],
  "components": {
    "securitySchemes": {
      "cookieSession": {
        "type": "apiKey",
        "in": "cookie",
        "name": "authjs.session-token",
        "description": "Sessione NextAuth v5 (cookie HttpOnly). L'endpoint richiede di essere già autenticati via Keycloak SSO. Il playground non può autenticarsi: testa da browser loggato."
      }
    },
    "schemas": {
      "SessionUser": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "activeCompanyId": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "email",
          "name",
          "activeCompanyId"
        ]
      },
      "AgentConversation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "companyId": {
            "type": "string",
            "format": "uuid"
          },
          "projectId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "awaiting_approval",
              "archived"
            ]
          },
          "provider": {
            "type": "string",
            "enum": [
              "firefeed"
            ]
          },
          "model": {
            "type": "string",
            "description": "Nome pubblico del profilo, non identificativo del motore"
          },
          "profileId": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "aria",
              "sprint",
              "logica",
              "frontier"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "companyId",
          "projectId",
          "title",
          "status",
          "provider",
          "model",
          "profileId",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateAgentConversationBody": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string",
            "format": "uuid"
          },
          "profileId": {
            "type": "string",
            "enum": [
              "aria",
              "sprint",
              "logica",
              "frontier"
            ]
          }
        },
        "required": [
          "projectId"
        ],
        "additionalProperties": false
      },
      "AgentUsage": {
        "type": "object",
        "properties": {
          "inputTokens": {
            "type": "integer",
            "minimum": 0
          },
          "outputTokens": {
            "type": "integer",
            "minimum": 0
          },
          "cacheReadTokens": {
            "type": "integer",
            "minimum": 0
          },
          "cacheWriteTokens": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "inputTokens",
          "outputTokens",
          "cacheReadTokens",
          "cacheWriteTokens"
        ]
      },
      "AgentMessage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "role": {
            "type": "string",
            "enum": [
              "user",
              "assistant"
            ]
          },
          "content": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            }
          },
          "usage": {
            "$ref": "#/components/schemas/AgentUsage"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "role",
          "content",
          "usage",
          "createdAt"
        ]
      },
      "AgentToolCall": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "messageId": {
            "type": "string",
            "format": "uuid"
          },
          "toolUseId": {
            "type": "string"
          },
          "toolName": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "read",
              "act"
            ]
          },
          "input": {},
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "executed",
              "failed",
              "rejected",
              "reverted"
            ]
          },
          "result": {},
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "revertable": {
            "type": "boolean"
          },
          "decidedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "executedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "messageId",
          "toolUseId",
          "toolName",
          "kind",
          "status",
          "error",
          "revertable",
          "decidedAt",
          "executedAt",
          "createdAt"
        ]
      },
      "AgentConversationDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/AgentConversation"
          },
          {
            "type": "object",
            "properties": {
              "messages": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AgentMessage"
                }
              },
              "toolCalls": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AgentToolCall"
                }
              }
            },
            "required": [
              "messages",
              "toolCalls"
            ]
          }
        ]
      },
      "AgentEventStream": {
        "type": "object",
        "properties": {
          "stream": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "stream"
        ]
      },
      "SendAgentMessageBody": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000
          },
          "profileId": {
            "type": "string",
            "enum": [
              "aria",
              "sprint",
              "logica",
              "frontier"
            ]
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false
      },
      "AgentDecisionBody": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 500
          }
        }
      },
      "AgentMemory": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "scope": {
            "type": "string",
            "enum": [
              "project",
              "user"
            ]
          },
          "content": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "user",
              "assistant"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "scope",
          "content",
          "source",
          "createdAt"
        ]
      },
      "AgentMemoryList": {
        "type": "object",
        "properties": {
          "project": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AgentMemory"
            }
          },
          "user": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AgentMemory"
            }
          }
        },
        "required": [
          "project",
          "user"
        ]
      },
      "AgentUsageReport": {
        "type": "object",
        "properties": {
          "period": {
            "type": "string"
          },
          "tokens": {
            "allOf": [
              {
                "$ref": "#/components/schemas/AgentUsage"
              },
              {
                "type": "object",
                "properties": {
                  "total": {
                    "type": "integer",
                    "minimum": 0
                  }
                },
                "required": [
                  "total"
                ]
              }
            ]
          },
          "turns": {
            "type": "integer",
            "minimum": 0
          },
          "budget": {
            "type": "object",
            "properties": {
              "limit": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "warnAt": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "exceeded": {
                "type": "boolean"
              },
              "message": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "limit",
              "warnAt",
              "exceeded",
              "message"
            ]
          }
        },
        "required": [
          "period",
          "tokens",
          "turns",
          "budget"
        ]
      },
      "ActiveCompanyResult": {
        "type": "object",
        "properties": {
          "companyId": {
            "type": "string"
          }
        },
        "required": [
          "companyId"
        ]
      },
      "ActiveCompanyBody": {
        "type": "object",
        "properties": {
          "companyId": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "companyId"
        ]
      },
      "CompanyBrief": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "slug"
        ]
      },
      "Health": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ]
          },
          "service": {
            "type": "string",
            "enum": [
              "firefeed-web"
            ]
          }
        },
        "required": [
          "status",
          "service"
        ]
      },
      "CatalogColumnMapping": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "columnKey": {
                "type": "string",
                "minLength": 1
              },
              "source": {
                "type": "string",
                "enum": [
                  "field"
                ]
              },
              "field": {
                "type": "string",
                "minLength": 1
              },
              "fallback": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "field",
                      "static"
                    ]
                  },
                  "value": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "type",
                  "value"
                ]
              }
            },
            "required": [
              "columnKey",
              "source",
              "field"
            ]
          },
          {
            "type": "object",
            "properties": {
              "columnKey": {
                "type": "string",
                "minLength": 1
              },
              "source": {
                "type": "string",
                "enum": [
                  "static"
                ]
              },
              "value": {
                "type": "string"
              }
            },
            "required": [
              "columnKey",
              "source",
              "value"
            ]
          },
          {
            "type": "object",
            "properties": {
              "columnKey": {
                "type": "string",
                "minLength": 1
              },
              "source": {
                "type": "string",
                "enum": [
                  "category"
                ]
              }
            },
            "required": [
              "columnKey",
              "source"
            ]
          },
          {
            "type": "object",
            "properties": {
              "columnKey": {
                "type": "string",
                "minLength": 1
              },
              "source": {
                "type": "string",
                "enum": [
                  "none"
                ]
              }
            },
            "required": [
              "columnKey",
              "source"
            ]
          }
        ]
      },
      "CatalogEnrichmentSource": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "gallery"
                ]
              },
              "index": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "type"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "brand"
                ]
              }
            },
            "required": [
              "type"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "generalInfo"
                ]
              },
              "key": {
                "type": "string",
                "enum": [
                  "productName",
                  "mpn"
                ]
              }
            },
            "required": [
              "type",
              "key"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "feature"
                ]
              },
              "name": {
                "type": "string",
                "minLength": 1
              }
            },
            "required": [
              "type",
              "name"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "none"
                ]
              }
            },
            "required": [
              "type"
            ]
          }
        ]
      },
      "CatalogEnrichmentMapping": {
        "type": "object",
        "properties": {
          "columnKey": {
            "type": "string",
            "minLength": 1
          },
          "source": {
            "$ref": "#/components/schemas/CatalogEnrichmentSource"
          }
        },
        "required": [
          "columnKey",
          "source"
        ]
      },
      "Completion": {
        "type": "object",
        "properties": {
          "score": {
            "type": "integer",
            "minimum": 0
          },
          "total": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "nextStep": {
            "type": [
              "string",
              "null"
            ]
          },
          "blockingIssues": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                }
              },
              "required": [
                "code",
                "label"
              ]
            }
          }
        },
        "required": [
          "score",
          "total",
          "nextStep",
          "blockingIssues"
        ]
      },
      "CatalogSync": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "provider": {
            "type": "string",
            "enum": [
              "EPRICE",
              "LEROY_MERLIN",
              "MEDIA_MARKT"
            ]
          },
          "apiKeyId": {
            "type": [
              "string",
              "null"
            ]
          },
          "isActive": {
            "type": "boolean"
          },
          "runWithPipeline": {
            "type": "boolean"
          },
          "templateKey": {
            "type": "string"
          },
          "settings": {
            "type": "object",
            "additionalProperties": {}
          },
          "columnMappings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CatalogColumnMapping"
            }
          },
          "enrichmentMappings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CatalogEnrichmentMapping"
            }
          },
          "categoryField": {
            "type": [
              "string",
              "null"
            ]
          },
          "defaultCategoryId": {
            "type": [
              "string",
              "null"
            ]
          },
          "unmappedPolicy": {
            "type": "string",
            "enum": [
              "SKIP",
              "DEFAULT"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "IDLE",
              "BUILDING",
              "UPLOADING",
              "AWAITING_MARKETPLACE",
              "COMPLETED",
              "FAILED"
            ]
          },
          "progress": {
            "type": "integer"
          },
          "lastRunAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "lastImportId": {
            "type": [
              "string",
              "null"
            ]
          },
          "lastStats": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "lastErrorReportKey": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "completion": {
            "$ref": "#/components/schemas/Completion"
          }
        },
        "required": [
          "id",
          "projectId",
          "name",
          "provider",
          "apiKeyId",
          "isActive",
          "runWithPipeline",
          "templateKey",
          "settings",
          "columnMappings",
          "enrichmentMappings",
          "categoryField",
          "defaultCategoryId",
          "unmappedPolicy",
          "status",
          "progress",
          "lastRunAt",
          "lastImportId",
          "lastStats",
          "lastErrorReportKey",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateCatalogSyncBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "provider": {
            "type": "string",
            "enum": [
              "EPRICE",
              "LEROY_MERLIN",
              "MEDIA_MARKT"
            ]
          },
          "templateKey": {
            "type": "string",
            "minLength": 1
          },
          "apiKeyId": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "name",
          "provider",
          "templateKey",
          "apiKeyId"
        ]
      },
      "UpdateCatalogSyncBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "apiKeyId": {
            "type": "string",
            "format": "uuid"
          },
          "isActive": {
            "type": "boolean"
          },
          "runWithPipeline": {
            "type": "boolean"
          },
          "settings": {
            "type": "object",
            "properties": {
              "useStaging": {
                "type": "boolean"
              },
              "enrichment": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "apiKeyId": {
                    "type": "string",
                    "format": "uuid"
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          },
          "categoryField": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1
          },
          "defaultCategoryId": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1
          },
          "unmappedPolicy": {
            "type": "string",
            "enum": [
              "SKIP",
              "DEFAULT"
            ]
          }
        }
      },
      "PutCatalogMappingsBody": {
        "type": "object",
        "properties": {
          "mappings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CatalogColumnMapping"
            }
          }
        },
        "required": [
          "mappings"
        ]
      },
      "PutCatalogEnrichmentMappingsBody": {
        "type": "object",
        "properties": {
          "mappings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CatalogEnrichmentMapping"
            }
          }
        },
        "required": [
          "mappings"
        ]
      },
      "CatalogTemplateColumn": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          },
          "kind": {
            "type": "string",
            "enum": [
              "text",
              "number",
              "category",
              "enum",
              "image"
            ]
          },
          "minLength": {
            "type": "integer"
          },
          "maxLength": {
            "type": "integer"
          },
          "pattern": {
            "type": "string"
          },
          "allowedValues": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "valuesListCode": {
            "type": "string"
          },
          "defaultValue": {
            "type": "string"
          },
          "group": {
            "type": "string"
          },
          "hierarchyCode": {
            "type": "string"
          }
        },
        "required": [
          "key",
          "label",
          "required",
          "kind"
        ]
      },
      "CatalogTemplate": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          },
          "provider": {
            "type": "string",
            "enum": [
              "EPRICE",
              "LEROY_MERLIN",
              "MEDIA_MARKT"
            ]
          },
          "label": {
            "type": "string"
          },
          "version": {
            "type": "integer"
          },
          "externalIdColumnKey": {
            "type": "string"
          },
          "categoryColumnKey": {
            "type": "string"
          },
          "columns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CatalogTemplateColumn"
            }
          },
          "categorySpec": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {
              "type": "object",
              "properties": {
                "applicable": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "required": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              },
              "required": [
                "applicable",
                "required"
              ]
            }
          }
        },
        "required": [
          "key",
          "provider",
          "label",
          "version",
          "externalIdColumnKey",
          "categoryColumnKey",
          "columns"
        ]
      },
      "CatalogCategory": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "path": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "label": {
            "type": "string"
          },
          "logisticClass": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "path",
          "label"
        ]
      },
      "CatalogValueMapping": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "sourceValue": {
            "type": "string"
          },
          "categoryId": {
            "type": [
              "string",
              "null"
            ]
          },
          "categoryPath": {
            "type": [
              "string",
              "null"
            ]
          },
          "occurrences": {
            "type": "integer"
          },
          "suggestedCategoryId": {
            "type": [
              "string",
              "null"
            ]
          },
          "suggestedCategoryPath": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "sourceValue",
          "categoryId",
          "categoryPath",
          "occurrences",
          "suggestedCategoryId",
          "suggestedCategoryPath"
        ]
      },
      "PutCatalogValueMappingsBody": {
        "type": "object",
        "properties": {
          "mappings": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "sourceValue": {
                  "type": "string",
                  "minLength": 1
                },
                "categoryId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "minLength": 1
                }
              },
              "required": [
                "sourceValue",
                "categoryId"
              ]
            },
            "minItems": 1
          }
        },
        "required": [
          "mappings"
        ]
      },
      "CatalogCategorySummary": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "products": {
            "type": "integer",
            "minimum": 0
          },
          "scopedFetched": {
            "type": "boolean"
          },
          "requiredTotal": {
            "type": "integer",
            "minimum": 0
          },
          "requiredMapped": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "code",
          "label",
          "products",
          "scopedFetched",
          "requiredTotal",
          "requiredMapped"
        ]
      },
      "PostCopyValueMappingsBody": {
        "type": "object",
        "properties": {
          "sourceSyncId": {
            "type": "string",
            "minLength": 1
          },
          "overwrite": {
            "type": "boolean",
            "default": false
          }
        },
        "required": [
          "sourceSyncId"
        ]
      },
      "Company": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "timezone": {
            "type": [
              "string",
              "null"
            ]
          },
          "keycloakOrgId": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "timezone",
          "keycloakOrgId",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateCompanyBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 120
          }
        },
        "required": [
          "name"
        ]
      },
      "UpdateCompanyBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "timezone": {
            "type": "string",
            "maxLength": 64
          }
        }
      },
      "AreaPermissions": {
        "type": [
          "object",
          "null"
        ],
        "properties": {
          "feed": {
            "type": "string",
            "enum": [
              "none",
              "read",
              "write"
            ]
          },
          "marketplaces": {
            "type": "string",
            "enum": [
              "none",
              "read",
              "write"
            ]
          },
          "pim": {
            "type": "string",
            "enum": [
              "none",
              "read",
              "write"
            ]
          },
          "oms": {
            "type": "string",
            "enum": [
              "none",
              "read",
              "write"
            ]
          }
        }
      },
      "CompanyMember": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "userId": {
            "type": "string"
          },
          "companyId": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": [
              "OWNER",
              "ADMIN",
              "MEMBER"
            ]
          },
          "notifyByEmail": {
            "type": "boolean"
          },
          "permissions": {
            "$ref": "#/components/schemas/AreaPermissions"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "user": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": "string",
                "format": "email"
              },
              "image": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri"
              }
            },
            "required": [
              "id",
              "name",
              "email",
              "image"
            ]
          }
        },
        "required": [
          "id",
          "userId",
          "companyId",
          "role",
          "notifyByEmail",
          "permissions",
          "createdAt",
          "user"
        ]
      },
      "UpdateMemberBody": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "OWNER",
              "ADMIN",
              "MEMBER"
            ]
          },
          "notifyByEmail": {
            "type": "boolean"
          },
          "permissions": {
            "$ref": "#/components/schemas/AreaPermissions"
          }
        }
      },
      "DeleteResult": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "warning": {
            "type": "string"
          }
        },
        "required": [
          "deleted"
        ]
      },
      "ApiKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "provider": {
            "type": "string",
            "enum": [
              "AMAZON",
              "EBAY",
              "MIRAKL",
              "EPRICE",
              "LEROY_MERLIN",
              "MEDIA_MARKT",
              "WOOCOMMERCE",
              "PRESTASHOP",
              "SHOPIFY",
              "ICECAT",
              "DHL",
              "BRT",
              "UPS",
              "POSTE",
              "GLS",
              "DPD",
              "FEDEX"
            ]
          },
          "name": {
            "type": "string"
          },
          "maskedSellerId": {
            "type": "string"
          },
          "marketplaceCountry": {
            "type": "string"
          },
          "region": {
            "type": "string"
          },
          "useStaging": {
            "type": "boolean"
          },
          "shopName": {
            "type": "string"
          },
          "country": {
            "type": "string",
            "enum": [
              "IT"
            ]
          },
          "shopDomain": {
            "type": "string"
          },
          "baseUrl": {
            "type": "string",
            "format": "uri"
          },
          "sandbox": {
            "type": "boolean"
          },
          "shippedStateId": {
            "type": "string"
          },
          "pendingStateIds": {
            "type": "string"
          },
          "processingStateIds": {
            "type": "string"
          },
          "completedStateIds": {
            "type": "string"
          },
          "cancelledStateIds": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "accountNumber": {
            "type": "string"
          },
          "useTest": {
            "type": "boolean"
          },
          "depotCode": {
            "type": "string"
          },
          "customerCode": {
            "type": "string"
          },
          "contractCode": {
            "type": "string"
          },
          "labelFormat": {
            "type": "string"
          },
          "serviceType": {
            "type": "string"
          },
          "packagingType": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "_count": {
            "type": "object",
            "properties": {
              "imports": {
                "type": "integer",
                "minimum": 0
              },
              "exports": {
                "type": "integer",
                "minimum": 0
              },
              "catalogSyncs": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "imports",
              "exports",
              "catalogSyncs"
            ]
          }
        },
        "required": [
          "id",
          "provider",
          "name",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateApiKeyBody": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "AMAZON"
                ]
              },
              "sellerId": {
                "type": "string",
                "minLength": 1
              },
              "marketplaceCountry": {
                "type": "string",
                "enum": [
                  "IT"
                ]
              },
              "region": {
                "type": "string",
                "enum": [
                  "EU"
                ]
              },
              "lwaClientId": {
                "type": "string",
                "minLength": 1
              },
              "lwaClientSecret": {
                "type": "string",
                "minLength": 1
              },
              "awsAccessKey": {
                "type": "string",
                "minLength": 1
              },
              "awsSecretKey": {
                "type": "string",
                "minLength": 1
              },
              "refreshToken": {
                "type": "string",
                "minLength": 1
              }
            },
            "required": [
              "name",
              "provider",
              "sellerId",
              "marketplaceCountry",
              "region",
              "lwaClientId",
              "lwaClientSecret",
              "awsAccessKey",
              "awsSecretKey",
              "refreshToken"
            ]
          },
          {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "EBAY"
                ]
              },
              "clientId": {
                "type": "string",
                "minLength": 1
              },
              "clientSecret": {
                "type": "string",
                "minLength": 1
              },
              "refreshToken": {
                "type": "string",
                "minLength": 1
              },
              "redirectUriName": {
                "type": "string",
                "minLength": 1
              },
              "accessToken": {
                "type": "string"
              },
              "sandbox": {
                "type": "boolean",
                "default": false
              }
            },
            "required": [
              "name",
              "provider",
              "clientId",
              "clientSecret",
              "refreshToken",
              "redirectUriName"
            ]
          },
          {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "MIRAKL"
                ]
              },
              "baseUrl": {
                "type": "string",
                "format": "uri"
              },
              "apiKey": {
                "type": "string",
                "minLength": 1
              },
              "shopId": {
                "type": "string"
              },
              "shopName": {
                "type": "string"
              }
            },
            "required": [
              "name",
              "provider",
              "baseUrl",
              "apiKey"
            ]
          },
          {
            "type": "object",
            "properties": {
              "apiKey": {
                "type": "string",
                "minLength": 1
              },
              "useStaging": {
                "type": "boolean",
                "default": false
              },
              "shopId": {
                "type": "string"
              },
              "shopName": {
                "type": "string"
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "EPRICE"
                ]
              }
            },
            "required": [
              "apiKey",
              "name",
              "provider"
            ]
          },
          {
            "type": "object",
            "properties": {
              "apiKey": {
                "type": "string",
                "minLength": 1
              },
              "useStaging": {
                "type": "boolean",
                "default": false
              },
              "shopId": {
                "type": "string"
              },
              "shopName": {
                "type": "string"
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "LEROY_MERLIN"
                ]
              }
            },
            "required": [
              "apiKey",
              "name",
              "provider"
            ]
          },
          {
            "type": "object",
            "properties": {
              "apiKey": {
                "type": "string",
                "minLength": 1
              },
              "useStaging": {
                "type": "boolean",
                "default": false
              },
              "shopId": {
                "type": "string"
              },
              "shopName": {
                "type": "string"
              },
              "country": {
                "type": "string",
                "enum": [
                  "IT"
                ],
                "default": "IT"
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "MEDIA_MARKT"
                ]
              }
            },
            "required": [
              "apiKey",
              "name",
              "provider"
            ]
          },
          {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "WOOCOMMERCE"
                ]
              },
              "baseUrl": {
                "type": "string",
                "format": "uri"
              },
              "consumerKey": {
                "type": "string",
                "minLength": 1
              },
              "consumerSecret": {
                "type": "string",
                "minLength": 1
              }
            },
            "required": [
              "name",
              "provider",
              "baseUrl",
              "consumerKey",
              "consumerSecret"
            ]
          },
          {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "PRESTASHOP"
                ]
              },
              "baseUrl": {
                "type": "string",
                "format": "uri"
              },
              "apiKey": {
                "type": "string",
                "minLength": 1
              },
              "shippedStateId": {
                "type": "string",
                "minLength": 1
              },
              "pendingStateIds": {
                "type": "string"
              },
              "processingStateIds": {
                "type": "string"
              },
              "completedStateIds": {
                "type": "string"
              },
              "cancelledStateIds": {
                "type": "string"
              }
            },
            "required": [
              "name",
              "provider",
              "baseUrl",
              "apiKey"
            ]
          },
          {
            "type": "object",
            "properties": {
              "username": {
                "type": "string",
                "minLength": 1
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "ICECAT"
                ]
              }
            },
            "required": [
              "username",
              "name",
              "provider"
            ]
          },
          {
            "type": "object",
            "properties": {
              "apiKey": {
                "type": "string",
                "minLength": 1
              },
              "apiSecret": {
                "type": "string",
                "minLength": 1
              },
              "accountNumber": {
                "type": "string",
                "minLength": 1
              },
              "useTest": {
                "type": "boolean",
                "default": true
              },
              "shipper": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1
                  },
                  "company": {
                    "type": "string"
                  },
                  "street1": {
                    "type": "string",
                    "minLength": 1
                  },
                  "street2": {
                    "type": "string"
                  },
                  "city": {
                    "type": "string",
                    "minLength": 1
                  },
                  "province": {
                    "type": "string"
                  },
                  "zip": {
                    "type": "string",
                    "minLength": 1
                  },
                  "country": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2
                  },
                  "phone": {
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "street1",
                  "city",
                  "zip",
                  "country"
                ]
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "DHL"
                ]
              }
            },
            "required": [
              "apiKey",
              "apiSecret",
              "accountNumber",
              "name",
              "provider"
            ]
          },
          {
            "type": "object",
            "properties": {
              "userID": {
                "type": "string",
                "minLength": 1
              },
              "password": {
                "type": "string",
                "minLength": 1
              },
              "senderCustomerCode": {
                "type": "string",
                "minLength": 1
              },
              "departureDepot": {
                "type": "string",
                "minLength": 1
              },
              "confirmMode": {
                "type": "string",
                "enum": [
                  "AUTO",
                  "EXPLICIT"
                ],
                "default": "AUTO"
              },
              "labelFormat": {
                "type": "string",
                "enum": [
                  "PDF",
                  "ZPL"
                ],
                "default": "PDF"
              },
              "deliveryFreightTypeCode": {
                "type": "string",
                "enum": [
                  "DAP",
                  "EXW"
                ],
                "default": "DAP"
              },
              "sender": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "company": {
                    "type": "string"
                  },
                  "street1": {
                    "type": "string"
                  },
                  "street2": {
                    "type": "string"
                  },
                  "city": {
                    "type": "string"
                  },
                  "province": {
                    "type": "string"
                  },
                  "zip": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2
                  },
                  "phone": {
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "street1",
                  "city",
                  "zip",
                  "country"
                ]
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "BRT"
                ]
              }
            },
            "required": [
              "userID",
              "password",
              "senderCustomerCode",
              "departureDepot",
              "name",
              "provider"
            ]
          },
          {
            "type": "object",
            "properties": {
              "clientId": {
                "type": "string",
                "minLength": 1
              },
              "clientSecret": {
                "type": "string",
                "minLength": 1
              },
              "shipperNumber": {
                "type": "string",
                "minLength": 1
              },
              "useTest": {
                "type": "boolean",
                "default": true
              },
              "labelFormat": {
                "type": "string",
                "enum": [
                  "GIF",
                  "ZPL",
                  "EPL",
                  "SPL"
                ],
                "default": "GIF"
              },
              "serviceCode": {
                "type": "string",
                "default": "11"
              },
              "negotiatedRates": {
                "type": "boolean",
                "default": false
              },
              "sender": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "company": {
                    "type": "string"
                  },
                  "street1": {
                    "type": "string"
                  },
                  "street2": {
                    "type": "string"
                  },
                  "city": {
                    "type": "string"
                  },
                  "province": {
                    "type": "string"
                  },
                  "zip": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2
                  },
                  "phone": {
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "street1",
                  "city",
                  "zip",
                  "country"
                ]
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "UPS"
                ]
              }
            },
            "required": [
              "clientId",
              "clientSecret",
              "shipperNumber",
              "name",
              "provider"
            ]
          },
          {
            "type": "object",
            "properties": {
              "clientId": {
                "type": "string",
                "minLength": 1
              },
              "secretId": {
                "type": "string",
                "minLength": 1
              },
              "costCenterCode": {
                "type": "string",
                "minLength": 1
              },
              "useTest": {
                "type": "boolean",
                "default": true
              },
              "printFormat": {
                "type": "string",
                "enum": [
                  "A4",
                  "1011",
                  "ZPL"
                ],
                "default": "A4"
              },
              "product": {
                "type": "string",
                "default": "APT000902"
              },
              "sender": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "company": {
                    "type": "string"
                  },
                  "street1": {
                    "type": "string"
                  },
                  "street2": {
                    "type": "string"
                  },
                  "city": {
                    "type": "string"
                  },
                  "province": {
                    "type": "string"
                  },
                  "zip": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2
                  },
                  "phone": {
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "street1",
                  "city",
                  "zip",
                  "country"
                ]
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "POSTE"
                ]
              }
            },
            "required": [
              "clientId",
              "secretId",
              "costCenterCode",
              "name",
              "provider"
            ]
          },
          {
            "type": "object",
            "properties": {
              "depotCode": {
                "type": "string",
                "minLength": 1,
                "maxLength": 10
              },
              "customerCode": {
                "type": "string",
                "maxLength": 6,
                "pattern": "^\\d+$"
              },
              "password": {
                "type": "string",
                "minLength": 1
              },
              "contractCode": {
                "type": "string",
                "maxLength": 9,
                "pattern": "^\\d+$"
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "GLS"
                ]
              }
            },
            "required": [
              "depotCode",
              "customerCode",
              "password",
              "contractCode",
              "name",
              "provider"
            ]
          },
          {
            "type": "object",
            "properties": {
              "clientId": {
                "type": "string",
                "minLength": 1
              },
              "clientSecret": {
                "type": "string",
                "minLength": 1
              },
              "accountNumber": {
                "type": "string",
                "minLength": 1
              },
              "useTest": {
                "type": "boolean",
                "default": true
              },
              "labelFormat": {
                "type": "string",
                "enum": [
                  "PDF",
                  "PNG",
                  "ZPLII"
                ],
                "default": "PDF"
              },
              "serviceType": {
                "type": "string",
                "minLength": 1,
                "default": "FEDEX_PRIORITY"
              },
              "packagingType": {
                "type": "string",
                "minLength": 1,
                "default": "YOUR_PACKAGING"
              },
              "sender": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1
                  },
                  "company": {
                    "type": "string"
                  },
                  "street1": {
                    "type": "string",
                    "minLength": 1
                  },
                  "street2": {
                    "type": "string"
                  },
                  "city": {
                    "type": "string",
                    "minLength": 1
                  },
                  "province": {
                    "type": "string"
                  },
                  "zip": {
                    "type": "string",
                    "minLength": 1
                  },
                  "country": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2
                  },
                  "phone": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                },
                "required": [
                  "name",
                  "street1",
                  "city",
                  "zip",
                  "country"
                ]
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "provider": {
                "type": "string",
                "enum": [
                  "FEDEX"
                ]
              }
            },
            "required": [
              "clientId",
              "clientSecret",
              "accountNumber",
              "sender",
              "name",
              "provider"
            ]
          }
        ]
      },
      "ShopifyOAuthStartResult": {
        "type": "object",
        "properties": {
          "authorizeUrl": {
            "type": "string",
            "format": "uri"
          },
          "redirectUri": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "authorizeUrl",
          "redirectUri"
        ]
      },
      "ShopifyOAuthStartBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "shopDomain": {
            "type": "string",
            "minLength": 1
          },
          "clientId": {
            "type": "string",
            "minLength": 1
          },
          "clientSecret": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "name",
          "shopDomain",
          "clientId",
          "clientSecret"
        ]
      },
      "UpdateApiKeyBody": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "AMAZON",
              "EBAY",
              "MIRAKL",
              "EPRICE",
              "LEROY_MERLIN",
              "MEDIA_MARKT",
              "WOOCOMMERCE",
              "PRESTASHOP",
              "SHOPIFY",
              "ICECAT",
              "DHL",
              "BRT",
              "UPS",
              "POSTE",
              "GLS",
              "DPD",
              "FEDEX"
            ]
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "apiKey": {
            "type": "string"
          },
          "useStaging": {
            "type": "boolean"
          },
          "shopId": {
            "type": "string"
          },
          "shopName": {
            "type": "string"
          },
          "country": {
            "type": "string",
            "enum": [
              "IT"
            ]
          },
          "sellerId": {
            "type": "string"
          },
          "marketplaceCountry": {
            "type": "string",
            "enum": [
              "IT"
            ]
          },
          "region": {
            "type": "string",
            "enum": [
              "EU"
            ]
          },
          "lwaClientId": {
            "type": "string"
          },
          "lwaClientSecret": {
            "type": "string"
          },
          "awsAccessKey": {
            "type": "string"
          },
          "awsSecretKey": {
            "type": "string"
          },
          "refreshToken": {
            "type": "string"
          },
          "clientId": {
            "type": "string"
          },
          "clientSecret": {
            "type": "string"
          },
          "redirectUriName": {
            "type": "string"
          },
          "accessToken": {
            "type": "string"
          },
          "sandbox": {
            "type": "boolean"
          },
          "baseUrl": {
            "type": "string",
            "format": "uri"
          },
          "consumerKey": {
            "type": "string"
          },
          "consumerSecret": {
            "type": "string"
          },
          "shippedStateId": {
            "type": "string"
          },
          "pendingStateIds": {
            "type": "string"
          },
          "processingStateIds": {
            "type": "string"
          },
          "completedStateIds": {
            "type": "string"
          },
          "cancelledStateIds": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "apiSecret": {
            "type": "string"
          },
          "accountNumber": {
            "type": "string"
          },
          "useTest": {
            "type": "boolean"
          },
          "shipper": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1
              },
              "company": {
                "type": "string"
              },
              "street1": {
                "type": "string",
                "minLength": 1
              },
              "street2": {
                "type": "string"
              },
              "city": {
                "type": "string",
                "minLength": 1
              },
              "province": {
                "type": "string"
              },
              "zip": {
                "type": "string",
                "minLength": 1
              },
              "country": {
                "type": "string",
                "minLength": 2,
                "maxLength": 2
              },
              "phone": {
                "type": "string"
              }
            },
            "required": [
              "name",
              "street1",
              "city",
              "zip",
              "country"
            ]
          },
          "depotCode": {
            "type": "string"
          },
          "customerCode": {
            "type": "string"
          },
          "contractCode": {
            "type": "string"
          },
          "password": {
            "type": "string"
          },
          "labelFormat": {
            "type": "string",
            "enum": [
              "PDF",
              "ZPL",
              "GIF",
              "PNG",
              "ZPLII"
            ]
          },
          "serviceType": {
            "type": "string"
          },
          "packagingType": {
            "type": "string"
          },
          "sender": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1
              },
              "company": {
                "type": "string"
              },
              "street1": {
                "type": "string",
                "minLength": 1
              },
              "street2": {
                "type": "string"
              },
              "city": {
                "type": "string",
                "minLength": 1
              },
              "province": {
                "type": "string"
              },
              "zip": {
                "type": "string",
                "minLength": 1
              },
              "country": {
                "type": "string",
                "minLength": 2,
                "maxLength": 2
              },
              "phone": {
                "type": "string"
              },
              "email": {
                "type": "string",
                "format": "email"
              }
            },
            "required": [
              "name",
              "street1",
              "city",
              "zip",
              "country"
            ]
          }
        }
      },
      "ApiKeyTestResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "success"
        ]
      },
      "Export": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "isActive": {
            "type": "boolean"
          },
          "typeFeed": {
            "type": "string",
            "enum": [
              "CSV",
              "JSON",
              "XML",
              "AMAZON",
              "EPRICE",
              "LEROY_MERLIN",
              "MEDIA_MARKT"
            ]
          },
          "typeProtocol": {
            "type": "string",
            "enum": [
              "HTTP",
              "HTTPS",
              "FTP",
              "SFTP",
              "DOWNLOAD"
            ]
          },
          "hostAddress": {
            "type": [
              "string",
              "null"
            ]
          },
          "username": {
            "type": [
              "string",
              "null"
            ]
          },
          "fieldSeparator": {
            "type": "string"
          },
          "encoding": {
            "type": "string"
          },
          "wrapper": {
            "type": [
              "string",
              "null"
            ]
          },
          "object": {
            "type": [
              "string",
              "null"
            ]
          },
          "apiKeyId": {
            "type": [
              "string",
              "null"
            ]
          },
          "amazonSettings": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "epriceSettings": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "leroyMerlinSettings": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "mediaMarktSettings": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "status": {
            "type": "string",
            "enum": [
              "IDLE",
              "GENERATING",
              "UPLOADING",
              "AWAITING_MARKETPLACE",
              "COMPLETED",
              "FAILED"
            ]
          },
          "progress": {
            "type": [
              "integer",
              "null"
            ]
          },
          "lastImportId": {
            "type": [
              "string",
              "null"
            ]
          },
          "lastStats": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "lastError": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "feedUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "_count": {
            "type": "object",
            "properties": {
              "mappings": {
                "type": "integer"
              }
            },
            "required": [
              "mappings"
            ]
          },
          "completion": {
            "$ref": "#/components/schemas/Completion"
          }
        },
        "required": [
          "id",
          "name",
          "projectId",
          "isActive",
          "typeFeed",
          "typeProtocol",
          "hostAddress",
          "username",
          "fieldSeparator",
          "encoding",
          "wrapper",
          "object",
          "apiKeyId",
          "status",
          "progress",
          "createdAt",
          "updatedAt"
        ]
      },
      "ExportCreatedResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Export"
          },
          "rawToken": {
            "type": "string",
            "description": "Token in chiaro mostrato UNA SOLA volta alla creazione. Va salvato dal client per costruire il link feedUrl. Non viene mai più restituito."
          }
        },
        "required": [
          "data",
          "rawToken"
        ]
      },
      "CreateExportBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "typeFeed": {
            "type": "string",
            "enum": [
              "CSV",
              "JSON",
              "XML",
              "AMAZON",
              "EPRICE",
              "LEROY_MERLIN",
              "MEDIA_MARKT"
            ]
          },
          "typeProtocol": {
            "type": "string",
            "enum": [
              "HTTP",
              "HTTPS",
              "FTP",
              "SFTP",
              "DOWNLOAD"
            ]
          },
          "hostAddress": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "password": {
            "type": "string"
          },
          "fieldSeparator": {
            "type": "string"
          },
          "encoding": {
            "type": "string"
          },
          "wrapper": {
            "type": "string"
          },
          "object": {
            "type": "string"
          },
          "apiKeyId": {
            "type": "string"
          },
          "amazonSettings": {
            "type": "object",
            "additionalProperties": {}
          },
          "epriceSettings": {
            "type": "object",
            "properties": {
              "useStaging": {
                "type": "boolean"
              },
              "fulfillmentLatency": {
                "type": "integer",
                "minimum": 1,
                "maximum": 30,
                "default": 1
              },
              "state": {
                "anyOf": [
                  {
                    "type": "number",
                    "enum": [
                      11
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      4
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      3
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      2
                    ]
                  }
                ],
                "default": 11
              },
              "productIdType": {
                "type": "string",
                "enum": [
                  "EAN",
                  "UPC",
                  "GTIN",
                  "ISBN",
                  "SHOP_SKU"
                ],
                "default": "EAN"
              },
              "skipDelete": {
                "type": "boolean",
                "default": true
              },
              "replaceAll": {
                "type": "boolean",
                "default": false
              },
              "logisticClass": {
                "type": "string",
                "enum": [
                  "U",
                  "E",
                  "P"
                ],
                "default": "U"
              }
            }
          },
          "leroyMerlinSettings": {
            "type": "object",
            "properties": {
              "useStaging": {
                "type": "boolean"
              },
              "fulfillmentLatency": {
                "type": "integer",
                "minimum": 1,
                "maximum": 30,
                "default": 1
              },
              "state": {
                "anyOf": [
                  {
                    "type": "number",
                    "enum": [
                      11
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      4
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      3
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      2
                    ]
                  }
                ],
                "default": 11
              },
              "productIdType": {
                "type": "string",
                "enum": [
                  "EAN",
                  "UPC",
                  "GTIN",
                  "ISBN",
                  "SHOP_SKU"
                ],
                "default": "EAN"
              },
              "skipDelete": {
                "type": "boolean",
                "default": true
              },
              "replaceAll": {
                "type": "boolean",
                "default": false
              }
            }
          },
          "mediaMarktSettings": {
            "type": "object",
            "properties": {
              "useStaging": {
                "type": "boolean"
              },
              "fulfillmentLatency": {
                "type": "integer",
                "minimum": 1,
                "maximum": 30,
                "default": 1
              },
              "state": {
                "anyOf": [
                  {
                    "type": "number",
                    "enum": [
                      11
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      4
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      3
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      2
                    ]
                  }
                ],
                "default": 11
              },
              "productIdType": {
                "type": "string",
                "enum": [
                  "EAN",
                  "UPC",
                  "GTIN",
                  "ISBN",
                  "SHOP_SKU"
                ],
                "default": "EAN"
              },
              "skipDelete": {
                "type": "boolean",
                "default": true
              },
              "replaceAll": {
                "type": "boolean",
                "default": false
              },
              "country": {
                "type": "string",
                "enum": [
                  "IT",
                  "DE",
                  "ES",
                  "NL",
                  "AT"
                ],
                "default": "IT"
              }
            }
          }
        },
        "required": [
          "name",
          "typeFeed",
          "typeProtocol"
        ],
        "description": "Per typeFeed marketplace (AMAZON|EPRICE|LEROY_MERLIN|MEDIA_MARKT): typeProtocol viene forzato a DOWNLOAD, apiKeyId obbligatorio. AMAZON richiede amazonSettings; le altre accettano *Settings opzionale (default {}). Per protocolli != DOWNLOAD: hostAddress obbligatorio e deve essere URL valida."
      },
      "UpdateExportBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "typeFeed": {
            "type": "string",
            "enum": [
              "CSV",
              "JSON",
              "XML",
              "AMAZON",
              "EPRICE",
              "LEROY_MERLIN",
              "MEDIA_MARKT"
            ]
          },
          "typeProtocol": {
            "type": "string",
            "enum": [
              "HTTP",
              "HTTPS",
              "FTP",
              "SFTP",
              "DOWNLOAD"
            ]
          },
          "hostAddress": {
            "type": "string",
            "format": "uri"
          },
          "username": {
            "type": "string"
          },
          "password": {
            "type": "string"
          },
          "isActive": {
            "type": "boolean"
          },
          "fieldSeparator": {
            "type": "string"
          },
          "encoding": {
            "type": "string"
          },
          "wrapper": {
            "type": "string"
          },
          "object": {
            "type": "string"
          },
          "apiKeyId": {
            "type": "string"
          },
          "amazonSettings": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "epriceSettings": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "useStaging": {
                "type": "boolean"
              },
              "fulfillmentLatency": {
                "type": "integer",
                "minimum": 1,
                "maximum": 30,
                "default": 1
              },
              "state": {
                "anyOf": [
                  {
                    "type": "number",
                    "enum": [
                      11
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      4
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      3
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      2
                    ]
                  }
                ],
                "default": 11
              },
              "productIdType": {
                "type": "string",
                "enum": [
                  "EAN",
                  "UPC",
                  "GTIN",
                  "ISBN",
                  "SHOP_SKU"
                ],
                "default": "EAN"
              },
              "skipDelete": {
                "type": "boolean",
                "default": true
              },
              "replaceAll": {
                "type": "boolean",
                "default": false
              },
              "logisticClass": {
                "type": "string",
                "enum": [
                  "U",
                  "E",
                  "P"
                ],
                "default": "U"
              }
            }
          },
          "leroyMerlinSettings": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "useStaging": {
                "type": "boolean"
              },
              "fulfillmentLatency": {
                "type": "integer",
                "minimum": 1,
                "maximum": 30,
                "default": 1
              },
              "state": {
                "anyOf": [
                  {
                    "type": "number",
                    "enum": [
                      11
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      4
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      3
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      2
                    ]
                  }
                ],
                "default": 11
              },
              "productIdType": {
                "type": "string",
                "enum": [
                  "EAN",
                  "UPC",
                  "GTIN",
                  "ISBN",
                  "SHOP_SKU"
                ],
                "default": "EAN"
              },
              "skipDelete": {
                "type": "boolean",
                "default": true
              },
              "replaceAll": {
                "type": "boolean",
                "default": false
              }
            }
          },
          "mediaMarktSettings": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "useStaging": {
                "type": "boolean"
              },
              "fulfillmentLatency": {
                "type": "integer",
                "minimum": 1,
                "maximum": 30,
                "default": 1
              },
              "state": {
                "anyOf": [
                  {
                    "type": "number",
                    "enum": [
                      11
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      4
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      3
                    ]
                  },
                  {
                    "type": "number",
                    "enum": [
                      2
                    ]
                  }
                ],
                "default": 11
              },
              "productIdType": {
                "type": "string",
                "enum": [
                  "EAN",
                  "UPC",
                  "GTIN",
                  "ISBN",
                  "SHOP_SKU"
                ],
                "default": "EAN"
              },
              "skipDelete": {
                "type": "boolean",
                "default": true
              },
              "replaceAll": {
                "type": "boolean",
                "default": false
              },
              "country": {
                "type": "string",
                "enum": [
                  "IT",
                  "DE",
                  "ES",
                  "NL",
                  "AT"
                ],
                "default": "IT"
              }
            }
          }
        }
      },
      "ExportMapping": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "exportId": {
            "type": "string"
          },
          "nameField": {
            "type": "string"
          },
          "nameColumn": {
            "type": "string"
          },
          "isRequired": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "exportId",
          "nameField",
          "nameColumn",
          "isRequired"
        ]
      },
      "PutExportMappingsBody": {
        "type": "object",
        "properties": {
          "mappings": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "nameField": {
                  "type": "string",
                  "minLength": 1
                },
                "nameColumn": {
                  "type": "string",
                  "minLength": 1
                },
                "isRequired": {
                  "type": "boolean"
                }
              },
              "required": [
                "nameField",
                "nameColumn"
              ]
            }
          }
        },
        "required": [
          "mappings"
        ]
      },
      "ExportRuleExclusions": {
        "type": "object",
        "properties": {
          "excludedRuleIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "required": [
          "excludedRuleIds"
        ]
      },
      "ExportRuleExclusionsResult": {
        "type": "object",
        "properties": {
          "excludedRuleIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "added": {
            "type": "integer",
            "minimum": 0
          },
          "removed": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "excludedRuleIds",
          "added",
          "removed"
        ]
      },
      "PutExportRuleExclusionsBody": {
        "type": "object",
        "properties": {
          "excludedRuleIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "required": [
          "excludedRuleIds"
        ]
      },
      "ExportRunResult": {
        "type": "object",
        "properties": {
          "pipelineRunId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING"
            ]
          }
        },
        "required": [
          "pipelineRunId",
          "status"
        ]
      },
      "Import": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "isActive": {
            "type": "boolean"
          },
          "typeFeed": {
            "type": "string",
            "enum": [
              "CSV",
              "JSON",
              "XML"
            ]
          },
          "typeProtocol": {
            "type": "string",
            "enum": [
              "HTTP",
              "HTTPS",
              "FTP",
              "SFTP"
            ]
          },
          "hostAddress": {
            "type": "string"
          },
          "username": {
            "type": [
              "string",
              "null"
            ]
          },
          "fieldSeparator": {
            "type": "string"
          },
          "encoding": {
            "type": "string"
          },
          "quoting": {
            "type": "string"
          },
          "headerLine": {
            "type": "integer"
          },
          "apiKeyId": {
            "type": [
              "string",
              "null"
            ]
          },
          "amazonSettings": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "shopifySettings": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "marketplaceSettings": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "sourceCheckpoint": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "apiSettings": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "mergeKeyField": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "IDLE",
              "FETCHING",
              "PARSING",
              "COMPLETED",
              "FAILED"
            ]
          },
          "progress": {
            "type": [
              "integer",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "_count": {
            "type": "object",
            "properties": {
              "mappings": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "mappings"
            ]
          },
          "completion": {
            "$ref": "#/components/schemas/Completion"
          }
        },
        "required": [
          "id",
          "name",
          "projectId",
          "isActive",
          "typeFeed",
          "typeProtocol",
          "hostAddress",
          "username",
          "fieldSeparator",
          "encoding",
          "quoting",
          "headerLine",
          "apiKeyId",
          "mergeKeyField",
          "status",
          "progress",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateImportBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "typeFeed": {
            "type": "string",
            "enum": [
              "CSV",
              "JSON",
              "XML"
            ]
          },
          "typeProtocol": {
            "type": "string",
            "enum": [
              "HTTP",
              "HTTPS",
              "FTP",
              "SFTP"
            ]
          },
          "hostAddress": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "password": {
            "type": "string"
          },
          "fieldSeparator": {
            "type": "string"
          },
          "encoding": {
            "type": "string"
          },
          "quoting": {
            "type": "string"
          },
          "headerLine": {
            "type": "integer",
            "minimum": 1
          },
          "apiKeyId": {
            "type": "string"
          },
          "amazonSettings": {
            "type": "object",
            "additionalProperties": {}
          },
          "shopifySettings": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "ACTIVE",
                  "ANY"
                ],
                "default": "ACTIVE"
              }
            }
          },
          "marketplaceSettings": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "schemaVersion": {
                    "type": "number",
                    "enum": [
                      1
                    ],
                    "default": 1
                  },
                  "provider": {
                    "type": "string",
                    "enum": [
                      "PRESTASHOP"
                    ]
                  },
                  "syncMode": {
                    "type": "string",
                    "enum": [
                      "FULL"
                    ],
                    "default": "FULL"
                  },
                  "market": {
                    "type": "string",
                    "enum": [
                      "IT"
                    ],
                    "default": "IT"
                  },
                  "shopId": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  },
                  "shopGroupId": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  },
                  "primaryLanguageId": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  },
                  "primaryLanguageIso": {
                    "type": "string",
                    "enum": [
                      "it"
                    ],
                    "default": "it"
                  },
                  "includeInactive": {
                    "type": "boolean",
                    "default": false
                  },
                  "includeTranslations": {
                    "type": "boolean",
                    "default": false
                  }
                },
                "required": [
                  "provider",
                  "shopId",
                  "primaryLanguageId"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "WOOCOMMERCE"
                    ],
                    "default": "WOOCOMMERCE"
                  },
                  "syncMode": {
                    "type": "string",
                    "enum": [
                      "FULL"
                    ],
                    "default": "FULL"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "ALL",
                      "PUBLISH"
                    ],
                    "default": "ALL"
                  }
                },
                "additionalProperties": false
              }
            ]
          },
          "apiSettings": {
            "type": "object",
            "additionalProperties": {}
          },
          "apiAuth": {
            "type": "object",
            "additionalProperties": {}
          },
          "mergeKeyField": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z0-9_]+$"
          }
        },
        "required": [
          "name"
        ],
        "description": "Marketplace import (apiKeyId + impostazioni provider): host/protocol vengono forzati server-side. Per import classici: typeFeed + typeProtocol + hostAddress sono obbligatori e hostAddress deve essere una URL valida."
      },
      "UpdateImportBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "typeFeed": {
            "type": "string",
            "enum": [
              "CSV",
              "JSON",
              "XML"
            ]
          },
          "typeProtocol": {
            "type": "string",
            "enum": [
              "HTTP",
              "HTTPS",
              "FTP",
              "SFTP"
            ]
          },
          "hostAddress": {
            "type": "string",
            "format": "uri"
          },
          "username": {
            "type": "string"
          },
          "password": {
            "type": "string"
          },
          "isActive": {
            "type": "boolean"
          },
          "fieldSeparator": {
            "type": "string"
          },
          "encoding": {
            "type": "string"
          },
          "quoting": {
            "type": "string"
          },
          "headerLine": {
            "type": "integer",
            "minimum": 1
          },
          "apiKeyId": {
            "type": "string"
          },
          "amazonSettings": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "shopifySettings": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "ACTIVE",
                  "ANY"
                ],
                "default": "ACTIVE"
              }
            }
          },
          "marketplaceSettings": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "schemaVersion": {
                    "type": "number",
                    "enum": [
                      1
                    ],
                    "default": 1
                  },
                  "provider": {
                    "type": "string",
                    "enum": [
                      "PRESTASHOP"
                    ]
                  },
                  "syncMode": {
                    "type": "string",
                    "enum": [
                      "FULL"
                    ],
                    "default": "FULL"
                  },
                  "market": {
                    "type": "string",
                    "enum": [
                      "IT"
                    ],
                    "default": "IT"
                  },
                  "shopId": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  },
                  "shopGroupId": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  },
                  "primaryLanguageId": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  },
                  "primaryLanguageIso": {
                    "type": "string",
                    "enum": [
                      "it"
                    ],
                    "default": "it"
                  },
                  "includeInactive": {
                    "type": "boolean",
                    "default": false
                  },
                  "includeTranslations": {
                    "type": "boolean",
                    "default": false
                  }
                },
                "required": [
                  "provider",
                  "shopId",
                  "primaryLanguageId"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "WOOCOMMERCE"
                    ],
                    "default": "WOOCOMMERCE"
                  },
                  "syncMode": {
                    "type": "string",
                    "enum": [
                      "FULL"
                    ],
                    "default": "FULL"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "ALL",
                      "PUBLISH"
                    ],
                    "default": "ALL"
                  }
                },
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          },
          "apiSettings": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "apiAuth": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "mergeKeyField": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z0-9_]+$"
          }
        }
      },
      "ImportColumnsResult": {
        "type": "object",
        "properties": {
          "columns": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "columns"
        ]
      },
      "ImportMapping": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "importId": {
            "type": "string"
          },
          "nameField": {
            "type": "string"
          },
          "nameColumn": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "importId",
          "nameField",
          "nameColumn"
        ]
      },
      "PutImportMappingsBody": {
        "type": "object",
        "properties": {
          "mappings": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "nameField": {
                  "type": "string",
                  "minLength": 1
                },
                "nameColumn": {
                  "type": "string",
                  "minLength": 1
                }
              },
              "required": [
                "nameField",
                "nameColumn"
              ]
            }
          }
        },
        "required": [
          "mappings"
        ]
      },
      "ImportRunResult": {
        "type": "object",
        "properties": {
          "pipelineRunId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING"
            ]
          }
        },
        "required": [
          "pipelineRunId",
          "status"
        ]
      },
      "ImportTestResult": {
        "type": "object",
        "properties": {
          "filename": {
            "type": "string"
          },
          "lines": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "lineCount": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "filename",
          "lines",
          "lineCount"
        ]
      },
      "Invitation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "companyId": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": [
              "ADMIN",
              "MEMBER"
            ]
          },
          "token": {
            "type": "string"
          },
          "invitedById": {
            "type": "string"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "acceptedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "emailSentAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "invitedBy": {
            "type": "object",
            "properties": {
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": "string",
                "format": "email"
              }
            },
            "required": [
              "name",
              "email"
            ]
          }
        },
        "required": [
          "id",
          "email",
          "companyId",
          "role",
          "token",
          "invitedById",
          "expiresAt",
          "acceptedAt",
          "emailSentAt",
          "createdAt"
        ]
      },
      "InvitationCreated": {
        "type": "object",
        "properties": {
          "invitation": {
            "$ref": "#/components/schemas/Invitation"
          },
          "inviteUrl": {
            "type": "string",
            "format": "uri"
          },
          "emailSent": {
            "type": "boolean"
          }
        },
        "required": [
          "invitation",
          "inviteUrl",
          "emailSent"
        ]
      },
      "CreateInvitationBody": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "pattern": "^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$"
          },
          "role": {
            "type": "string",
            "enum": [
              "ADMIN",
              "MEMBER"
            ],
            "default": "MEMBER"
          }
        },
        "required": [
          "email"
        ]
      },
      "AcceptInvitationResult": {
        "type": "object",
        "properties": {
          "company": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ]
          },
          "role": {
            "type": "string",
            "enum": [
              "OWNER",
              "ADMIN",
              "MEMBER"
            ]
          }
        },
        "required": [
          "company",
          "role"
        ]
      },
      "AcceptInvitationBody": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "token"
        ]
      },
      "RunPipelineResult": {
        "type": "object",
        "properties": {
          "pipelineRunId": {
            "type": "string"
          },
          "queuedJobs": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "pipelineRunId"
        ]
      },
      "RunPipelineBody": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "IMPORT",
              "EXPORT",
              "BOTH"
            ]
          }
        },
        "description": "Tipo di run da lanciare. Default: BOTH (import + export + rules in sequenza completa)."
      },
      "PipelineRun": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "RUNNING",
              "COMPLETED",
              "FAILED",
              "CANCELLED"
            ]
          },
          "type": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "IMPORT",
              "EXPORT",
              "BOTH"
            ]
          },
          "startedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "stats": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "status",
          "startedAt",
          "completedAt",
          "createdAt"
        ]
      },
      "PipelineRunsListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PipelineRun"
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer",
                "minimum": 0
              },
              "page": {
                "type": "integer",
                "minimum": 1
              },
              "limit": {
                "type": "integer",
                "minimum": 1
              }
            },
            "required": [
              "total",
              "page",
              "limit"
            ]
          }
        },
        "required": [
          "data",
          "meta"
        ]
      },
      "PipelineLog": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "step": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "FETCH",
              "PARSE",
              "MERGE",
              "RULES",
              "EXPORT"
            ]
          },
          "level": {
            "type": "string",
            "enum": [
              "INFO",
              "WARN",
              "ERROR",
              "DEBUG"
            ]
          },
          "message": {
            "type": "string"
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {}
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "step",
          "level",
          "message",
          "createdAt"
        ]
      },
      "PipelineRunWithLogs": {
        "allOf": [
          {
            "$ref": "#/components/schemas/PipelineRun"
          },
          {
            "type": "object",
            "properties": {
              "logs": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PipelineLog"
                }
              }
            },
            "required": [
              "logs"
            ]
          }
        ]
      },
      "Schedule": {
        "type": [
          "object",
          "null"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "timeSlots": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "executionType": {
            "type": "string",
            "enum": [
              "IMPORT",
              "EXPORT",
              "BOTH"
            ]
          },
          "isStarted": {
            "type": "boolean"
          },
          "monday": {
            "type": "boolean"
          },
          "tuesday": {
            "type": "boolean"
          },
          "wednesday": {
            "type": "boolean"
          },
          "thursday": {
            "type": "boolean"
          },
          "friday": {
            "type": "boolean"
          },
          "saturday": {
            "type": "boolean"
          },
          "sunday": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "projectId",
          "timeSlots",
          "executionType",
          "isStarted",
          "monday",
          "tuesday",
          "wednesday",
          "thursday",
          "friday",
          "saturday",
          "sunday",
          "createdAt",
          "updatedAt"
        ]
      },
      "ScheduleResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Schedule"
          },
          "timezone": {
            "type": "string"
          }
        },
        "required": [
          "data",
          "timezone"
        ]
      },
      "UpdateScheduleBody": {
        "type": "object",
        "properties": {
          "timeSlots": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
            },
            "minItems": 1,
            "maxItems": 24
          },
          "executionType": {
            "type": "string",
            "enum": [
              "IMPORT",
              "EXPORT",
              "BOTH"
            ]
          },
          "isStarted": {
            "type": "boolean"
          },
          "monday": {
            "type": "boolean"
          },
          "tuesday": {
            "type": "boolean"
          },
          "wednesday": {
            "type": "boolean"
          },
          "thursday": {
            "type": "boolean"
          },
          "friday": {
            "type": "boolean"
          },
          "saturday": {
            "type": "boolean"
          },
          "sunday": {
            "type": "boolean"
          }
        },
        "required": [
          "timeSlots",
          "executionType"
        ]
      },
      "Project": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "companyId": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "_count": {
            "type": "object",
            "properties": {
              "fields": {
                "type": "integer",
                "minimum": 0
              },
              "imports": {
                "type": "integer",
                "minimum": 0
              },
              "exports": {
                "type": "integer",
                "minimum": 0
              },
              "runs": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        },
        "required": [
          "id",
          "name",
          "companyId",
          "createdAt",
          "updatedAt"
        ]
      },
      "DatabaseField": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "field": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "order": {
            "type": "integer"
          },
          "isVisible": {
            "type": "boolean"
          },
          "role": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "ean",
              "sku",
              "brand",
              "mpn",
              "title",
              "description",
              "image",
              "price",
              "quantity",
              "category",
              "weight",
              "volume"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "field",
          "projectId",
          "order",
          "isVisible",
          "role"
        ]
      },
      "ProjectWithFields": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Project"
          },
          {
            "type": "object",
            "properties": {
              "fields": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/DatabaseField"
                }
              }
            }
          }
        ]
      },
      "CreateProjectBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            },
            "maxItems": 200
          }
        },
        "required": [
          "name"
        ]
      },
      "UpdateProjectBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          }
        },
        "required": [
          "name"
        ]
      },
      "CreateFieldBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          }
        },
        "required": [
          "name"
        ]
      },
      "UpdateFieldBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "isVisible": {
            "type": "boolean"
          },
          "role": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "ean",
              "sku",
              "brand",
              "mpn",
              "title",
              "description",
              "image",
              "price",
              "quantity",
              "category",
              "weight",
              "volume"
            ]
          }
        }
      },
      "ReorderFieldsBody": {
        "type": "object",
        "properties": {
          "fieldIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1
          }
        },
        "required": [
          "fieldIds"
        ]
      },
      "ColumnQuality": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          },
          "role": {
            "type": [
              "string",
              "null"
            ]
          },
          "filled": {
            "type": "integer",
            "minimum": 0
          },
          "distinct": {
            "type": "integer",
            "minimum": 0
          },
          "enriched": {
            "type": "integer",
            "minimum": 0
          },
          "issues": {
            "type": "object",
            "properties": {
              "invalidGtin": {
                "type": "integer"
              },
              "duplicates": {
                "type": "integer"
              },
              "nonNumeric": {
                "type": "integer"
              },
              "zero": {
                "type": "integer"
              },
              "notUrl": {
                "type": "integer"
              },
              "tooShort": {
                "type": "integer"
              }
            }
          },
          "recoverable": {
            "type": "integer"
          }
        },
        "required": [
          "slug",
          "role",
          "filled",
          "distinct",
          "enriched"
        ]
      },
      "IcecatCoverage": {
        "type": "object",
        "properties": {
          "hit": {
            "type": "integer",
            "minimum": 0
          },
          "notFound": {
            "type": "integer",
            "minimum": 0
          },
          "notCovered": {
            "type": "integer",
            "minimum": 0
          },
          "unknown": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "hit",
          "notFound",
          "notCovered",
          "unknown"
        ]
      },
      "DataQuality": {
        "type": "object",
        "properties": {
          "stats": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "totalRows": {
                "type": "integer",
                "minimum": 0
              },
              "columns": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ColumnQuality"
                }
              },
              "icecat": {
                "$ref": "#/components/schemas/IcecatCoverage"
              },
              "computedAt": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": [
              "totalRows",
              "columns",
              "computedAt"
            ]
          },
          "fieldRoles": {
            "type": "array",
            "items": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "enrichmentEnabled": {
            "type": "boolean"
          }
        },
        "required": [
          "stats",
          "fieldRoles",
          "enrichmentEnabled"
        ]
      },
      "ProjectFieldSource": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "gallery"
                ]
              },
              "index": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "type"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "brand"
                ]
              }
            },
            "required": [
              "type"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "generalInfo"
                ]
              },
              "key": {
                "type": "string",
                "enum": [
                  "productName",
                  "mpn",
                  "description"
                ]
              }
            },
            "required": [
              "type",
              "key"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "feature"
                ]
              },
              "name": {
                "type": "string",
                "minLength": 1
              }
            },
            "required": [
              "type",
              "name"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "none"
                ]
              }
            },
            "required": [
              "type"
            ]
          }
        ]
      },
      "ProjectEnrichmentSettings": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "apiKeyId": {
            "type": "string",
            "format": "uuid"
          },
          "fieldSources": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "fieldSlug": {
                  "type": "string",
                  "minLength": 1
                },
                "source": {
                  "$ref": "#/components/schemas/ProjectFieldSource"
                }
              },
              "required": [
                "fieldSlug",
                "source"
              ]
            }
          }
        },
        "required": [
          "enabled",
          "fieldSources"
        ]
      },
      "ProjectEnrichmentResponse": {
        "type": "object",
        "properties": {
          "settings": {
            "$ref": "#/components/schemas/ProjectEnrichmentSettings"
          },
          "icecatKeys": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "name"
              ]
            }
          },
          "coverage": {
            "allOf": [
              {
                "$ref": "#/components/schemas/IcecatCoverage"
              },
              {
                "type": [
                  "object",
                  "null"
                ]
              }
            ]
          },
          "computedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "settings",
          "icecatKeys",
          "coverage",
          "computedAt"
        ]
      },
      "PutProjectEnrichmentBody": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "apiKeyId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "fieldSources": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "fieldSlug": {
                  "type": "string",
                  "minLength": 1
                },
                "source": {
                  "$ref": "#/components/schemas/ProjectFieldSource"
                }
              },
              "required": [
                "fieldSlug",
                "source"
              ]
            }
          }
        }
      },
      "RuleCondition": {
        "type": [
          "object",
          "null"
        ],
        "additionalProperties": {}
      },
      "RuleQueryTree": {
        "type": [
          "object",
          "null"
        ],
        "additionalProperties": {}
      },
      "RuleAction": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "set",
              "combine",
              "replace",
              "calculate",
              "round",
              "reformat",
              "transform",
              "exclude",
              "deduplicate",
              "copy"
            ]
          }
        },
        "required": [
          "type"
        ]
      },
      "Rule": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "isActive": {
            "type": "boolean"
          },
          "order": {
            "type": "integer"
          },
          "type": {
            "type": "string",
            "enum": [
              "CONDITION",
              "ALWAYS"
            ]
          },
          "condition": {
            "$ref": "#/components/schemas/RuleCondition"
          },
          "queryTree": {
            "$ref": "#/components/schemas/RuleQueryTree"
          },
          "action": {
            "$ref": "#/components/schemas/RuleAction"
          },
          "ruleGroupId": {
            "type": "string"
          },
          "importId": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "isActive",
          "order",
          "type",
          "condition",
          "action",
          "ruleGroupId",
          "importId",
          "createdAt",
          "updatedAt"
        ]
      },
      "RuleGroup": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "order": {
            "type": "integer"
          },
          "rules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Rule"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "color",
          "projectId",
          "order",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateRuleGroupBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "color": {
            "type": "string",
            "pattern": "^#[0-9A-Fa-f]{6}$"
          }
        },
        "required": [
          "name"
        ]
      },
      "UpdateRuleGroupBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "color": {
            "type": "string"
          },
          "order": {
            "type": "integer"
          }
        }
      },
      "CreateRuleBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 160
          },
          "type": {
            "type": "string",
            "enum": [
              "CONDITION",
              "ALWAYS"
            ],
            "default": "CONDITION"
          },
          "condition": {
            "$ref": "#/components/schemas/RuleCondition"
          },
          "queryTree": {
            "$ref": "#/components/schemas/RuleQueryTree"
          },
          "action": {
            "$ref": "#/components/schemas/RuleAction"
          }
        },
        "required": [
          "name",
          "action"
        ]
      },
      "UpdateRuleBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 160
          },
          "type": {
            "type": "string",
            "enum": [
              "CONDITION",
              "ALWAYS"
            ]
          },
          "condition": {
            "$ref": "#/components/schemas/RuleCondition"
          },
          "queryTree": {
            "$ref": "#/components/schemas/RuleQueryTree"
          },
          "action": {
            "$ref": "#/components/schemas/RuleAction"
          },
          "order": {
            "type": "integer"
          }
        }
      },
      "ReorderRulesBody": {
        "type": "object",
        "properties": {
          "rules": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "order": {
                  "type": "integer"
                }
              },
              "required": [
                "id",
                "order"
              ]
            },
            "minItems": 1
          }
        },
        "required": [
          "rules"
        ]
      },
      "RulesPreviewResult": {
        "type": "object",
        "properties": {
          "before": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            }
          },
          "after": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            }
          },
          "stats": {
            "type": "object",
            "properties": {
              "inputCount": {
                "type": "integer",
                "minimum": 0
              },
              "outputCount": {
                "type": "integer",
                "minimum": 0
              },
              "excludedCount": {
                "type": "integer",
                "minimum": 0
              },
              "deduplicatedCount": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "inputCount",
              "outputCount",
              "excludedCount",
              "deduplicatedCount"
            ]
          },
          "perRule": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "ruleId": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "matched": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "required": [
                "ruleId",
                "name",
                "matched"
              ]
            }
          }
        },
        "required": [
          "before",
          "after",
          "stats",
          "perRule"
        ]
      },
      "RulesPreviewBody": {
        "type": "object",
        "properties": {
          "sampleSize": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          }
        }
      }
    },
    "parameters": {}
  },
  "paths": {
    "/api/agent/conversations": {
      "post": {
        "tags": [
          "Agent"
        ],
        "summary": "Apre una conversazione con l'assistente su un progetto",
        "description": "Provider e modello vengono congelati alla creazione (`AGENT_PROVIDER`, `AGENT_MODEL_MAIN`). 404 se `AGENT_ENABLED` non è `true`.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAgentConversationBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentConversation"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Agent"
        ],
        "summary": "Elenca le conversazioni dell'utente su un progetto",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "projectId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AgentConversation"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/agent/conversations/{id}": {
      "get": {
        "tags": [
          "Agent"
        ],
        "summary": "Conversazione completa con messaggi e tool call",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentConversationDetail"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Agent"
        ],
        "summary": "Archivia una conversazione (non la cancella)",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentConversation"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/agent/conversations/{id}/messages": {
      "post": {
        "tags": [
          "Agent"
        ],
        "summary": "Invia un messaggio ed esegue un turno (SSE)",
        "description": "Risposta in streaming `text/event-stream`: una riga `data: <AgentEvent JSON>\\n\\n` per evento (`message_start`, `text_delta`, `thinking_delta`, `tool_call`, `tool_result`, `approval_required`, `usage`, `done`, `error`) più heartbeat `: heartbeat`. Lo schema JSON qui sotto è un segnaposto: il generatore OpenAPI del monorepo descrive solo risposte `application/json`. 429 se si superano 10 turni al minuto, 409 se un altro turno è già in corso sulla stessa conversazione, 402 se il budget token mensile del piano è esaurito (vincolante salvo `AGENT_HARD_BUDGET=false`).",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendAgentMessageBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentEventStream"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "402": {
            "description": "HTTP 402",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentEventStream"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "409": {
            "description": "Conflitto (es. risorsa già esistente).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentEventStream"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "429": {
            "description": "HTTP 429",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentEventStream"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/agent/conversations/{id}/tool-calls/{callId}/approve": {
      "post": {
        "tags": [
          "Agent"
        ],
        "summary": "Approva un'azione in attesa e riprende il turno (SSE)",
        "description": "Risposta in streaming `text/event-stream`: una riga `data: <AgentEvent JSON>\\n\\n` per evento (`message_start`, `text_delta`, `thinking_delta`, `tool_call`, `tool_result`, `approval_required`, `usage`, `done`, `error`) più heartbeat `: heartbeat`. Lo schema JSON qui sotto è un segnaposto: il generatore OpenAPI del monorepo descrive solo risposte `application/json`.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "callId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentDecisionBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentEventStream"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "409": {
            "description": "Conflitto (es. risorsa già esistente).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentEventStream"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/agent/conversations/{id}/tool-calls/{callId}/reject": {
      "post": {
        "tags": [
          "Agent"
        ],
        "summary": "Rifiuta un'azione in attesa e riprende il turno (SSE)",
        "description": "Risposta in streaming `text/event-stream`: una riga `data: <AgentEvent JSON>\\n\\n` per evento (`message_start`, `text_delta`, `thinking_delta`, `tool_call`, `tool_result`, `approval_required`, `usage`, `done`, `error`) più heartbeat `: heartbeat`. Lo schema JSON qui sotto è un segnaposto: il generatore OpenAPI del monorepo descrive solo risposte `application/json`.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "callId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentDecisionBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentEventStream"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "409": {
            "description": "Conflitto (es. risorsa già esistente).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentEventStream"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/agent/conversations/{id}/tool-calls/{callId}/revert": {
      "post": {
        "tags": [
          "Agent"
        ],
        "summary": "Annulla un'azione già eseguita",
        "description": "Chiama il `revert()` del tool. 400 se l'azione non è annullabile, 409 se non è in stato `executed`.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "callId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "reverted"
                          ]
                        }
                      },
                      "required": [
                        "status"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "409": {
            "description": "Conflitto (es. risorsa già esistente).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "reverted"
                          ]
                        }
                      },
                      "required": [
                        "status"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/agent/memories": {
      "get": {
        "tags": [
          "Agent"
        ],
        "summary": "Memorie dell'assistente visibili su un progetto",
        "description": "`project` sono condivise da chi lavora al progetto, `user` sono personali di chi chiama e valgono su tutti i suoi progetti. Le stesse voci finiscono nel blocco di contesto del turno.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "projectId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentMemoryList"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/agent/memories/{id}": {
      "delete": {
        "tags": [
          "Agent"
        ],
        "summary": "Cancella una memoria dell'assistente",
        "description": "Una memoria `project` richiede `feed/write` sul progetto; una `user` la cancella solo il suo proprietario. 404 (non 403) quando la memoria non è visibile a chi chiama.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentMemory"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/agent/usage": {
      "get": {
        "tags": [
          "Agent"
        ],
        "summary": "Consumo token dell'assistente nel mese corrente",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentUsageReport"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/active-company": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Imposta la company attiva nella sessione utente",
        "description": "Verifica server-side che l'utente sia membro della company (o super-admin), poi il client invoca update({activeCompanyId}) sulla sessione. Defense-in-depth rispetto al callback jwt.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActiveCompanyBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ActiveCompanyResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/admin/companies": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Cerca tra tutte le companies (super-admin only)",
        "description": "Restituisce una lista paginata di companies che matchano la query string (case-insensitive su nome o slug). Solo per super-admin Connecteed.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "q",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CompanyBrief"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "tags": [
          "System"
        ],
        "summary": "Liveness check del web service",
        "description": "Endpoint usato da reverse proxy / Dokploy healthcheck. Sempre 200 se il server risponde. Non richiede autenticazione.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/feeds/{token}": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "summary": "Scarica l'ultimo export pubblicato per il token dato",
        "description": "Risolve il token (cifrato AES) a un Export, trova l'ultimo file generato in storage e lo streamma con Content-Disposition: attachment. Endpoint pubblico (non richiede sessione, l'autenticazione è il possesso del token).",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 32
            },
            "required": true,
            "name": "token",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "description": "File binario (CSV/JSON/XML/TXT)."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs": {
      "get": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Elenca le sincronizzazioni catalogo del progetto",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CatalogSync"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Crea una sincronizzazione catalogo",
        "description": "Valida templateKey contro il registry condiviso e la coerenza provider/ApiKey. Permesso a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCatalogSyncBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CatalogSync"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}": {
      "get": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Dettaglio di una sincronizzazione catalogo",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CatalogSync"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Aggiorna una sincronizzazione catalogo",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCatalogSyncBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CatalogSync"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Elimina una sincronizzazione catalogo",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      },
                      "required": [
                        "deleted"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/mappings": {
      "put": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Sostituisce le mappature colonne (atomico)",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutCatalogMappingsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CatalogSync"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/enrichment-mappings": {
      "put": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Sostituisce le mappature di arricchimento Icecat (atomico)",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutCatalogEnrichmentMappingsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CatalogSync"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/template": {
      "get": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Metadati e colonne del template risolto per il sync",
        "description": "Per provider dinamici include anche le colonne scoped delle categorie già mappate.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CatalogTemplate"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/categories": {
      "get": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Ricerca categorie del sync catalogo",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "search",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CatalogCategory"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/value-mappings": {
      "get": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Mappa valori → categoria (paginata)",
        "description": "Filtri: unmapped | mapped | all; ricerca testuale; ordinamento non-mappate-prima per occorrenze. Include i contatori di progresso.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "mapped",
                "unmapped"
              ]
            },
            "required": false,
            "name": "filter",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "search",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CatalogValueMapping"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Upsert parziale della mappa valori → categoria",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutCatalogValueMappingsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "updated": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "updated"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/value-mappings/refresh": {
      "post": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Sincronizza i valori DISTINCT del campo categoria dal database",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "totalDistinct": {
                          "type": "integer"
                        },
                        "added": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "totalDistinct",
                        "added"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/value-mappings/suggest": {
      "post": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Suggerisce categorie per i valori non mappati (similarità testuale)",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "suggested": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "suggested"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/categories-summary": {
      "get": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Riepilogo attributi per categoria mappata",
        "description": "Per ogni categoria mappata: prodotti coperti, progresso dei required (spec × mappature) e disponibilità degli attributi scoped in cache. Vuoto per sorgenti statiche.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "categories": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/CatalogCategorySummary"
                          }
                        }
                      },
                      "required": [
                        "categories"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/value-mappings/csv": {
      "get": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Esporta la mappa valori → categoria come CSV",
        "description": "Colonne: valore, categoria_id, categoria_path, occorrenze. Compilabile in Excel e re-importabile con la POST.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Importa assegnazioni valore → categoria da CSV",
        "description": "Body raw text/csv (colonne richieste: valore, categoria_id). Non distruttivo: categoria vuota = riga ignorata; valori sconosciuti e categorie non valide vengono scartati e riportati.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "applied": {
                          "type": "integer"
                        },
                        "skippedUnknownValue": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "skippedUnknownValueCount": {
                          "type": "integer"
                        },
                        "skippedUnknownCategory": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "skippedUnknownCategoryCount": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "applied",
                        "skippedUnknownValue",
                        "skippedUnknownValueCount",
                        "skippedUnknownCategory",
                        "skippedUnknownCategoryCount"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/value-mappings/copy-from": {
      "post": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Copia le mappature categorie da un altro sync compatibile",
        "description": "Compatibile = stesso provider e templateKey. I categoryId vengono validati contro l'albero del sync di destinazione; di default non sovrascrive le mappature esistenti.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostCopyValueMappingsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "copied": {
                          "type": "integer"
                        },
                        "skippedExisting": {
                          "type": "integer"
                        },
                        "skippedUnknownValue": {
                          "type": "integer"
                        },
                        "skippedInvalidCategory": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "copied",
                        "skippedExisting",
                        "skippedUnknownValue",
                        "skippedInvalidCategory"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/run": {
      "post": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Avvia la sincronizzazione del catalogo",
        "description": "Crea un PipelineRun e inoltra al worker. Mirakl accetta un import prodotti ogni 15 minuti.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "responses": {
          "202": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "pipelineRunId": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "pipelineRunId"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/refresh-status": {
      "post": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Ricontrolla lo stato dell'import marketplace (AWAITING_MARKETPLACE)",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "IDLE",
                            "BUILDING",
                            "UPLOADING",
                            "AWAITING_MARKETPLACE",
                            "COMPLETED",
                            "FAILED"
                          ]
                        },
                        "rawStatus": {
                          "type": "string"
                        },
                        "linesInError": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "status"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/refresh-metadata": {
      "post": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Avvia refresh asincrono dei metadati catalogo Mirakl",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "responses": {
          "202": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "started": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      },
                      "required": [
                        "started"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/catalog-syncs/{syncId}/report": {
      "get": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Scarica l'ultimo report CSV di scarti o errori catalogo",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "syncId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/catalog-templates/{templateKey}": {
      "get": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Metadati e colonne di un template catalogo",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "templateKey",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CatalogTemplate"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/catalog-templates/{templateKey}/categories": {
      "get": {
        "tags": [
          "CatalogSync"
        ],
        "summary": "Ricerca categorie del template (server-side)",
        "description": "L'albero (migliaia di nodi) non viene mai inviato al client: la ricerca è filtrata lato server. Parametri: search, limit (default 50).",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "templateKey",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CatalogCategory"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/companies": {
      "post": {
        "tags": [
          "Companies"
        ],
        "summary": "Crea una nuova company (organizzazione)",
        "description": "Crea la company sia in Keycloak (organization) sia nel DB control plane (con CompanyUser OWNER per l'utente corrente). Le due scritture sono coordinate: in caso di fallimento DB la Keycloak org viene rollbackata.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCompanyBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Company"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/companies/current": {
      "get": {
        "tags": [
          "Companies"
        ],
        "summary": "Restituisce la company attiva nella sessione",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Company"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Companies"
        ],
        "summary": "Aggiorna nome o timezone della company attiva",
        "description": "Permesso solo a ruoli OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCompanyBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Company"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/companies/current/members": {
      "get": {
        "tags": [
          "Companies"
        ],
        "summary": "Elenca i membri della company attiva",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CompanyMember"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/companies/current/members/{memberId}": {
      "put": {
        "tags": [
          "Companies"
        ],
        "summary": "Aggiorna ruolo o preferenza notifiche di un membro",
        "description": "Permesso a OWNER / ADMIN. Un ADMIN non può modificare un OWNER né assegnare il ruolo OWNER. Non si può declassare l'unico OWNER.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "memberId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateMemberBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CompanyMember"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Companies"
        ],
        "summary": "Rimuove un membro dalla company",
        "description": "Permesso a OWNER / ADMIN. Un ADMIN non può rimuovere un OWNER; non si può rimuovere l'unico OWNER né se stessi. Sincronizza la rimozione con Keycloak (best-effort).",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "memberId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/DeleteResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/companies/current/api-keys": {
      "get": {
        "tags": [
          "ApiKeys"
        ],
        "summary": "Elenca le API keys salvate per la company attiva",
        "description": "Restituisce metadati e seller ID mascherato. Credenziali in chiaro non vengono mai esposte.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiKey"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "ApiKeys"
        ],
        "summary": "Salva una nuova API key (Amazon SP-API)",
        "description": "Credenziali cifrate AES e salvate. Permesso solo a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateApiKeyBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ApiKey"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/companies/current/api-keys/shopify/oauth/start": {
      "post": {
        "tags": [
          "ApiKeys"
        ],
        "summary": "Avvia il flusso OAuth Shopify (authorization code grant)",
        "description": "Salva una sessione OAuth temporanea (clientSecret cifrato) e restituisce l'URL di autorizzazione Shopify verso cui reindirizzare il browser. La callback /api/shopify/oauth/callback completa la connessione creando l'ApiKey. Permesso a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShopifyOAuthStartBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ShopifyOAuthStartResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/companies/current/api-keys/{keyId}": {
      "get": {
        "tags": [
          "ApiKeys"
        ],
        "summary": "Recupera una singola API key",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "keyId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ApiKey"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "ApiKeys"
        ],
        "summary": "Aggiorna parzialmente una API key esistente",
        "description": "Solo i campi presenti e non vuoti nel body sovrascrivono le credenziali esistenti. Permesso a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "keyId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateApiKeyBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ApiKey"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "ApiKeys"
        ],
        "summary": "Cancella una API key",
        "description": "Eventuali import/export collegati vengono scollegati (set null). Permesso a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "keyId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/DeleteResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/companies/current/api-keys/{keyId}/test": {
      "post": {
        "tags": [
          "ApiKeys"
        ],
        "summary": "Testa la connessione di una API key contro il provider",
        "description": "Inoltra al worker (POST /internal/amazon/test) che esegue una chiamata di smoke test al provider.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "keyId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ApiKeyTestResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/exports": {
      "get": {
        "tags": [
          "Exports"
        ],
        "summary": "Elenca gli export di un progetto",
        "description": "Risolve il `stableUrlToken` cifrato in `feedUrl` (`/api/feeds/<token>`) per ogni export. Il token raw non viene mai esposto.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Export"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Exports"
        ],
        "summary": "Crea un nuovo export",
        "description": "Genera un `stableUrlToken` random + cifrato. La risposta include il `rawToken` UNA sola volta. Permesso a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateExportBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportCreatedResponse"
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/exports/{exportId}": {
      "put": {
        "tags": [
          "Exports"
        ],
        "summary": "Aggiorna parzialmente un export",
        "description": "Cambiare typeFeed in AMAZON forza typeProtocol=DOWNLOAD. Permesso a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "exportId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateExportBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Export"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Exports"
        ],
        "summary": "Elimina un export",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "exportId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      },
                      "required": [
                        "deleted"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/exports/{exportId}/mappings": {
      "get": {
        "tags": [
          "Exports"
        ],
        "summary": "Elenca i mappings field↔column di un export",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "exportId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ExportMapping"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Exports"
        ],
        "summary": "Sovrascrive il set di mappings di un export",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "exportId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutExportMappingsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ExportMapping"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/exports/{exportId}/rule-exclusions": {
      "get": {
        "tags": [
          "Exports"
        ],
        "summary": "Elenca le regole escluse per questo export",
        "description": "Le regole escluse NON vengono applicate quando questo export gira lo step RULES.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "exportId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ExportRuleExclusions"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Exports"
        ],
        "summary": "Sostituisce la lista delle regole escluse per un export",
        "description": "Diff implicito: INSERT delle regole nella lista che non sono escluse, DELETE di quelle escluse non più presenti. Tutte le rule devono appartenere a un RuleGroup di questo project.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "exportId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutExportRuleExclusionsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ExportRuleExclusionsResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/exports/{exportId}/run": {
      "post": {
        "tags": [
          "Exports"
        ],
        "summary": "Lancia una pipeline run di tipo EXPORT solo per questo export",
        "description": "Crea un PipelineRun PENDING e enqueue il job sul worker. Restituisce 409 se l'export è GENERATING/UPLOADING, 400 se nessun mapping è configurato.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "exportId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ExportRunResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/exports/{exportId}/refresh-status": {
      "post": {
        "tags": [
          "Exports"
        ],
        "summary": "Ricontrolla lo stato dell'import offerte sul marketplace (Mirakl OF02)",
        "description": "Per export in AWAITING_MARKETPLACE: ri-polla OF02 via worker e aggiorna stato + resoconto (lines_read/success/error).",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "exportId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "IDLE",
                            "GENERATING",
                            "UPLOADING",
                            "AWAITING_MARKETPLACE",
                            "COMPLETED",
                            "FAILED"
                          ]
                        },
                        "processed": {
                          "type": "integer"
                        },
                        "created": {
                          "type": "integer"
                        },
                        "errors": {
                          "type": "integer"
                        },
                        "rawStatus": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "status"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/exports/{exportId}/error-report": {
      "get": {
        "tags": [
          "Exports"
        ],
        "summary": "Scarica il CSV degli errori per-riga dell'ultimo invio (Mirakl OF02)",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "exportId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/imports": {
      "get": {
        "tags": [
          "Imports"
        ],
        "summary": "Elenca le import sources di un progetto",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Import"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Imports"
        ],
        "summary": "Crea una nuova import source",
        "description": "Password connettore criptata AES. Permesso a OWNER / ADMIN. Vedi `CreateImportBody` per la distinzione Amazon Report vs import classico.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateImportBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Import"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/imports/{importId}": {
      "put": {
        "tags": [
          "Imports"
        ],
        "summary": "Aggiorna parzialmente una import source",
        "description": "Cambiare `mergeKeyField` mentre una pipeline è RUNNING/PENDING per il progetto restituisce 409. Permesso a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "importId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateImportBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Import"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Imports"
        ],
        "summary": "Elimina una import source",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "importId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      },
                      "required": [
                        "deleted"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/imports/{importId}/columns": {
      "get": {
        "tags": [
          "Imports"
        ],
        "summary": "Estrae le colonne sorgente leggendo le prime righe del feed",
        "description": "Si connette alla source (SFTP/FTP/HTTP) e legge headerLine + 5 righe, poi parsea CSV/JSON/XML per estrarre i nomi colonna. Errori connettore → 422.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "importId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ImportColumnsResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/imports/{importId}/mappings": {
      "get": {
        "tags": [
          "Imports"
        ],
        "summary": "Elenca i mappings nomeField↔nomeColonna",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "importId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ImportMapping"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Imports"
        ],
        "summary": "Sovrascrive il set di mappings di una import",
        "description": "Operazione idempotente: cancella i mapping esistenti e li ricrea dall'array. Permesso a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "importId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutImportMappingsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ImportMapping"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/imports/{importId}/run": {
      "post": {
        "tags": [
          "Imports"
        ],
        "summary": "Lancia una pipeline run di tipo IMPORT solo per questa source",
        "description": "Crea un PipelineRun PENDING e enqueue il job sul worker. Restituisce 409 se l'import è già FETCHING/PARSING, 400 se non ci sono mappings configurati.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "importId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ImportRunResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/imports/{importId}/test": {
      "post": {
        "tags": [
          "Imports"
        ],
        "summary": "Smoke test della connessione: scarica le prime 10 righe",
        "description": "Restituisce filename, righe raw, conteggio. Errori connettore → 422 con `code` del ConnectorError.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "importId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ImportTestResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/invitations": {
      "get": {
        "tags": [
          "Invitations"
        ],
        "summary": "Elenca le invitations pendenti della company attiva",
        "description": "Mostra solo invitations non ancora accettate. Permesso a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Invitation"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Invitations"
        ],
        "summary": "Crea una nuova invitation per la company attiva",
        "description": "Genera un token unico (UUID), salva la invitation con scadenza 7 giorni, prova ad inviare l'email transazionale (best-effort: un fallimento SMTP non fa rollback).",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateInvitationBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/InvitationCreated"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/invitations/{id}": {
      "delete": {
        "tags": [
          "Invitations"
        ],
        "summary": "Revoca una invitation pendente",
        "description": "Una invitation già accettata NON può essere revocata (409). Permesso a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "success": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      },
                      "required": [
                        "success"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/invitations/{id}/resend": {
      "post": {
        "tags": [
          "Invitations"
        ],
        "summary": "Rispedisce l'email di una invitation pendente",
        "description": "Riusa lo stesso token (l'utente vede la stessa /invite/<token> URL) e aggiorna emailSentAt. Permesso a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/InvitationCreated"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/invitations/accept": {
      "post": {
        "tags": [
          "Invitations"
        ],
        "summary": "Accetta una invitation usando il token",
        "description": "Verifica che l'email della invitation matchi l'utente loggato, sync Keycloak org membership, crea CompanyUser e marca acceptedAt. Manda una welcome email best-effort.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcceptInvitationBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AcceptInvitationResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/pipeline/events": {
      "get": {
        "tags": [
          "Pipeline"
        ],
        "summary": "Stream SSE degli eventi pipeline live",
        "description": "Server-Sent Events su Redis pubsub. Inviati eventi `progress`, `log`, `status`, `complete`, `error`. Heartbeat ogni 25s. Content-Type: text/event-stream.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Stream SSE (text/event-stream)"
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/pipeline/run": {
      "post": {
        "tags": [
          "Pipeline"
        ],
        "summary": "Lancia una pipeline run completa (delegata al worker)",
        "description": "Verifica che nessuna pipeline sia già PENDING/RUNNING per il progetto (409 altrimenti) e delega al worker l'enqueue del job. Restituisce 202.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RunPipelineBody"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/RunPipelineResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/pipeline/run-now": {
      "post": {
        "tags": [
          "Pipeline"
        ],
        "summary": "Alias di /pipeline/run (back-compat con la UI esistente)",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RunPipelineBody"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/RunPipelineResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/pipeline/runs": {
      "get": {
        "tags": [
          "Pipeline"
        ],
        "summary": "Elenca le pipeline runs (paginate)",
        "description": "Default page=1, limit=20 (max 50). Restituisce id, status, type, timestamps, stats. Per i log usa `/runs/{runId}`.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "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": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PipelineRunsListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/pipeline/runs/{runId}": {
      "get": {
        "tags": [
          "Pipeline"
        ],
        "summary": "Dettaglio di una pipeline run con i log",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "runId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PipelineRunWithLogs"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/schedule": {
      "get": {
        "tags": [
          "Scheduler"
        ],
        "summary": "Recupera la schedule corrente del progetto",
        "description": "Restituisce `data: null` se nessuna schedule è configurata. `timezone` viene dalla company (default `Europe/Rome`).",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleResponse"
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Scheduler"
        ],
        "summary": "Upserta la schedule del progetto",
        "description": "Time slots HH:mm (max 24, deduplicati). Sync con worker `/internal/scheduler/sync` (non-fatal, errori loggati ma non bloccanti). Permesso a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateScheduleBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Schedule"
                        },
                        {
                          "type": "object"
                        }
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects": {
      "get": {
        "tags": [
          "Projects"
        ],
        "summary": "Elenca i progetti dell'azienda attiva",
        "description": "Restituisce tutti i progetti della company attiva dell'utente, ordinati per data di creazione discendente. Include il conteggio dei campi configurati.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Project"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Projects"
        ],
        "summary": "Crea un nuovo progetto",
        "description": "Crea un progetto nella company attiva. Inizializza lo schema Postgres dedicato e, opzionalmente, una lista di campi (database fields) iniziali.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProjectBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProjectWithFields"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}": {
      "get": {
        "tags": [
          "Projects"
        ],
        "summary": "Dettaglio di un progetto",
        "description": "Include i database fields ordinati e il conteggio imports/exports/runs.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProjectWithFields"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Projects"
        ],
        "summary": "Rinomina un progetto",
        "description": "Permesso solo a OWNER / ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProjectBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Project"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Projects"
        ],
        "summary": "Elimina un progetto e droppa la tabella dati",
        "description": "Droppa la tabella `project_<id>` nello schema company e cancella il record Project. Permesso a OWNER / ADMIN. Operazione NON reversibile.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      },
                      "required": [
                        "deleted"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/fields": {
      "get": {
        "tags": [
          "Fields"
        ],
        "summary": "Elenca i database fields di un progetto",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DatabaseField"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Fields"
        ],
        "summary": "Crea un nuovo database field",
        "description": "Lo slug viene derivato dal nome (snake_case lowercase). Aggiunge una colonna alla tabella dati Postgres del progetto.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFieldBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/DatabaseField"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/fields/{fieldId}": {
      "put": {
        "tags": [
          "Fields"
        ],
        "summary": "Aggiorna nome o visibilità di un field",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "fieldId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateFieldBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/DatabaseField"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Fields"
        ],
        "summary": "Elimina un field e droppa la colonna",
        "description": "Droppa anche la colonna dalla tabella dati Postgres del progetto.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "fieldId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      },
                      "required": [
                        "deleted"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/fields/reorder": {
      "patch": {
        "tags": [
          "Fields"
        ],
        "summary": "Riordina i fields di un progetto",
        "description": "Aggiorna l'ordine dei fields in base alla posizione dell'array `fieldIds`. Restituisce la nuova lista.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReorderFieldsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DatabaseField"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/rows": {
      "get": {
        "tags": [
          "Rows"
        ],
        "summary": "Leggi righe dati del progetto (paginate, con ricerca)",
        "description": "Query parametrica: `page` (default 1), `limit` (default 50, max 200), `search` (filtra ILIKE su tutti i fields visibili). Risposta con envelope esteso `{data, meta}`.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "search",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": {
                          "type": "string"
                        }
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "page": {
                          "type": "integer",
                          "minimum": 1
                        },
                        "limit": {
                          "type": "integer",
                          "minimum": 1
                        },
                        "totalPages": {
                          "type": "integer",
                          "minimum": 0
                        }
                      },
                      "required": [
                        "total",
                        "page",
                        "limit",
                        "totalPages"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "description": "Paginated rows from the project data table (envelope diverso: data + meta)."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/quality": {
      "get": {
        "tags": [
          "DataHub"
        ],
        "summary": "Snapshot qualità dati del progetto",
        "description": "Aggregati per colonna (fill rate, distinct, celle arricchite), check semantici per ruolo (EAN invalidi/duplicati, prezzi non numerici o a zero, immagini non-URL, testi sotto soglia) e recuperabilità via Icecat. Ricalcolato dal worker dopo ogni import; `stats: null` se non è mai girato un import. Include il contesto per il completion Data Hub (ruoli campi, arricchimento abilitato).",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/DataQuality"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/enrichment": {
      "get": {
        "tags": [
          "DataHub"
        ],
        "summary": "Configurazione arricchimento Icecat project-level",
        "description": "Settings correnti, connessioni ICECAT disponibili e copertura cache sugli EAN del progetto (dallo snapshot qualità).",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProjectEnrichmentResponse"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "DataHub"
        ],
        "summary": "Aggiorna la configurazione di arricchimento del progetto",
        "description": "I valori Icecat vengono materializzati nella tabella progetto dallo step ENRICHMENT (solo celle vuote; la sorgente vince sempre). Richiede ruolo OWNER o ADMIN.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutProjectEnrichmentBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProjectEnrichmentSettings"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/rule-groups": {
      "get": {
        "tags": [
          "Rules"
        ],
        "summary": "Elenca i gruppi di regole con le regole annidate",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RuleGroup"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Rules"
        ],
        "summary": "Crea un nuovo gruppo di regole",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRuleGroupBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/RuleGroup"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/rule-groups/{groupId}": {
      "put": {
        "tags": [
          "Rules"
        ],
        "summary": "Aggiorna nome, colore o ordine di un rule group",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "groupId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateRuleGroupBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/RuleGroup"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Rules"
        ],
        "summary": "Elimina un rule group e le sue regole",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "groupId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      },
                      "required": [
                        "deleted"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/rule-groups/{groupId}/rules": {
      "post": {
        "tags": [
          "Rules"
        ],
        "summary": "Crea una nuova regola in un gruppo",
        "description": "Per `type=CONDITION` la `condition` (JSONLogic) è obbligatoria. Per `type=ALWAYS` viene ignorata.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "groupId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRuleBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Rule"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/rules/{ruleId}": {
      "put": {
        "tags": [
          "Rules"
        ],
        "summary": "Aggiorna parzialmente una regola",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "ruleId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateRuleBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Rule"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Rules"
        ],
        "summary": "Elimina una regola",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "ruleId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      },
                      "required": [
                        "deleted"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/rules/{ruleId}/toggle": {
      "patch": {
        "tags": [
          "Rules"
        ],
        "summary": "Toggle attiva/disattiva una regola",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "ruleId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Rule"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/rules/reorder": {
      "patch": {
        "tags": [
          "Rules"
        ],
        "summary": "Riordina N regole in batch",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReorderRulesBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "updated": {
                          "type": "integer",
                          "minimum": 0
                        }
                      },
                      "required": [
                        "updated"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/rules/preview": {
      "post": {
        "tags": [
          "Rules"
        ],
        "summary": "Anteprima delle regole su un campione di righe",
        "description": "Carica le prime `sampleSize` (default 20, max 100) righe dalla tabella dati del progetto, applica tutte le regole attive in ordine, restituisce `before`/`after` e statistiche di trasformazione.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RulesPreviewBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/RulesPreviewResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "description": "Envelope di successo. Il payload è in `data`."
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    },
    "/api/companies/current/webhooks/{id}/deliveries": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Elenca le delivery di un webhook",
        "description": "Richiede OWNER o ADMIN. Restituisce solo metadata operativi: payload, URL snapshot e signing secret non sono esposti.",
        "security": [
          {
            "cookieSession": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "event": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "PENDING",
                              "CLAIMED",
                              "SUCCEEDED",
                              "FAILED",
                              "CANCELLED"
                            ]
                          },
                          "attemptCount": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "maxAttempts": {
                            "type": "integer",
                            "exclusiveMinimum": 0
                          },
                          "responseStatus": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "durationMs": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "occurredAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "completedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "event",
                          "status",
                          "attemptCount",
                          "maxAttempts",
                          "responseStatus",
                          "durationMs",
                          "occurredAt",
                          "completedAt",
                          "createdAt"
                        ]
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "nextCursor": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "uuid"
                        }
                      },
                      "required": [
                        "nextCursor"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Input non valido (validazione Zod fallita).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "401": {
            "description": "Non autenticato.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "403": {
            "description": "Autenticato ma non autorizzato sulla risorsa.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "404": {
            "description": "Risorsa non trovata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          },
          "500": {
            "description": "Errore interno.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "description": "Envelope di errore. Il messaggio human-readable è in `error`; lo status code HTTP racconta il tipo (400, 401, 403, 404, 409, 500)."
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {}
}
