{
  "openapi": "3.0.0",
  "info": {
    "title": "API de OnePrint",
    "version": "1.0.0",
    "description": "API para gestionar clientes y etiquetas ZPL con soporte para logos y contadores. Esta API tiene CORS habilitado para permitir solicitudes desde cualquier origen.",
    "contact": {
      "name": "Soporte",
      "email": "soporte@oneprint.com"
    }
  },
  "servers": [
    {
      "url": "/",
      "description": "Servidor de desarrollo"
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      },
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "API Key para autenticación de aplicaciones externas"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Mensaje de error"
          }
        },
        "required": [
          "error"
        ]
      },
      "Client": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID único del cliente"
          },
          "name": {
            "type": "string",
            "description": "Nombre del cliente"
          },
          "email": {
            "type": "string",
            "format": "email",
            "nullable": true,
            "description": "Email del cliente"
          },
          "phone": {
            "type": "string",
            "nullable": true,
            "description": "Teléfono del cliente"
          },
          "address": {
            "type": "string",
            "nullable": true,
            "description": "Dirección del cliente"
          },
          "logo_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL del logo del cliente"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Fecha de creación"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Fecha de última actualización"
          }
        },
        "required": [
          "id",
          "name",
          "created_at",
          "updated_at"
        ]
      },
      "Label": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID único de la etiqueta"
          },
          "client_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID del cliente propietario"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Nombre de la etiqueta"
          },
          "content": {
            "type": "object",
            "additionalProperties": true,
            "description": "Contenido variable de la etiqueta"
          },
          "zpl_template": {
            "type": "string",
            "description": "Plantilla ZPL de la etiqueta"
          },
          "label_type": {
            "type": "string",
            "enum": [
              "standard",
              "product",
              "shipping",
              "inventory"
            ],
            "description": "Tipo de etiqueta"
          },
          "counter_current": {
            "type": "integer",
            "nullable": true,
            "description": "Valor actual del contador"
          },
          "counter_start": {
            "type": "integer",
            "nullable": true,
            "description": "Valor inicial del contador"
          },
          "counter_increment": {
            "type": "integer",
            "nullable": true,
            "description": "Incremento del contador"
          },
          "counter_format": {
            "type": "string",
            "nullable": true,
            "description": "Formato del contador (ej: 000000)"
          },
          "logo_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL del logo para la etiqueta"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Fecha de creación"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Fecha de última actualización"
          },
          "label_width": {
            "type": "number",
            "nullable": true,
            "description": "Ancho de la etiqueta en mm"
          },
          "label_height": {
            "type": "number",
            "nullable": true,
            "description": "Alto de la etiqueta en mm"
          }
        },
        "required": [
          "id",
          "client_id",
          "zpl_template",
          "label_type",
          "created_at",
          "updated_at"
        ]
      },
      "PrintRequest": {
        "type": "object",
        "properties": {
          "labelId": {
            "type": "string",
            "format": "uuid",
            "description": "ID de la etiqueta a imprimir"
          },
          "quantity": {
            "type": "integer",
            "description": "Cantidad de etiquetas a imprimir",
            "default": 1,
            "minimum": 1,
            "maximum": 100
          }
        },
        "required": [
          "labelId"
        ]
      },
      "PrintResponse": {
        "type": "object",
        "properties": {
          "zpl": {
            "type": "string",
            "description": "Código ZPL generado para la impresión"
          },
          "counter": {
            "type": "integer",
            "description": "Valor actual del contador después de la impresión",
            "nullable": true
          }
        },
        "required": [
          "zpl"
        ]
      },
      "PrintJob": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID único del trabajo de impresión"
          },
          "label_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de la etiqueta"
          },
          "printer_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "ID de la impresora"
          },
          "user_id": {
            "type": "string",
            "description": "ID del usuario"
          },
          "copies": {
            "type": "integer",
            "description": "Número de copias",
            "minimum": 1
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "printing",
              "completed",
              "failed"
            ],
            "description": "Estado del trabajo"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Fecha de creación"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Fecha de última actualización"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Fecha de completado"
          },
          "error_message": {
            "type": "string",
            "nullable": true,
            "description": "Mensaje de error si falló"
          },
          "job_data": {
            "type": "object",
            "additionalProperties": true,
            "description": "Datos adicionales del trabajo"
          }
        },
        "required": [
          "id",
          "label_id",
          "user_id",
          "copies",
          "status",
          "created_at",
          "updated_at"
        ]
      },
      "BatchUpdateRequest": {
        "type": "object",
        "properties": {
          "job_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Lista de IDs de trabajos de impresión a actualizar",
            "minItems": 1
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "printing",
              "completed",
              "failed"
            ],
            "description": "Nuevo estado para los trabajos"
          },
          "error_message": {
            "type": "string",
            "nullable": true,
            "description": "Mensaje de error opcional (para estado 'failed')"
          }
        },
        "required": [
          "job_ids",
          "status"
        ]
      },
      "BatchUpdateResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Indica si la operación fue exitosa"
          },
          "updated_count": {
            "type": "integer",
            "description": "Número de trabajos actualizados",
            "minimum": 0
          },
          "message": {
            "type": "string",
            "description": "Mensaje descriptivo del resultado"
          },
          "updated_jobs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PrintJob"
            },
            "description": "Lista de trabajos actualizados"
          }
        },
        "required": [
          "success",
          "updated_count",
          "message"
        ]
      },
      "PendingPrintJobRequest": {
        "type": "object",
        "properties": {
          "jobs": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "label_id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "ID de la etiqueta"
                },
                "printer_id": {
                  "type": "string",
                  "format": "uuid",
                  "nullable": true,
                  "description": "ID de la impresora (opcional)"
                },
                "copies": {
                  "type": "integer",
                  "default": 1,
                  "minimum": 1,
                  "description": "Número de copias"
                },
                "job_data": {
                  "type": "object",
                  "additionalProperties": true,
                  "description": "Datos adicionales del trabajo"
                },
                "content": {
                  "type": "object",
                  "additionalProperties": true,
                  "description": "Contenido para llenar las variables de la etiqueta"
                }
              },
              "required": [
                "label_id"
              ]
            },
            "minItems": 1,
            "description": "Lista de trabajos a crear"
          }
        },
        "required": [
          "jobs"
        ]
      },
      "PendingPrintJobResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "Mensaje de éxito"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PrintJob"
            },
            "description": "Lista de trabajos creados"
          }
        },
        "required": [
          "message",
          "data"
        ]
      },
      "InforLabelRequest": {
        "type": "object",
        "properties": {
          "FilePath": {
            "type": "string",
            "description": "Ruta al archivo de plantilla de etiqueta en Infor"
          },
          "Printer": {
            "type": "string",
            "description": "Nombre de la impresora en Infor"
          },
          "Quantity": {
            "type": "integer",
            "description": "Cantidad de etiquetas a imprimir",
            "default": 1,
            "minimum": 1
          },
          "Variables": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            },
            "description": "Array de objetos con variables para la etiqueta",
            "minItems": 1
          },
          "_LabelType_": {
            "type": "string",
            "description": "Tipo de etiqueta en formato 'Type:TIPO_ETIQUETA DROPID=ID'"
          }
        },
        "required": [
          "FilePath",
          "Printer",
          "Quantity",
          "Variables",
          "_LabelType_"
        ]
      },
      "InforLabelResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "Mensaje de éxito"
          },
          "jobs": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "ID del trabajo de impresión creado"
                },
                "label_id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "ID de la etiqueta"
                },
                "printer_id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "ID de la impresora"
                },
                "status": {
                  "type": "string",
                  "description": "Estado del trabajo (pending)"
                }
              },
              "required": [
                "id",
                "label_id",
                "printer_id",
                "status"
              ]
            },
            "description": "Lista de trabajos creados"
          }
        },
        "required": [
          "message",
          "jobs"
        ]
      },
      "InforLabelClientRequest": {
        "type": "object",
        "properties": {
          "ClientId": {
            "type": "string",
            "format": "uuid",
            "description": "ID del cliente específico para la etiqueta"
          },
          "FilePath": {
            "type": "string",
            "description": "Identificador de la plantilla de etiqueta"
          },
          "Variables": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "Name": {
                  "type": "string",
                  "description": "Nombre de la variable"
                },
                "Value": {
                  "type": "string",
                  "description": "Valor de la variable"
                }
              },
              "required": [
                "Name",
                "Value"
              ]
            },
            "description": "Array de variables para la etiqueta",
            "minItems": 1
          },
          "PrinterName": {
            "type": "string",
            "description": "Nombre de la impresora"
          },
          "Copies": {
            "type": "integer",
            "description": "Número de copias a imprimir",
            "default": 1,
            "minimum": 1,
            "maximum": 100
          }
        },
        "required": [
          "ClientId",
          "FilePath",
          "Variables",
          "PrinterName"
        ]
      },
      "InforLabelClientResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Indica si la operación fue exitosa"
          },
          "message": {
            "type": "string",
            "description": "Mensaje descriptivo del resultado"
          },
          "data": {
            "type": "object",
            "properties": {
              "job_id": {
                "type": "string",
                "format": "uuid",
                "description": "ID del trabajo de impresión creado"
              },
              "label_id": {
                "type": "string",
                "format": "uuid",
                "description": "ID de la etiqueta utilizada"
              },
              "client_id": {
                "type": "string",
                "format": "uuid",
                "description": "ID del cliente"
              },
              "client_name": {
                "type": "string",
                "description": "Nombre del cliente"
              },
              "printer_id": {
                "type": "string",
                "format": "uuid",
                "description": "ID de la impresora"
              },
              "printer_name": {
                "type": "string",
                "description": "Nombre de la impresora"
              },
              "copies": {
                "type": "integer",
                "description": "Número de copias"
              },
              "status": {
                "type": "string",
                "description": "Estado del trabajo (pending)"
              },
              "external_reference": {
                "type": "string",
                "description": "Referencia externa única para trazabilidad"
              },
              "created_at": {
                "type": "string",
                "format": "date-time",
                "description": "Fecha de creación"
              }
            },
            "required": [
              "job_id",
              "label_id",
              "client_id",
              "client_name",
              "printer_id",
              "printer_name",
              "copies",
              "status",
              "external_reference",
              "created_at"
            ]
          }
        },
        "required": [
          "success",
          "message",
          "data"
        ]
      },
      "ApiInfo": {
        "type": "object",
        "properties": {
          "api_name": {
            "type": "string",
            "description": "Nombre de la API"
          },
          "version": {
            "type": "string",
            "description": "Versión de la API"
          },
          "description": {
            "type": "string",
            "description": "Descripción de la API"
          },
          "authentication": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string"
              },
              "how_to_get_token": {
                "type": "string"
              },
              "token_format": {
                "type": "string"
              },
              "token_expiration": {
                "type": "string"
              }
            }
          },
          "cors": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "allowed_origins": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "allowed_methods": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "allowed_headers": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "allow_credentials": {
                "type": "boolean"
              },
              "max_age": {
                "type": "integer"
              }
            }
          }
        },
        "required": [
          "api_name",
          "version",
          "description"
        ]
      }
    }
  },
  "security": [
    {
      "BearerAuth": []
    },
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Público",
      "description": "Endpoints públicos que no requieren autenticación"
    },
    {
      "name": "Etiquetas",
      "description": "Operaciones relacionadas con etiquetas"
    },
    {
      "name": "Clientes",
      "description": "Operaciones relacionadas con clientes"
    },
    {
      "name": "Impresión",
      "description": "Operaciones relacionadas con la impresión de etiquetas"
    },
    {
      "name": "Autenticación",
      "description": "Operaciones relacionadas con la autenticación"
    },
    {
      "name": "Integraciones Externas",
      "description": "Endpoints para integración con sistemas externos (solo API Key)"
    },
    {
      "name": "API Keys",
      "description": "Operaciones relacionadas con la gestión de API Keys"
    }
  ],
  "paths": {
    "/api/public/test": {
      "get": {
        "summary": "Endpoint público de prueba",
        "description": "Endpoint que no requiere autenticación para probar la API",
        "tags": [
          "Público"
        ],
        "responses": {
          "200": {
            "description": "Respuesta exitosa",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "api_version": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/public/info": {
      "get": {
        "summary": "Información sobre la API",
        "description": "Devuelve información detallada sobre la API y cómo utilizarla",
        "tags": [
          "Público"
        ],
        "responses": {
          "200": {
            "description": "Información de la API",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiInfo"
                }
              }
            }
          }
        }
      }
    },
    "/api/labels": {
      "get": {
        "summary": "Obtiene la lista de etiquetas",
        "description": "Devuelve la lista de etiquetas a las que el usuario tiene acceso",
        "tags": [
          "Etiquetas"
        ],
        "security": [
          {
            "BearerAuth": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de etiquetas obtenida exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Label"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/labels/{id}": {
      "get": {
        "summary": "Obtiene una etiqueta específica",
        "description": "Devuelve los detalles de una etiqueta específica",
        "tags": [
          "Etiquetas"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de la etiqueta"
          }
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Etiqueta obtenida exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Label"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Prohibido",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Etiqueta no encontrada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/labels/{id}/zpl": {
      "get": {
        "summary": "Obtiene el código ZPL de una etiqueta",
        "description": "Genera y devuelve el código ZPL para una etiqueta específica",
        "tags": [
          "Etiquetas",
          "Impresión"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de la etiqueta"
          }
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Código ZPL generado exitosamente",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Prohibido",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Etiqueta no encontrada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/clients": {
      "get": {
        "summary": "Obtiene la lista de clientes",
        "description": "Devuelve la lista de clientes a los que el usuario tiene acceso",
        "tags": [
          "Clientes"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de clientes obtenida exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Client"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/clients/{id}": {
      "get": {
        "summary": "Obtiene un cliente específico",
        "description": "Devuelve los detalles de un cliente específico",
        "tags": [
          "Clientes"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID del cliente"
          }
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Cliente obtenido exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Client"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Prohibido",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Cliente no encontrado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/labels/print": {
      "post": {
        "summary": "Genera e incrementa el contador de una etiqueta",
        "description": "Genera el código ZPL para una etiqueta e incrementa su contador si tiene uno. Permite imprimir múltiples etiquetas a la vez.",
        "tags": [
          "Etiquetas",
          "Impresión"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrintRequest"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Código ZPL generado exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrintResponse"
                }
              }
            }
          },
          "400": {
            "description": "Solicitud incorrecta",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Prohibido",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Etiqueta no encontrada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/auth-test": {
      "get": {
        "summary": "Verifica la autenticación",
        "description": "Endpoint para verificar si el token de autenticación es válido",
        "tags": [
          "Autenticación"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Token válido",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "user": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string",
                          "format": "email"
                        }
                      }
                    },
                    "token_info": {
                      "type": "object",
                      "properties": {
                        "expires_at": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "issued_at": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "expires_in": {
                          "type": "integer"
                        },
                        "role": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/print-jobs/{id}/zpl": {
      "get": {
        "summary": "Obtiene el código ZPL de un trabajo de impresión",
        "description": "Devuelve el código ZPL de un trabajo de impresión específico para enviarlo a la impresora. Opcionalmente, actualiza el estado del trabajo.",
        "tags": [
          "Impresión"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID del trabajo de impresión"
          },
          {
            "in": "query",
            "name": "update_status",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "printing",
                "completed"
              ]
            },
            "description": "Actualiza el estado del trabajo después de obtener el ZPL. Valores posibles: 'printing', 'completed'"
          }
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Código ZPL obtenido exitosamente",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "headers": {
              "Content-Type": {
                "schema": {
                  "type": "string",
                  "example": "text/plain"
                },
                "description": "Tipo de contenido de la respuesta"
              },
              "Content-Disposition": {
                "schema": {
                  "type": "string",
                  "example": "attachment; filename=\"print-job-550e8400-e29b-41d4-a716-446655440000.zpl\""
                },
                "description": "Cabecera para descargar el archivo"
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Trabajo de impresión no encontrado o no tiene ZPL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/print-jobs/pending": {
      "get": {
        "summary": "Obtiene los trabajos de impresión pendientes",
        "description": "Devuelve la lista de trabajos de impresión con estado \"pending\"",
        "tags": [
          "Impresión"
        ],
        "parameters": [
          {
            "in": "query",
            "name": "printer_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filtrar por impresora"
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "default": 10,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Número máximo de resultados"
          }
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de trabajos pendientes obtenida exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PrintJob"
                      }
                    },
                    "count": {
                      "type": "integer"
                    },
                    "links": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "zpl_url": {
                            "type": "string",
                            "format": "uri"
                          },
                          "update_url": {
                            "type": "string",
                            "format": "uri"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/print-jobs/{id}/status": {
      "post": {
        "summary": "Actualiza el estado de un trabajo de impresión",
        "description": "Actualiza el estado de un trabajo de impresión (pending, printing, completed, failed)",
        "tags": [
          "Impresión"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID del trabajo de impresión"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "pending",
                      "printing",
                      "completed",
                      "failed"
                    ]
                  },
                  "error_message": {
                    "type": "string",
                    "nullable": true
                  }
                },
                "required": [
                  "status"
                ]
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Estado actualizado exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PrintJob"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Datos inválidos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Trabajo de impresión no encontrado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/clients/{id}/print-jobs": {
      "get": {
        "summary": "Obtiene los trabajos de impresión de un cliente",
        "description": "Devuelve la lista de trabajos de impresión asociados a un cliente específico",
        "tags": [
          "Clientes",
          "Impresión"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID del cliente"
          },
          {
            "in": "query",
            "name": "status",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "printing",
                "completed",
                "failed"
              ]
            },
            "description": "Filtrar por estado"
          }
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de trabajos de impresión obtenida exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PrintJob"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "No tienes permiso para acceder a este cliente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Cliente no encontrado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Crea un nuevo trabajo de impresión para un cliente",
        "description": "Registra un nuevo trabajo de impresión asociado a una etiqueta del cliente",
        "tags": [
          "Clientes",
          "Impresión"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID del cliente"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "printer_id": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true
                  },
                  "copies": {
                    "type": "integer",
                    "default": 1,
                    "minimum": 1
                  },
                  "job_data": {
                    "type": "object",
                    "additionalProperties": true
                  }
                },
                "required": [
                  "label_id"
                ]
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "description": "Trabajo de impresión creado exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PrintJob"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Datos inválidos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "No tienes permiso para acceder a este cliente o etiqueta",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Cliente o etiqueta no encontrada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/print-jobs/batch-update": {
      "post": {
        "summary": "Actualiza el estado de múltiples trabajos de impresión",
        "description": "Actualiza el estado de varios trabajos de impresión a la vez",
        "tags": [
          "Impresión"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchUpdateRequest"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Estados actualizados exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchUpdateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Datos inválidos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/print-jobs/pending/create": {
      "post": {
        "summary": "Crea trabajos de impresión pendientes en lote",
        "description": "Crea múltiples trabajos de impresión con estado pendiente para una o varias etiquetas",
        "tags": [
          "Impresión"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PendingPrintJobRequest"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "description": "Trabajos de impresión creados exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PendingPrintJobResponse"
                }
              }
            }
          },
          "400": {
            "description": "Datos inválidos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/external/infor/create-label": {
      "post": {
        "summary": "Crea trabajos de impresión desde Infor WMS",
        "description": "Recibe datos de etiquetas desde Infor WMS y crea trabajos de impresión pendientes",
        "tags": [
          "Integraciones Externas"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InforLabelRequest"
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "201": {
            "description": "Trabajos de impresión creados exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InforLabelResponse"
                }
              }
            }
          },
          "400": {
            "description": "Datos inválidos o etiqueta no encontrada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No autorizado - API Key faltante, inválida o inactiva",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Impresora no encontrada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/external/infor/create-label-client": {
      "post": {
        "summary": "Crea trabajos de impresión desde Infor WMS con ClientId específico",
        "description": "Recibe datos de etiquetas desde Infor WMS con un ClientId específico y crea trabajos de impresión pendientes",
        "tags": [
          "Integraciones Externas"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InforLabelClientRequest"
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "201": {
            "description": "Trabajo de impresión creado exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InforLabelClientResponse"
                }
              }
            }
          },
          "400": {
            "description": "Datos inválidos, cliente o etiqueta no encontrada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No autorizado - API Key faltante, inválida o inactiva",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Cliente o impresora no encontrada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Error interno del servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/swagger.json": {
      "get": {
        "summary": "Descarga la especificación OpenAPI",
        "description": "Devuelve la especificación completa de la API en formato JSON para importar en herramientas como Postman, Insomnia, etc.",
        "tags": [
          "Público"
        ],
        "responses": {
          "200": {
            "description": "Especificación OpenAPI descargada exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Especificación OpenAPI 3.0"
                }
              }
            }
          }
        }
      }
    },
    "/api/docs": {
      "get": {
        "summary": "Documentación de la API",
        "description": "Devuelve la especificación OpenAPI para mostrar en la interfaz de documentación",
        "tags": [
          "Público"
        ],
        "responses": {
          "200": {
            "description": "Documentación obtenida exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Especificación OpenAPI 3.0"
                }
              }
            }
          }
        }
      }
    },
    "/api/keys/create": {
      "post": {
        "summary": "Crea una nueva API Key",
        "description": "Genera una nueva API Key para el usuario autenticado",
        "tags": [
          "API Keys"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nombre descriptivo para la API Key"
                  }
                },
                "required": [
                  "name"
                ]
              },
              "example": {
                "name": "Integración con Sistema ERP"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "API Key creada exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "key": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "id": "550e8400-e29b-41d4-a716-446655440000",
                  "key": "api_key_123456789abcdef",
                  "name": "Integración con Sistema ERP",
                  "created_at": "2023-01-01T00:00:00Z"
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/keys/list": {
      "get": {
        "summary": "Lista las API Keys",
        "description": "Devuelve la lista de API Keys del usuario autenticado",
        "tags": [
          "API Keys"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de API Keys obtenida exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "name": {
                            "type": "string"
                          },
                          "is_active": {
                            "type": "boolean"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/keys/revoke": {
      "post": {
        "summary": "Revoca una API Key",
        "description": "Desactiva una API Key existente",
        "tags": [
          "API Keys"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "ID de la API Key a revocar"
                  }
                },
                "required": [
                  "id"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "API Key revocada exitosamente",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "message": "API Key revocada exitosamente"
                }
              }
            }
          },
          "401": {
            "description": "No autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "API Key no encontrada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  }
}