Cómo implementar una API Flask o FastAPI en OuiPanel
Tiempo estimado: 15 minutos
Dificultad: Intermedia ⭐⭐
Tipo de servidor: Python
📋 Introducción
Esta guía explica cómo alojar una API REST desarrollada con Flask o FastAPI en OuiPanel. Su API estará disponible las 24 horas del día, los 7 días de la semana, con la posibilidad de agregar un nombre de dominio personalizado y HTTPS.
Flask vs FastAPI
| Criterio | Flask | FastAPI |
|---|---|---|
| Dificultad | Principiante | Intermedio |
| Instalación | Sencilla (sin compilación) | Pesada (compilación Rust) |
| Requisito de espacio en disco | ~100 MB | ~5 GB mínimo |
| Rendimiento | Bueno | Excelente (async) |
| Documentación automática | No (extensión) | Sí (Swagger/OpenAPI) |
| Validación de datos | Manual | Automática (Pydantic) |
| Ideal para | APIs simples, servidores pequeños | APIs modernas, servidores grandes |
💡 Recomendación: Si tiene un servidor con poco almacenamiento (< 5 GB), utilice Flask.
Lo que necesitas
| Requisito | Descripción |
|---|---|
| 📁 Tu código de API | Archivos Python (app.py, main.py...) |
| 🐍 Un servidor Python | Ordenado en OuiHeberg |
| 🌐 Un nombre de dominio | (Opcional) Para acceder mediante una URL personalizada |
💡 ¿Todavía no tienes un servidor Python?
Ordénalo en: https://www.ouiheberg.com/fr/hebergement-python
📁 Paso 1: Preparar los Archivos de la API
Structura de archivos
Tu API debe tener esta estructura:
📁 MiAPI/
├── 📄 app.py ← Archivo principal (o main.py)
├── 📄 requirements.txt ← Dependencias Python
├── 📄 .env ← Variables de entorno (creado en el servidor)
└── 📁 routes/ ← (Opcional) Carpeta de rutas
🌶️ Opción A: API con Flask
Archivo requirements.txt (Flask)
flask==2.3.3
python-dotenv==1.0.0
werkzeug==2.3.7
| Paquete | Descripción |
|---|---|
flask | Framework web minimalista |
python-dotenv | Cargar variables desde .env |
werkzeug | Utilidades WSGI (incluido con Flask) |
⚠️ Importante: Utilice estas versiones exactas para evitar problemas de compatibilidad.
Archivo principal (app.py) - Flask
import os
from dotenv import load_dotenv
# Cargar variables de entorno desde .env
load_dotenv()
from flask import Flask, jsonify, request
# Crear la aplicación Flask
app = Flask(__name__)
# ============================================
# RUTAS DE LA API
# ============================================
# Ruta principal
@app.route('/')
def home():
return jsonify({
'status': 'online',
'message': '¡Bienvenido a mi API Flask!',
'version': '1.0.0'
})
# Ruta de salud (health check)
@app.route('/health')
def health():
return jsonify({
'status': 'saludable',
'servicio': 'Mi API Flask'
})
# Ejemplo de datos (simulando una base de datos)
items = [
{'id': 1, 'name': 'Item 1', 'price': 10.99},
{'id': 2, 'name': 'Item 2', 'price': 24.99},
{'id': 3, 'name': 'Item 3', 'price': 5.49}
]
# GET todos los elementos
@app.route('/api/items', methods=['GET'])
def get_items():
return jsonify({
'success': True,
'data': items,
'count': len(items)
})
# GET un elemento por ID
@app.route('/api/items/<int:item_id>', methods=['GET'])
def get_item(item_id):
for item in items:
if item['id'] == item_id:
return jsonify({
'success': True,
'data': item
})
return jsonify({
'success': False,
'error': 'Elemento no encontrado'
}), 404
# POST crear un elemento
@app.route('/api/items', methods=['POST'])
def create_item():
data = request.get_json()
if not data or 'name' not in data:
return jsonify({
'success': False,
'error': 'El campo "name" es obligatorio'
}), 400
new_id = max(item['id'] for item in items) + 1 if items else 1
new_item = {
'id': new_id,
'name': data['name'],
'price': data.get('price', 0)
}
items.append(new_item)
return jsonify({
'success': True,
'message': 'Elemento creado exitosamente',
'data': new_item
}), 201
# PUT modificar un elemento
@app.route('/api/items/<int:item_id>', methods=['PUT'])
def update_item(item_id):
data = request.get_json()
for item in items:
if item['id'] == item_id:
item['name'] = data.get('name', item['name'])
item['price'] = data.get('price', item['price'])
return jsonify({
'success': True,
'message': 'Elemento modificado exitosamente',
'data': item
})
return jsonify({
'success': False,
'error': 'Elemento no encontrado'
}), 404
# DELETE eliminar un elemento
@app.route('/api/items/<int:item_id>', methods=['DELETE'])
def delete_item(item_id):
for index, item in enumerate(items):
if item['id'] == item_id:
items.pop(index)
return jsonify({
'success': True,
'message': f'Elemento {item_id} eliminado exitosamente'
})
return jsonify({
'success': False,
'error': 'Elemento no encontrado'
}), 404
# ============================================
# GESTIÓN DE ERRORES
# ============================================
@app.errorhandler(404)
def not_found(error):
return jsonify({
'success': False,
'error': 'Recurso no encontrado'
}), 404
@app.errorhandler(500)
def internal_error(error):
return jsonify({
'success': False,
'error': 'Error interno del servidor'
}), 500
# ============================================
# INICIO DEL SERVIDOR
# ============================================
if __name__ == '__main__':
# Puerto: usar SERVER_PORT (OuiPanel) o 5000 por defecto
port = int(os.getenv('SERVER_PORT', 5000))
# IMPORTANTE: Escuchar en 0.0.0.0 para OuiPanel
app.run(host='0.0.0.0', port=port)
⚠️ IMPORTANTE: La API debe escuchar en
0.0.0.0y no enlocalhosto127.0.0.1para ser accesible desde el exterior.
⚡ Opción B: API con FastAPI
⚠️ Atención: FastAPI requiere
pydanticque debe ser compilado. Esto requiere mucho espacio en disco (varios GB) durante la instalación. Si obtiene un errorNo space left on device, use Flask en su lugar o aumente el almacenamiento de su servidor.
Archivo requirements.txt (FastAPI)
fastapi==0.104.1
uvicorn==0.24.0
python-dotenv==1.0.0
| Paquete | Descripción |
|---|---|
fastapi | Framework web moderno y rápido |
uvicorn | Servidor ASGI para FastAPI |
python-dotenv | Cargar variables desde .env |
💡 Recomendación de almacenamiento: Reserve al menos 5 GB de almacenamiento libre para la instalación de FastAPI.
Archivo principal (app.py) - FastAPI
import os
from dotenv import load_dotenv
# Cargar variables de entorno desde .env
load_dotenv()
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional, List
# Crear la aplicación FastAPI
app = FastAPI(
title="Mi API FastAPI",
description="Una API REST moderna con FastAPI",
version="1.0.0",
docs_url="/docs", # Documentación Swagger
redoc_url="/redoc" # Documentación ReDoc
)
# ============================================
# MODELOS PYDANTIC (validación de datos)
# ============================================
class ItemCreate(BaseModel):
name: str
price: float = 0
description: Optional[str] = None
class Item(BaseModel):
id: int
name: str
price: float
description: Optional[str] = None
# ============================================
# DATOS DE EJEMPLO (simulando una base de datos)
# ============================================
items_db = [
{"id": 1, "name": "Item 1", "price": 10.99, "description": "Primer item"},
{"id": 2, "name": "Item 2", "price": 24.99, "description": "Segundo item"},
{"id": 3, "name": "Item 3", "price": 5.49, "description": "Tercer item"},
]
# ============================================
# RUTAS DE LA API
# ============================================
# Ruta principal
@app.get("/", tags=["General"])
async def home():
return {
"status": "online",
"message": "¡Bienvenido a mi API FastAPI!",
"version": "1.0.0",
"docs": "/docs"
}
# Ruta de salud (health check)
@app.get("/health", tags=["General"])
async def health():
return {
"status": "saludable",
"service": "Mi API FastAPI"
}
# GET todos los elementos
@app.get("/api/items", tags=["Items"])
async def get_items():
return {
"success": True,
"data": items_db,
"count": len(items_db)
}
# GET un elemento por ID
@app.get("/api/items/{item_id}", tags=["Items"])
async def get_item(item_id: int):
for item in items_db:
if item["id"] == item_id:
return {"success": True, "data": item}
raise HTTPException(status_code=404, detail="Elemento no encontrado")
# POST crear un elemento
@app.post("/api/items", status_code=201, tags=["Items"])
async def create_item(item: ItemCreate):
new_id = max(i["id"] for i in items_db) + 1 if items_db else 1
new_item = {
"id": new_id,
"name": item.name,
"price": item.price,
"description": item.description
}
items_db.append(new_item)
return {
"success": True,
"message": "Elemento creado exitosamente",
"data": new_item
}
# PUT modificar un elemento
@app.put("/api/items/{item_id}", tags=["Items"])
async def update_item(item_id: int, item: ItemCreate):
for index, existing_item in enumerate(items_db):
if existing_item["id"] == item_id:
updated_item = {
"id": item_id,
"name": item.name,
"price": item.price,
"description": item.description
}
items_db[index] = updated_item
return {
"success": True,
"message": "Elemento modificado exitosamente",
"data": updated_item
}
raise HTTPException(status_code=404, detail="Elemento no encontrado")
# DELETE eliminar un elemento
@app.delete("/api/items/{item_id}", tags=["Items"])
async def delete_item(item_id: int):
for index, item in enumerate(items_db):
if item["id"] == item_id:
items_db.pop(index)
return {"success": True, "message": f"Elemento {item_id} eliminado"}
raise HTTPException(status_code=404, detail="Elemento no encontrado")
# ============================================
# INICIO DEL SERVIDOR
# ============================================
if __name__ == "__main__":
import uvicorn
# Puerto: use SERVER_PORT (OuiPanel) or 8000 por defecto
port = int(os.getenv('SERVER_PORT', 8000))
# IMPORTANTE: Escuchar en 0.0.0.0 para OuiPanel
uvicorn.run(app, host="0.0.0.0", port=port)
💡 Bono FastAPI: ¡La documentación interactiva se genera automáticamente!
- Swagger UI:
http://your-ip:port/docs- ReDoc:
http://your-ip:port/redoc
📤 Paso 2: Subir los Archivos a OuiPanel
Mediante el Administrador de Archivos
- Inicie sesión en OuiPanel
- Seleccione su servidor Python
- En el menú lateral, haga clic en Administrador de archivos

- Elimine los archivos predeterminados (si los hay)
- Haga clic en Subir (Upload)
- Suba sus archivos:
app.py(omain.py)requirements.txt- Sus carpetas (
routes/,models/...) si es necesario

⚠️ No subir: El archivo
.envse creará directamente en el servidor (más seguro).
Mediante SFTP (Recomendado para varios archivos)
- Inicie sesión en SFTP con FileZilla
- Arrastre y suelte todo el contenido de su carpeta API
- Verifique que todos los archivos se hayan subido correctamente
📖 Consulte la guía "Acceso SFTP con FileZilla" para obtener instrucciones detalladas.
🔑 Paso 3: Crear el Archivo .env
Crear el archivo .env
- En el Administrador de archivos, haga clic en Nuevo archivo
- Nómbrelo
.env(con el punto delante) - Agregue sus variables:
# Configuración de la API
DEBUG=false
PORT=8000
# Base de datos (si es necesario)
DATABASE_URL=mysql://user:password@host:3306/database
# Claves API (ejemplos)
API_KEY=your_secret_api_key
SECRET_KEY=your_secret_key_for_jwt

- Haga clic en Crear o Guardar
⚠️ Importante:
- Sin espacios alrededor del
=- Sin comillas alrededor de valores simples
- No compartas nunca este archivo
⚙️ Paso 4: Configurar el Archivo de Inicio
OuiPanel necesita saber qué archivo de Python ejecutar al inicio.
Acceder a los ajustes
- En el menú lateral, haz clic en Configuración
- Haz clic en Ajustes del servidor

Configurar el archivo a ejecutar
Encuentra el campo Archivo a ejecutar (o Main File / Startup File):
| Tu archivo principal | Valor a ingresar |
|---|---|
app.py | app.py |
main.py | main.py |
api.py | api.py |
src/app.py | src/app.py |
⚠️ Importante: El nombre debe coincidir exactamente con tu archivo (distingue mayúsculas de minúsculas).
🚀 Paso 5: Iniciar la API
Iniciar el servidor
- En el menú lateral, haz clic en Consola
- Haz clic en Iniciar
Instalación automática de dependencias
En el primer inicio, el servidor instala automáticamente los paquetes:
Flask:
Installing requirements from requirements.txt...
Successfully installed flask-3.0.0 python-dotenv-1.0.0 gunicorn-21.2.0
Running app.py...
* Running on http://0.0.0.0:25639
FastAPI:
Installing requirements from requirements.txt...
Successfully installed fastapi-0.109.0 uvicorn-0.27.0 python-dotenv-1.0.0
Running app.py...
INFO: Uvicorn running on http://0.0.0.0:25639 ✅ Paso 6: Probar la API
Obtener la dirección
- Toma nota del puerto mostrado en la consola (ej:
25639) - Obtén la IP de tu servidor en la Vista Global
- La dirección de tu API es:
http://IP:PUERTO
Ejemplo: http://51.77.xxx.xxx:25639


Probar los endpoints
Con un navegador:
- Abre
http://51.77.xxx.xxx:25639/→ Debería mostrar el JSON de bienvenida - Abre
http://51.77.xxx.xxx:25639/health→ Comprobación de estado - (FastAPI) Abre
http://51.77.xxx.xxx:25639/docs→ Documentación Swagger
Con curl:
# GET - Página de inicio
curl http://51.77.xxx.xxx:25639/
# GET - Lista de elementos
curl http://51.77.xxx.xxx:25639/api/items
# GET - Un elemento específico
curl http://51.77.xxx.xxx:25639/api/items/1
# POST - Crear un elemento
curl -X POST http://51.77.xxx.xxx:25639/api/items \
-H "Content-Type: application/json" \
-d '{"name": "Nuevo elemento", "price": 29.99}'
# PUT - Modificar un elemento
curl -X PUT http://51.77.xxx.xxx:25639/api/items/1 \
-H "Content-Type: application/json" \
-d '{"name": "Elemento modificado", "price": 39.99}'
# DELETE - Eliminar un elemento
curl -X DELETE http://51.77.xxx.xxx:25639/api/items/1
Con Postman / Insomnia:
- Importa la URL base:
http://51.77.xxx.xxx:25639 - Prueba tus diferentes endpoints

🌐 Paso 7: Configurar un Nombre de Dominio (Proxy Manager)
Para acceder a tu API a través de una URL limpia con HTTPS (ej: https://api.monsite.com), utiliza el Proxy Manager.
Configurar el DNS
- En OuiPanel → Proxy Manager, toma nota de la IP del Proxy
- En tu registrador (OVH, Cloudflare, etc.), crea un registro DNS:
| Tipo | Nombre | Valor |
|---|---|---|
A | api | IP del Proxy |
Agregar el dominio en OuiPanel
- En el menú lateral, haz clic en Proxy Manager
- Haz clic en Agregar
- Rellena:
| Campo | Valor |
|---|---|
| Nombre de dominio | api.monsite.com |
| Puerto | El puerto de tu API (ej: 25639) |
| SSL | ✅ Activado |

- Haz clic en Crear la redirección
Resultado
Tu API ahora es accesible a través de:
- ✅
https://api.monsite.com(con HTTPS automático) - ✅ Certificado SSL gratuito (Let's Encrypt)
Ejemplo de llamada:
curl https://api.monsite.com/api/items
📖 Consulta la guía "Configurar un Nombre de Dominio con el Proxy Manager" para más detalles.
🗄️ Bonus: Conexión a una Base de Datos
MySQL con Flask (PyMySQL)
Agrega en requirements.txt:
pymysql==1.1.0
Ejemplo de conexión:
import pymysql
import os
# Conexión a MySQL
connection = pymysql.connect(
host=os.getenv('DB_HOST', 'localhost'),
user=os.getenv('DB_USER', 'root'),
password=os.getenv('DB_PASSWORD', ''),
database=os.getenv('DB_NAME', 'mydb'),
charset='utf8mb4'
)
# Ejemplo de consulta
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM items")
result = cursor.fetchall()
Variables .env a añadir:
DB_HOST=mysql-host.ouiheberg.com
DB_USER=tu_usuario
DB_PASSWORD=tu_contraseña
DB_NAME=tu_base
📖 Consulta la guía "Crear y Gestionar una Base de Datos MySQL" para crear tu base de datos.
🔧 Solución de Problemas
La API no se inicia
| ❌ Error | ✅ Solución |
|---|---|
ModuleNotFoundError: No module named 'flask' | Verifica requirements.txt y reinicia |
ModuleNotFoundError: No module named 'fastapi' | Verifica requirements.txt y reinicia |
ModuleNotFoundError: No module named 'dotenv' | Agrega python-dotenv en requirements.txt |
SyntaxError | Error en tu código Python |
Error "No space left on device" (FastAPI)
Este error ocurre cuando pydantic-core (dependencia de FastAPI) debe compilarse con Rust:
error: No space left on device (os error 28)
ERROR: Failed building wheel for pydantic-core
| ✅ Soluciones |
|---|
| 1. Utilice Flask en su lugar (no requiere compilación) |
| 2. Aumente el almacenamiento de su servidor (se recomiendan 5+ GB) |
| 3. Limpie los archivos temporales y vuelva a intentarlo |
💡 Recomendación: Para servidores pequeños con poco almacenamiento, Flask es más adecuado que FastAPI.
La API se inicia pero no es accesible
| ❌ Causa | ✅ Solución |
|---|---|
Escucha en localhost | Cambie a 0.0.0.0 |
| Puerto incorrecto | Utilice os.getenv('SERVER_PORT') |
Verifique su código:
# ❌ INCORRECTO - escucha solo localmente
app.run(host='localhost', port=5000)
app.run(host='127.0.0.1', port=5000)
# ✅ CORRECTO - escucha en todas las interfaces
app.run(host='0.0.0.0', port=port)
uvicorn.run(app, host='0.0.0.0', port=port)
Error 502 Bad Gateway (Proxy Manager)
| ❌ Causa | ✅ Solución |
|---|---|
| API no iniciada | Inicie el servidor en OuiPanel |
| Puerto incorrecto en Proxy Manager | Verifique el puerto configurado |
| API caída | Consulte la Consola |
El archivo .env no se está leyendo
| ❌ Causa | ✅ Solución |
|---|---|
| python-dotenv no instalado | Verifique requirements.txt |
| load_dotenv() no llamado | Agregue load_dotenv() al inicio del archivo |
| Archivo mal nombrado | El archivo debe llamarse exactamente .env |
Error CORS
Si llama a su API desde un frontend (React, Vue, etc.):
| ❌ Error | ✅ Solución |
|---|---|
Access-Control-Allow-Origin | Agregue Flask-CORS o CORSMiddleware (ver sección Seguridad) |
🔒 Seguridad
Archivo .env
| ✅ Por hacer | ❌ No hacer |
|---|---|
Crear el .env en el servidor | Subir el .env desde su PC |
Agregar .env al .gitignore | Hacer commit del .env en GitHub |
| Usar variables para secretos | Poner las claves API en el código |
Prácticas recomendadas de API
- ✅ Valide siempre las entradas de usuario
- ✅ Use HTTPS en producción (Proxy Manager)
- ✅ No exponga los errores detallados en producción
- ✅ Agregue una autenticación para rutas sensibles
Activar CORS (si es necesario)
Si su API es llamada desde un frontend (React, Vue, etc.) en otro dominio:
Flask - Agregue flask-cors:
# requirements.txt
flask-cors==4.0.0
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
FastAPI - El middleware ya está disponible:
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
📂 Estructura Avanzada (Recomendada)
Para una API más compleja, organice su código:
📁 MonAPI/
├── 📄 app.py ← Punto de entrada
├── 📄 requirements.txt
├── 📄 .env
├── 📁 routes/
│ ├── 📄 __init__.py
│ ├── 📄 items.py ← Rutas /api/items
│ └── 📄 users.py ← Rutas /api/users
├── 📁 models/
│ └── 📄 item.py ← Modelo Item
└── 📁 utils/
└── 📄 helpers.py ← Funciones utilitarias
💡 Para APIs grandes, esta estructura ayuda a organizar mejor el código y facilita el mantenimiento.
📝 Resumen
1. Elegir el framework (Flask o FastAPI)
2. Preparar los archivos (app.py + requirements.txt con python-dotenv)
3. Asegurarse de que el servidor escuche en 0.0.0.0:PUERTO
4. Subir los archivos a OuiPanel (sin el .env)
5. Crear el archivo .env en el servidor
6. Configurar el archivo de inicio (app.py, main.py...)
7. Iniciar el servidor
8. Probar a través de http://IP:PUERTO
9. (Opcional) Configurar el Proxy Manager para HTTPS
ENDPOINTS DE PRUEBA:
├── GET / → Página de inicio
├── GET /health → Verificación de estado
├── GET /api/items → Lista de items
├── GET /api/items/1 → Un item
├── POST /api/items → Crear un item
├── PUT /api/items/1 → Modificar un item
└── DELETE /api/items/1 → Eliminar un item
(FastAPI) Documentación automática:
├── /docs → Interfaz Swagger
└── /redoc → ReDoc
