{
  "openapi": "3.0.3",
  "info": {
    "title": "Autoreports API",
    "description": "API para gerenciamento de relatórios programados da Convert.\nGera e envia relatórios automatizados por email com gráficos, tabelas e exportações de dados (PDF/XLS).\n\n## Autenticação\nTodos os endpoints (exceto `/login` e `/auth/callback`) requerem um Bearer Token.\nOs tokens são criados via `/criarToken` e têm roles associadas:\n- `cliente` — acesso básico de leitura\n- `mailonly` — permissão para envio de emails\n- `monitor.convert` — acesso a monitoramento\n- `admin.convert` — acesso administrativo completo\n\n## Rate Limiting\nRequisições não autenticadas: 6 tentativas por hora por IP.\n",
    "version": "2.7.0",
    "contact": {
      "email": "rodolfo@convertcompany.com.br"
    }
  },
  "servers": [
    {
      "url": "/api",
      "description": "API principal"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "msg": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "data": {
            "oneOf": [
              {
                "type": "array",
                "items": {}
              },
              {
                "type": "object"
              },
              {
                "type": "string"
              }
            ]
          }
        }
      },
      "ValidationErrorResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "example": "Foram encontradas inconsistências na entrada"
          },
          "status": {
            "type": "integer",
            "example": 400
          },
          "data": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        }
      },
      "PaginationMeta": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer"
          },
          "per_page": {
            "type": "integer"
          },
          "current_page": {
            "type": "integer"
          },
          "last_page": {
            "type": "integer"
          },
          "first_page_url": {
            "type": "string"
          },
          "last_page_url": {
            "type": "string"
          },
          "next_page_url": {
            "type": "string",
            "nullable": true
          },
          "prev_page_url": {
            "type": "string",
            "nullable": true
          },
          "path": {
            "type": "string"
          },
          "from": {
            "type": "integer"
          },
          "to": {
            "type": "integer"
          }
        }
      },
      "Conexao": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "driver": {
            "type": "string"
          },
          "host": {
            "type": "string"
          },
          "port": {
            "type": "string"
          },
          "db_name": {
            "type": "string"
          },
          "descricao": {
            "type": "string"
          },
          "omnichannel_url": {
            "type": "string",
            "nullable": true
          },
          "omnichannel_descricao": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Empresa": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "nome": {
            "type": "string"
          },
          "nome_config": {
            "type": "string"
          },
          "dominio": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "conexao": {
            "$ref": "#/components/schemas/Conexao"
          }
        }
      },
      "Bloco": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "nome": {
            "type": "string"
          },
          "nomereal": {
            "type": "string"
          },
          "tipo": {
            "type": "string",
            "enum": [
              "tabela",
              "grafico",
              "xls"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Parametro": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "nome": {
            "type": "string"
          },
          "nomereal": {
            "type": "string"
          },
          "tipo": {
            "type": "string",
            "enum": [
              "array",
              "hora",
              "valor"
            ]
          },
          "valorpadrao": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Modelo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "nome": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "blocos": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "nome": {
                  "type": "string"
                },
                "nomereal": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Envio": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "nome": {
            "type": "string"
          },
          "destino_cc": {
            "type": "string"
          },
          "destino_cco": {
            "type": "string",
            "nullable": true
          },
          "periodo": {
            "type": "string",
            "enum": [
              "diario",
              "semanal",
              "mensal",
              "hoje",
              "quinzenal"
            ]
          },
          "horario_envio": {
            "type": "string",
            "nullable": true
          },
          "empresa_id": {
            "type": "integer"
          },
          "conexao_id": {
            "type": "integer"
          },
          "assunto": {
            "type": "string",
            "nullable": true
          },
          "ativo": {
            "type": "boolean"
          },
          "is_forcado": {
            "type": "boolean"
          },
          "status_envio": {
            "type": "integer",
            "description": "Códigos de status:\n- 999: Processando\n- 200: Enviado com sucesso\n- 301: Sem dados disponíveis\n- 302: Precisa revisão manual\n- 600: Falhou (será reprocessado)\n"
          },
          "exibir_quadro_mudanca_ar": {
            "type": "boolean"
          },
          "ultimo_envio": {
            "type": "string",
            "nullable": true,
            "description": "Formato d/m/Y H:i:s"
          },
          "id_modelo": {
            "type": "integer",
            "nullable": true
          },
          "blocos_individuais": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "parametros_de_envio": {
            "type": "object",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ConexaoEmpresasEnvio": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "empresa_id": {
            "type": "integer"
          },
          "driver": {
            "type": "string"
          },
          "host": {
            "type": "string"
          },
          "port": {
            "type": "string"
          },
          "db_name": {
            "type": "string"
          },
          "descricao": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  },
  "paths": {
    "/login": {
      "get": {
        "tags": [
          "Autenticação"
        ],
        "summary": "Obter URL de redirecionamento OAuth (Azure)",
        "security": [],
        "responses": {
          "200": {
            "description": "URL de redirecionamento gerada",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "msg": {
                      "type": "string",
                      "example": "Redirect URL"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "type": "string",
                      "example": "https://login.microsoftonline.com/..."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/auth/callback": {
      "post": {
        "tags": [
          "Autenticação"
        ],
        "summary": "Callback OAuth — autentica usuário e retorna token",
        "security": [],
        "responses": {
          "200": {
            "description": "Usuário autenticado com sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "msg": {
                      "type": "string",
                      "example": "Usuário autenticado"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "user": {
                          "type": "string",
                          "example": "user@example.com"
                        },
                        "token": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/logout": {
      "post": {
        "tags": [
          "Autenticação"
        ],
        "summary": "Invalida o token atual e encerra a sessão",
        "responses": {
          "200": {
            "description": "Logout bem-sucedido",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "msg": {
                      "type": "string",
                      "example": "Logout bem-sucedido"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "type": "array",
                      "items": {}
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/criarToken": {
      "post": {
        "tags": [
          "Autenticação"
        ],
        "summary": "Criar token de acesso para um usuário",
        "description": "Requer role `admin.convert`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "name",
                  "ability",
                  "expiration"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 255,
                    "description": "Deve existir na tabela users"
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "ability": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Role do token (cliente, mailonly, monitor.convert, admin.convert)"
                  },
                  "expiration": {
                    "type": "integer",
                    "maximum": 365,
                    "description": "Dias até expiração. Use -1 para sem expiração."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Token criado",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "msg": {
                      "type": "string",
                      "example": "Token criado: "
                    },
                    "status": {
                      "type": "integer",
                      "example": 201
                    },
                    "data": {
                      "type": "string",
                      "description": "Token gerado"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Dados inválidos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Não autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/revokeToken": {
      "delete": {
        "tags": [
          "Autenticação"
        ],
        "summary": "Revogar token de acesso",
        "description": "Requer role `admin.convert`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id"
                ],
                "properties": {
                  "id": {
                    "type": "integer",
                    "description": "ID do token a revogar"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token revogado",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "msg": {
                      "type": "string",
                      "example": "Token revogado com sucesso"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        },
                        "name": {
                          "type": "string"
                        },
                        "abilities": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "expires_at": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/empresas": {
      "get": {
        "tags": [
          "Empresas"
        ],
        "summary": "Listar ou buscar empresas",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Retorna apenas a empresa com este ID"
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 50
            },
            "description": "Busca textual pelo nome"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "id",
                "created_at",
                "updated_at"
              ]
            }
          },
          {
            "name": "order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          },
          {
            "name": "show_all",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "Retorna todos os registros sem paginação"
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Empresa(s) encontrada(s)",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "description": "Resultado único",
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "integer",
                          "example": 200
                        },
                        "message": {
                          "type": "string"
                        },
                        "data": {
                          "$ref": "#/components/schemas/Empresa"
                        }
                      }
                    },
                    {
                      "description": "Lista paginada",
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/PaginationMeta"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "msg": {
                              "type": "string"
                            },
                            "status": {
                              "type": "integer",
                              "example": 200
                            },
                            "data": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/Empresa"
                              }
                            }
                          }
                        }
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Empresas"
        ],
        "summary": "Criar, atualizar ou excluir empresa",
        "description": "- **Criar**: omitir `id` e `delete`\n- **Atualizar**: incluir `id`\n- **Excluir**: incluir `id` e `\"delete\": true`\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "integer",
                    "description": "Incluir para atualizar ou excluir"
                  },
                  "delete": {
                    "type": "boolean",
                    "description": "true para excluir"
                  },
                  "nome": {
                    "type": "string",
                    "maxLength": 50
                  },
                  "nome_config": {
                    "type": "string",
                    "maxLength": 50
                  },
                  "dominio": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "conexao": {
                    "type": "object",
                    "properties": {
                      "driver": {
                        "type": "string",
                        "maxLength": 50
                      },
                      "host": {
                        "type": "string",
                        "maxLength": 50
                      },
                      "port": {
                        "type": "string",
                        "maxLength": 50
                      },
                      "db_name": {
                        "type": "string",
                        "maxLength": 50
                      },
                      "username": {
                        "type": "string",
                        "maxLength": 50
                      },
                      "password": {
                        "type": "string",
                        "maxLength": 50
                      },
                      "descricao": {
                        "type": "string",
                        "maxLength": 50
                      },
                      "omnichannel_url": {
                        "type": "string",
                        "maxLength": 60,
                        "nullable": true
                      },
                      "omnichannel_descricao": {
                        "type": "string",
                        "maxLength": 90
                      },
                      "omnichannel_x_user_id": {
                        "type": "string",
                        "maxLength": 50
                      },
                      "omnichannel_token": {
                        "type": "string",
                        "maxLength": 255
                      },
                      "omnichannel_bearer_token": {
                        "type": "string",
                        "maxLength": 255
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Operação bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Empresa"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Dados inválidos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/atualizarconexao": {
      "post": {
        "tags": [
          "Empresas"
        ],
        "summary": "Atualizar conexão de uma empresa",
        "description": "Requer role `admin.convert`",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "conexao"
                ],
                "properties": {
                  "id": {
                    "type": "integer"
                  },
                  "conexao": {
                    "type": "object",
                    "properties": {
                      "driver": {
                        "type": "string"
                      },
                      "host": {
                        "type": "string"
                      },
                      "port": {
                        "type": "string"
                      },
                      "db_name": {
                        "type": "string"
                      },
                      "username": {
                        "type": "string"
                      },
                      "password": {
                        "type": "string"
                      },
                      "descricao": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conexão atualizada",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Conexao"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/blocos": {
      "get": {
        "tags": [
          "Blocos"
        ],
        "summary": "Listar blocos disponíveis",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Retorna apenas o bloco com este ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Bloco(s) encontrado(s)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/Bloco"
                        },
                        {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Bloco"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Blocos"
        ],
        "summary": "Criar, atualizar ou excluir bloco",
        "description": "- **Criar**: omitir `id` e `delete`\n- **Atualizar**: incluir `id`\n- **Excluir**: incluir `id` e `\"delete\": true`\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "integer"
                  },
                  "delete": {
                    "type": "boolean"
                  },
                  "nome": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "nomereal": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "tipo": {
                    "type": "string",
                    "enum": [
                      "tabela",
                      "grafico",
                      "xls"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Operação bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "$ref": "#/components/schemas/Bloco"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Dados inválidos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/parametros": {
      "get": {
        "tags": [
          "Parâmetros"
        ],
        "summary": "Listar parâmetros disponíveis",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Retorna apenas o parâmetro com este ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Parâmetro(s) encontrado(s)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/Parametro"
                        },
                        {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Parametro"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Parâmetros"
        ],
        "summary": "Criar, atualizar ou excluir parâmetro",
        "description": "- **Criar**: omitir `id` e `delete`\n- **Atualizar**: incluir `id`\n- **Excluir**: incluir `id` e `\"delete\": true`\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "integer"
                  },
                  "delete": {
                    "type": "boolean"
                  },
                  "nome": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "nomereal": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "tipo": {
                    "type": "string",
                    "enum": [
                      "array",
                      "hora",
                      "valor"
                    ]
                  },
                  "valorpadrao": {
                    "type": "string",
                    "maxLength": 255
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Operação bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "$ref": "#/components/schemas/Parametro"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Dados inválidos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/parametroblocos": {
      "get": {
        "tags": [
          "Parâmetros"
        ],
        "summary": "Listar associações parâmetro-bloco",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Filtrar pelo ID do bloco"
          }
        ],
        "responses": {
          "200": {
            "description": "Associações encontradas",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer"
                      },
                      "id_bloco": {
                        "type": "integer"
                      },
                      "id_parametro": {
                        "type": "integer"
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "updated_at": {
                        "type": "string",
                        "format": "date-time"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Parâmetros"
        ],
        "summary": "Associar parâmetro a um bloco",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id_bloco",
                  "id_parametro"
                ],
                "properties": {
                  "id_bloco": {
                    "type": "integer"
                  },
                  "id_parametro": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Parâmetro associado ao bloco",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/modelos": {
      "get": {
        "tags": [
          "Modelos"
        ],
        "summary": "Listar modelos com seus blocos",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Retorna apenas o modelo com este ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Modelo(s) encontrado(s)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/Modelo"
                        },
                        {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Modelo"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Modelos"
        ],
        "summary": "Criar, atualizar ou excluir modelo",
        "description": "- **Criar**: omitir `id` e `delete`\n- **Atualizar**: incluir `id`\n- **Excluir**: incluir `id` e `\"delete\": true`\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "integer"
                  },
                  "delete": {
                    "type": "boolean"
                  },
                  "nome": {
                    "type": "string"
                  },
                  "blocos": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Lista de `nomereal` dos blocos a associar"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Operação bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Bloco"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/envios": {
      "get": {
        "tags": [
          "Envios"
        ],
        "summary": "Listar ou buscar envios (relatórios agendados)",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Retorna apenas o envio com este ID"
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 255
            },
            "description": "Busca textual pelo nome"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "id",
                "updated_at",
                "created_at"
              ]
            }
          },
          {
            "name": "order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          },
          {
            "name": "id_empresa",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Filtrar por empresa"
          },
          {
            "name": "parametros_de_envio",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por parâmetros de envio"
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 15
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Envio(s) encontrado(s)",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "description": "Resultado único",
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "status": {
                          "type": "integer",
                          "example": 200
                        },
                        "data": {
                          "$ref": "#/components/schemas/Envio"
                        }
                      }
                    },
                    {
                      "description": "Lista paginada",
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/PaginationMeta"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "message": {
                              "type": "string"
                            },
                            "status": {
                              "type": "integer",
                              "example": 200
                            },
                            "data": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/Envio"
                              }
                            }
                          }
                        }
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Envios"
        ],
        "summary": "Criar, atualizar ou excluir envio",
        "description": "- **Criar**: omitir `id` e `delete`\n- **Atualizar**: incluir `id`\n- **Excluir**: incluir `id` e `\"delete\": true`\n\nUm envio deve ter `id_modelo` **ou** `blocos_individuais`, não ambos.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "integer"
                  },
                  "delete": {
                    "type": "boolean"
                  },
                  "nome": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "destino_cc": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Endereços de email separados por vírgula (CC)"
                  },
                  "destino_cco": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Endereços de email separados por vírgula (CCO)"
                  },
                  "periodo": {
                    "type": "string",
                    "enum": [
                      "diario",
                      "semanal",
                      "mensal",
                      "hoje",
                      "quinzenal"
                    ]
                  },
                  "empresa_id": {
                    "type": "integer"
                  },
                  "assunto": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "horario_envio": {
                    "type": "string",
                    "description": "Horário no formato HH:MM"
                  },
                  "ativo": {
                    "type": "boolean"
                  },
                  "exibir_quadro_mudanca_ar": {
                    "type": "boolean"
                  },
                  "id_modelo": {
                    "type": "integer",
                    "description": "ID do modelo de relatório a usar"
                  },
                  "blocos_individuais": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Lista de blocos individuais (alternativa ao id_modelo)"
                  },
                  "parametros_de_envio": {
                    "type": "object",
                    "description": "Parâmetros adicionais de envio como chave-valor"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Operação bem-sucedida",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "$ref": "#/components/schemas/Envio"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Dados inválidos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/forcarenvioteste": {
      "post": {
        "tags": [
          "Envios"
        ],
        "summary": "Forçar envio de teste imediato",
        "description": "Requer role `admin.convert`. Despacha o relatório imediatamente para teste.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id"
                ],
                "properties": {
                  "id": {
                    "type": "integer",
                    "description": "ID do envio a ser forçado"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Envio forçado com sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "msg": {
                      "type": "string",
                      "example": "Envio forçado e processado"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "type": "array",
                      "items": {}
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/proximosenvios": {
      "get": {
        "tags": [
          "Envios"
        ],
        "summary": "Listar próximos envios agendados",
        "description": "Retorna até 30 envios ativos futuros, ordenados por data de próximo envio. Períodos suportados: diario, semanal, mensal, hoje.",
        "responses": {
          "200": {
            "description": "Lista de próximos envios",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Os próximos envios são:"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id_envio": {
                            "type": "integer"
                          },
                          "nome": {
                            "type": "string"
                          },
                          "assunto": {
                            "type": "string",
                            "nullable": true
                          },
                          "destino_cc": {
                            "type": "string"
                          },
                          "destino_cco": {
                            "type": "string",
                            "nullable": true
                          },
                          "empresa": {
                            "type": "string",
                            "description": "Nome da empresa"
                          },
                          "prox_envio": {
                            "type": "string",
                            "format": "date-time",
                            "description": "Data/hora do próximo envio agendado"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/verificaenvio": {
      "get": {
        "tags": [
          "Envios"
        ],
        "summary": "Verificar status de um envio",
        "description": "Retorna o código de status atual do envio com base no período e último envio registrado.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "ID do envio a verificar"
          }
        ],
        "responses": {
          "200": {
            "description": "Código de status do envio: 200 (enviado), 301 (sem dados), 600 (falhou). Retorna mensagem de erro em caso de envio não encontrado.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "integer",
                      "enum": [
                        200,
                        301,
                        600
                      ],
                      "description": "Código de status do envio"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "Mensagem": {
                          "type": "string"
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/consultarenvioscomfalha": {
      "get": {
        "tags": [
          "Envios"
        ],
        "summary": "Listar envios com falha",
        "description": "Requer role `monitor.convert`. Retorna todos os envios com `status_envio = 600`.",
        "responses": {
          "200": {
            "description": "Envios com status de falha",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Os envios com falha são os seguintes: "
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Envio"
                      }
                    },
                    "qtde": {
                      "type": "integer",
                      "description": "Quantidade de envios com falha"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Envios"
        ],
        "summary": "Forçar reenvio de todos os envios com falha",
        "description": "Requer role `monitor.convert`. Marca todos os envios com `status_envio = 600` (exceto período `hoje`) como `is_forcado = 1` para reprocessamento.",
        "responses": {
          "200": {
            "description": "Envios forçados com sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Os envios forçados foram os seguintes: "
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Envio"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/reconhecerstatusenvio": {
      "post": {
        "tags": [
          "Envios"
        ],
        "summary": "Reconhecer falha e marcar envio para revisão manual",
        "description": "Requer role `admin.convert`. Atualiza `status_envio` para 302 (precisa revisão manual), retirando o envio do ciclo automático de retry.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id"
                ],
                "properties": {
                  "id": {
                    "type": "integer",
                    "description": "ID do envio a reconhecer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Status atualizado para 302",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Status de Envio atualizado para o envio 42"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "$ref": "#/components/schemas/Envio"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Envio não encontrado ou erro",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/forcarenvio": {
      "post": {
        "tags": [
          "Envios"
        ],
        "summary": "Forçar envio imediato",
        "description": "Despacha o job de geração e envio do relatório imediatamente. Falha se o envio já estiver em processamento (status 999).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id"
                ],
                "properties": {
                  "id": {
                    "type": "integer",
                    "description": "ID do envio (deve existir na tabela envios)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Envio forçado com sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Envio Forçado com sucesso."
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "$ref": "#/components/schemas/Envio"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Envio já está em processamento ou ID inválido",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/forcarenvioespecifico": {
      "post": {
        "tags": [
          "Envios"
        ],
        "summary": "Forçar envio com período de datas específico",
        "description": "Despacha o job `ForcarEnvioJob` usando um intervalo de datas customizado em vez do período configurado no envio.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "data_inicio",
                  "data_fim"
                ],
                "properties": {
                  "id": {
                    "type": "integer",
                    "description": "ID do envio"
                  },
                  "data_inicio": {
                    "type": "string",
                    "format": "date",
                    "example": "2024-01-01",
                    "description": "Data inicial no formato YYYY-MM-DD"
                  },
                  "data_fim": {
                    "type": "string",
                    "format": "date",
                    "example": "2024-01-31",
                    "description": "Data final no formato YYYY-MM-DD"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Envio específico enfileirado com sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "O envio 42 será enviado agora."
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "$ref": "#/components/schemas/Envio"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Dados inválidos ou envio não encontrado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/conexaoempresasenvio": {
      "get": {
        "tags": [
          "Conexões"
        ],
        "summary": "Obter conexão de uma empresa",
        "parameters": [
          {
            "name": "empresa_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Conexão encontrada",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "$ref": "#/components/schemas/ConexaoEmpresasEnvio"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Conexões"
        ],
        "summary": "Criar conexão de empresa",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "driver",
                  "host",
                  "port",
                  "db_name",
                  "username",
                  "password",
                  "empresa_id",
                  "descricao"
                ],
                "properties": {
                  "driver": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "host": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "port": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "db_name": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "username": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "password": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "empresa_id": {
                    "type": "integer"
                  },
                  "descricao": {
                    "type": "string",
                    "maxLength": 255
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Conexão criada",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "Mensagem": {
                      "type": "string",
                      "example": "Conexão estabelecida"
                    },
                    "Dados": {
                      "$ref": "#/components/schemas/ConexaoEmpresasEnvio"
                    },
                    "status": {
                      "type": "integer",
                      "example": 201
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/sendMail": {
      "post": {
        "tags": [
          "Email"
        ],
        "summary": "Enviar email com anexos opcionais",
        "description": "Requer role `mailonly` ou `admin.convert`. O email é enfileirado para envio assíncrono.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "from",
                  "cc",
                  "subject",
                  "body"
                ],
                "properties": {
                  "from": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 100
                  },
                  "from_name": {
                    "type": "string",
                    "maxLength": 100,
                    "nullable": true
                  },
                  "cc": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 100,
                    "description": "Destinatário principal"
                  },
                  "ccos": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "email"
                    },
                    "description": "Destinatários em cópia oculta"
                  },
                  "subject": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "body": {
                    "type": "string",
                    "description": "Corpo do email (suporta HTML)"
                  },
                  "attachments": {
                    "type": "array",
                    "nullable": true,
                    "items": {
                      "type": "string",
                      "format": "binary"
                    },
                    "description": "Arquivos anexos (máx. 50 MB cada).\nTipos permitidos: pdf, doc, docx, xls, xlsx, csv, txt, jpg, jpeg, png, gif\n"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Email enfileirado com sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "msg": {
                      "type": "string",
                      "example": "Email enfileirado com sucesso"
                    },
                    "status": {
                      "type": "integer",
                      "example": 202
                    },
                    "data": {
                      "type": "array",
                      "items": {}
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Dados inválidos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Não autorizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/parametrosgerais": {
      "get": {
        "tags": [
          "Parâmetros"
        ],
        "summary": "Obter parâmetros gerais de um envio",
        "description": "Retorna um mapa chave-valor com os parâmetros gerais associados ao envio informado. As chaves são os `nomereal` dos parâmetros.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "ID do envio"
          }
        ],
        "responses": {
          "200": {
            "description": "Mapa de parâmetros gerais (nomereal → valor)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "string"
                  },
                  "example": {
                    "data_inicio": "2024-01-01",
                    "data_fim": "2024-01-31"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/parametrosespecificos": {
      "get": {
        "tags": [
          "Parâmetros"
        ],
        "summary": "Obter parâmetros específicos de um envio por bloco",
        "description": "Retorna um objeto aninhado organizado por `id_bloco` → `id_parametro` → valor.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "ID do envio"
          }
        ],
        "responses": {
          "200": {
            "description": "Parâmetros organizados por bloco (id_bloco → id_parametro → valor)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "3": {
                      "7": "08:00",
                      "8": "18:00"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/obterparametros": {
      "get": {
        "tags": [
          "Parâmetros"
        ],
        "summary": "Obter parâmetros associados a blocos específicos",
        "description": "Recebe uma lista de `nomereal` de blocos separada por vírgula e retorna os parâmetros configurados para cada um.",
        "parameters": [
          {
            "name": "blocos",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Lista de nomereal dos blocos separada por vírgula. Ex: ligacoesporhora,tabelaagentes",
            "example": "ligacoesporhora,tabelaagentes"
          }
        ],
        "responses": {
          "200": {
            "description": "Parâmetros por bloco",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Parâmetros para os blocos: "
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "data": {
                      "type": "object",
                      "description": "Objeto com chaves sendo o nomereal de cada bloco",
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "$ref": "#/components/schemas/Parametro"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bloco não encontrado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/enviosblocos": {
      "get": {
        "tags": [
          "Blocos"
        ],
        "summary": "Listar blocos individuais associados a um envio",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "ID do envio"
          }
        ],
        "responses": {
          "200": {
            "description": "Blocos associados ao envio",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "message": {
                      "type": "string",
                      "example": "Blocos associados ao envio 42"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "blocos": {
                            "type": "string",
                            "description": "nomereal do bloco"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Envio não encontrado ou sem blocos individuais",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/modelosblocos": {
      "get": {
        "tags": [
          "Modelos"
        ],
        "summary": "Listar associações modelo-bloco",
        "description": "Endpoint interno usado pelo sistema. Retorna associações da tabela `modelo_blocos`.",
        "responses": {
          "200": {
            "description": "Associações modelo-bloco",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/obternomesblocosmodelos": {
      "get": {
        "tags": [
          "Modelos"
        ],
        "summary": "Obter blocos relacionados a um modelo",
        "description": "Consulta a tabela `modelo_blocos` com JOIN em `modelos` e `blocos`, retornando nome do modelo e os blocos vinculados.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "ID do modelo"
          },
          {
            "name": "nomereal",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrar por nomereal do bloco (opcional)"
          },
          {
            "name": "tipo",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "tabela",
                "grafico",
                "xls"
              ]
            },
            "description": "Filtrar por tipo de bloco (opcional)"
          }
        ],
        "responses": {
          "200": {
            "description": "Blocos relacionados ao modelo",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "modelo_nome": {
                            "type": "string",
                            "description": "Nome do modelo"
                          },
                          "nomebloco": {
                            "type": "string",
                            "description": "nomereal do bloco"
                          },
                          "tipo": {
                            "type": "string",
                            "enum": [
                              "tabela",
                              "grafico",
                              "xls"
                            ]
                          }
                        }
                      }
                    },
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Erro interno",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/jsonconfig": {
      "get": {
        "tags": [
          "Configuração"
        ],
        "summary": "Obter configuração JSON no formato Zabbix",
        "description": "Requer role `monitor.convert`. Retorna dados de envios de uma empresa no formato de discovery do Zabbix (macros {#IDEMAIL}, {#EMAIL}, etc.).",
        "parameters": [
          {
            "name": "empresa",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "nome_config da empresa (campo `nome_config` na tabela empresas)",
            "example": "empresa_abc"
          }
        ],
        "responses": {
          "200": {
            "description": "JSON de configuração no formato Zabbix",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "{#IDEMAIL}": {
                            "type": "integer",
                            "description": "ID do envio"
                          },
                          "{#EMAIL}": {
                            "type": "string",
                            "description": "Destinatário principal do envio"
                          },
                          "{#PERIODO}": {
                            "type": "string",
                            "description": "Período do envio"
                          },
                          "{#EMPRESA}": {
                            "type": "string",
                            "description": "nome_config da empresa"
                          },
                          "{#HORA_CHECK}": {
                            "type": "string",
                            "description": "Horário de checagem gerado aleatoriamente para o Zabbix"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Autenticação",
      "description": "Login, logout e gerenciamento de tokens de acesso"
    },
    {
      "name": "Empresas",
      "description": "Gerenciamento de empresas clientes e suas conexões de banco de dados"
    },
    {
      "name": "Blocos",
      "description": "Blocos de relatórios (tabelas, gráficos, exportações XLS)"
    },
    {
      "name": "Parâmetros",
      "description": "Parâmetros configuráveis para blocos e envios"
    },
    {
      "name": "Modelos",
      "description": "Templates de relatórios compostos por blocos"
    },
    {
      "name": "Envios",
      "description": "Relatórios agendados — criação, edição e monitoramento"
    },
    {
      "name": "Conexões",
      "description": "Conexões de banco de dados das empresas"
    },
    {
      "name": "Email",
      "description": "Envio avulso de emails com anexos"
    },
    {
      "name": "Configuração",
      "description": "Configuração e monitoramento do sistema"
    }
  ]
}