Visión General
La autenticación en las APIs de Imagina Energía se basa en el estándar JSON Web Token (JWT). Cada solicitud a endpoints protegidos debe incluir un token JWT válido en el encabezado de autorización.
- Un token JWT válido (obtenido mediante autenticación)
- Permisos configurados en tu cuenta de usuario
- Conocer el ambiente correcto (PRE o Producción)
Obtener un Token JWT
Para obtener tu token JWT, debes autenticarte con tus credenciales en el endpoint de autenticación.
Endpoint de Autenticación
Solicitud de Login
Envía tus credenciales en formato JSON:
curl -X POST https://oezimzeqmtmncuipqgwd.supabase.co/functions/v1/initiateauthcommand \
-H "Content-Type: application/json" \
-d '{
"email": "tu_usuario@ejemplo.com",
"password": "tu_contraseña"
}'
Respuesta Exitosa
Si las credenciales son correctas, recibirás:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 3600
}
expires_in indica la validez del token en segundos (normalmente 1 hora).
Usar el Token en tus Peticiones
Una vez obtenido el token, debes incluirlo en el encabezado Authorization
de todas las solicitudes a endpoints protegidos.
Formato del Encabezado
Authorization: Bearer <tu_token_jwt>
Ejemplo de Solicitud
Consultando un contrato:
curl -X GET "https://pre-webhooks.imaginaenergia.com/contrato?contrato_id=12345" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Validez del Token
⏰ Duración del Token:
- Los tokens tienen un tiempo de expiración limitado (normalmente 1 hora)
- Cuando un token expira, recibirás un error
401 Unauthorized - Deberás autenticarte nuevamente para obtener un token fresco
Impersonación de Canal
La impersonación de canal te permite realizar operaciones en nombre de un canal específico, en lugar de usar tu canal por defecto. Esto es útil cuando gestionas múltiples canales o necesitas realizar operaciones administrativas.
Requisitos para Impersonar
Para poder impersonar un canal necesitas:
- El permiso
impersonar_canalasignado a tu usuario - Un ID de permiso específico (UUID) proporcionado por el administrador
X-Canal debe ser el ID del permiso (UUID),
NO el ID del canal directamente. Este UUID te lo proporciona el administrador del sistema.
Cómo Impersonar un Canal
Incluye el encabezado X-Canal con el ID de permiso en tu solicitud:
curl -X GET "https://pre-webhooks.imaginaenergia.com/contrato?contrato_id=12345" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "X-Canal: 550e8400-e29b-41d4-a716-446655440000"
Comportamiento de la Impersonación
| Escenario | Comportamiento |
|---|---|
| Sin encabezado X-Canal | Las operaciones se realizan con tu canal por defecto |
| Con X-Canal válido | Las operaciones se realizan en nombre del canal impersonado |
| Con X-Canal sin permisos | Recibirás un error 401 Unauthorized |
Ejemplo Completo con Python
import requests
# Configuración
api_url = "https://pre-webhooks.imaginaenergia.com/contrato"
jwt_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
permiso_id = "550e8400-e29b-41d4-a716-446655440000"
# Headers con impersonación
headers = {
"Authorization": f"Bearer {jwt_token}",
"X-Canal": permiso_id
}
# Realizar solicitud
params = {"contrato_id": "12345"}
response = requests.get(api_url, headers=headers, params=params)
if response.status_code == 200:
print("✅ Solicitud exitosa:", response.json())
else:
print(f"❌ Error {response.status_code}:", response.json())
Códigos de Error de Autenticación
El sistema puede devolver los siguientes errores relacionados con autenticación:
| Código | Descripción | Solución |
|---|---|---|
401 |
Token JWT inválido o expirado | Obtén un nuevo token autenticándote |
401 |
Token no proporcionado | Incluye el encabezado Authorization |
401 |
Error en impersonación de canal | Verifica el ID de permiso y tus permisos |
403 |
No tienes permisos para esta operación | Contacta con el administrador |
Ejemplo de Respuesta de Error
{
"error": "Authentication failed",
"message": "Invalid or expired token"
}
Mejores Prácticas de Seguridad
Gestión del Token
1 Nunca compartas tu token JWT con otras personas
2 No incluyas el token en URLs o logs públicos
3 Almacena el token de forma segura en variables de entorno o sistemas de gestión de secretos
4 Renueva el token periódicamente antes de que expire
Uso de Impersonación
- Solicita al administrador solo los permisos de impersonación que realmente necesites
- Documenta internamente qué operaciones realizas con cada canal impersonado
- Verifica que estás usando el ID de permiso correcto antes de realizar operaciones críticas
Ejemplos de Código Completos
Python con Requests
import requests
import os
# 1. Obtener token JWT
def get_jwt_token(email, password):
url = "https://oezimzeqmtmncuipqgwd.supabase.co/functions/v1/initiateauthcommand"
payload = {
"email": email,
"password": password
}
response = requests.post(url, json=payload)
if response.status_code == 200:
data = response.json()
return data["token"]
else:
raise Exception(f"Error de autenticación: {response.text}")
# 2. Realizar petición autenticada
def get_contrato(token, contrato_id, permiso_canal=None):
url = "https://pre-webhooks.imaginaenergia.com/contrato"
headers = {
"Authorization": f"Bearer {token}"
}
# Agregar impersonación si se proporciona
if permiso_canal:
headers["X-Canal"] = permiso_canal
params = {"contrato_id": contrato_id}
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
return response.json()
elif response.status_code == 401:
raise Exception("Token inválido o expirado")
else:
raise Exception(f"Error {response.status_code}: {response.text}")
# Uso
try:
# Autenticarse
token = get_jwt_token(
email=os.getenv("API_EMAIL"),
password=os.getenv("API_PASSWORD")
)
print("✅ Token obtenido")
# Consultar contrato
contrato = get_contrato(
token=token,
contrato_id="12345",
permiso_canal="550e8400-e29b-41d4-a716-446655440000" # Opcional
)
print("✅ Contrato:", contrato)
except Exception as e:
print(f"❌ Error: {e}")
JavaScript con Fetch
// 1. Obtener token JWT
async function getJwtToken(email, password) {
const url = 'https://oezimzeqmtmncuipqgwd.supabase.co/functions/v1/initiateauthcommand';
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ email, password })
});
if (!response.ok) {
throw new Error(`Error de autenticación: ${response.statusText}`);
}
const data = await response.json();
return data.token;
}
// 2. Realizar petición autenticada
async function getContrato(token, contratoId, permisoCanal = null) {
const url = `https://pre-webhooks.imaginaenergia.com/contrato?contrato_id=${contratoId}`;
const headers = {
'Authorization': `Bearer ${token}`
};
// Agregar impersonación si se proporciona
if (permisoCanal) {
headers['X-Canal'] = permisoCanal;
}
const response = await fetch(url, { headers });
if (!response.ok) {
throw new Error(`Error ${response.status}: ${response.statusText}`);
}
return await response.json();
}
// Uso
(async () => {
try {
// Autenticarse
const token = await getJwtToken(
'tu_usuario@ejemplo.com',
'tu_contraseña'
);
console.log('✅ Token obtenido');
// Consultar contrato
const contrato = await getContrato(
token,
'12345',
'550e8400-e29b-41d4-a716-446655440000' // Opcional
);
console.log('✅ Contrato:', contrato);
} catch (error) {
console.error('❌ Error:', error.message);
}
})();
Gestión de Errores Completa
import requests
from typing import Optional, Dict, Any
class ImaginaEnergiaAPI:
def __init__(self, email: str, password: str):
self.email = email
self.password = password
self.token: Optional[str] = None
self.base_url = "https://pre-webhooks.imaginaenergia.com"
def authenticate(self) -> bool:
"""Obtiene un nuevo token JWT"""
url = "https://oezimzeqmtmncuipqgwd.supabase.co/functions/v1/initiateauthcommand"
try:
response = requests.post(url, json={
"email": self.email,
"password": self.password
})
if response.status_code == 200:
data = response.json()
self.token = data["token"]
print(f"✅ Autenticado. Token expira en {data['expires_in']} segundos")
return True
elif response.status_code == 401:
print("❌ Credenciales inválidas")
return False
else:
print(f"❌ Error de autenticación: {response.text}")
return False
except Exception as e:
print(f"❌ Error de conexión: {e}")
return False
def _make_request(self, method: str, endpoint: str,
permiso_canal: Optional[str] = None,
**kwargs) -> Dict[Any, Any]:
"""Realiza una petición HTTP con manejo de errores"""
if not self.token:
raise Exception("No hay token. Llama a authenticate() primero")
headers = {
"Authorization": f"Bearer {self.token}"
}
if permiso_canal:
headers["X-Canal"] = permiso_canal
url = f"{self.base_url}{endpoint}"
try:
response = requests.request(method, url, headers=headers, **kwargs)
if response.status_code == 200:
return response.json()
elif response.status_code == 401:
# Token expirado, intentar re-autenticar
print("⚠️ Token expirado, re-autenticando...")
if self.authenticate():
# Reintentar con nuevo token
headers["Authorization"] = f"Bearer {self.token}"
response = requests.request(method, url, headers=headers, **kwargs)
return response.json()
else:
raise Exception("No se pudo re-autenticar")
elif response.status_code == 403:
raise Exception("Acceso prohibido: no tienes permisos")
elif response.status_code == 404:
raise Exception("Recurso no encontrado")
else:
raise Exception(f"Error {response.status_code}: {response.text}")
except requests.RequestException as e:
raise Exception(f"Error de conexión: {e}")
def get_contrato(self, contrato_id: str,
permiso_canal: Optional[str] = None) -> Dict[Any, Any]:
"""Consulta un contrato específico"""
return self._make_request(
"GET",
"/contrato",
permiso_canal=permiso_canal,
params={"contrato_id": contrato_id}
)
# Uso
api = ImaginaEnergiaAPI("tu_usuario@ejemplo.com", "tu_contraseña")
if api.authenticate():
try:
contrato = api.get_contrato("12345")
print(f"✅ Contrato obtenido: {contrato}")
except Exception as e:
print(f"❌ Error: {e}")