datadis_python.client.v2 package

Submodules

Module contents

Cliente Datadis API v2 - Respuestas tipadas con Pydantic.

class datadis_python.client.v2.DatadisClientV2(username, password, timeout=90, retries=5)[fuente]

Bases: BaseDatadisClient

Cliente para API v2 de Datadis.

Características: - Devuelve datos raw exactamente como los proporciona la API - Endpoints v2 con estructura de respuesta actualizada - Validación de parámetros de entrada - Manejo de errores de distribuidor en formato v2

Parámetros:
  • username (str) – NIF del usuario registrado en Datadis.

  • password (str) – Contraseña de acceso a Datadis.

  • timeout (int) – Timeout para requests en segundos.

  • retries (int) – Número de reintentos automáticos.

get_consumption(cups, distributor_code, date_from, date_to, measurement_type=0, point_type=None, authorized_nif=None)[fuente]

Buscar los datos de consumo.

Parámetros:
  • cups (str) – Los CUPS de los que querremos saber los datos de consumo.

  • distributor_code (str) – Código del distribuidor, que se obtiene con la solicitud de obtención de suministros.

  • date_from (str) – Fecha de inicio entre los datos de búsqueda. Formato: AAAA/MM. Ejemplo = 2020/02.

  • date_to (str) – Fecha de finalización entre los datos de búsqueda. Formato: AAAA/MM. Ejemplo = 2020/02.

  • measurement_type (int) – Establézcalo en 0 (Cero) si desea obtener el consumo por hora y en 1 (Uno) si desea obtener el consumo por cuarto de hora. La consulta cuarta horaria solo está disponible para los PointType 1 y 2, y en el caso de la distribuidora E-distribución adicionalmente el PointType 3.

  • point_type (Optional[int]) – Código de tipo de punto, que se obtiene con la solicitud de obtención de suministros.

  • authorized_nif (Optional[str]) – Solo en caso que se quiera obtener los datos de consumo de un NIF autorizado.

Devuelve:

Respuesta con datos de consumo validados y errores de distribuidora en formato v2.

Tipo del valor devuelto:

ConsumptionResponse

get_contract_detail(cups, distributor_code, authorized_nif=None)[fuente]

Buscar el detalle del contrato.

Parámetros:
  • cups (str) – Los CUPS de los que querremos saber los detalles del contrato. Solo puede buscar un CUPS por pedido.

  • distributor_code (str) – Código del distribuidor, que se obtiene con la solicitud de obtención de suministros.

  • authorized_nif (Optional[str]) – Solo en el caso de que quieras obtener el detalle del contrato del NIF autorizado.

Devuelve:

Respuesta con datos de contrato validados y errores de distribuidora en formato v2.

Tipo del valor devuelto:

ContractResponse

get_distributors(authorized_nif=None)[fuente]

Obtiene una lista de códigos de distribuidores en los que el usuario tiene suministros.

Parámetros:

authorized_nif (Optional[str]) – Únicamente en caso de querer obtener el listado de códigos de distribuidoras que disponen de suministros del NIF autorizado.

Devuelve:

Respuesta con códigos de distribuidores validados y errores en formato v2.

Tipo del valor devuelto:

DistributorsResponse

Note:

Códigos de distribuidora: (1: Viesgo, 2: E-distribución, 3: E-redes, 4: ASEME, 5: UFD, 6: EOSA, 7:CIDE, 8: IDE)

get_max_power(cups, distributor_code, date_from, date_to, authorized_nif=None)[fuente]

Busca la potencia máxima y te aparecerá el resultado en kW.

Parámetros:
  • cups (str) – Las CUPS de las que querremos conocer los detalles del contrato.

  • distributor_code (str) – Código del distribuidor, que se obtiene con la solicitud de obtención de suministros.

  • date_from (str) – Fecha de inicio entre los datos de búsqueda. Formato: AAAA/MM. Ejemplo = 2020/02.

  • date_to (str) – Fecha de finalización entre los datos de búsqueda. Formato: AAAA/MM. Ejemplo = 2020/02.

  • authorized_nif (Optional[str]) – Solo en el caso de que quieras obtener el detalle del contrato del NIF autorizado.

Devuelve:

Respuesta con datos de potencia máxima validados y errores de distribuidora en formato v2.

Tipo del valor devuelto:

MaxPowerResponse

get_reactive_data(cups, distributor_code, date_from, date_to, authorized_nif=None)[fuente]

Buscar datos de energía reactiva (solo disponible en v2).

Parámetros:
  • cups (str) – Los CUPS de los que querremos saber los datos de consumo.

  • distributor_code (str) – Código del distribuidor, que se obtiene con la solicitud de obtención de suministros.

  • date_from (str) – Fecha de inicio entre los datos de búsqueda. Formato: AAAA/MM. Ejemplo = 2020/02.

  • date_to (str) – Fecha de finalización entre los datos de búsqueda. Formato: AAAA/MM. Ejemplo = 2020/02.

  • authorized_nif (Optional[str]) – Solo en caso que se quiera obtener los datos de consumo de un NIF autorizado.

Devuelve:

Lista de objetos ReactiveData validados.

Tipo del valor devuelto:

List[ReactiveData]

get_supplies(authorized_nif=None, distributor_code=None)[fuente]

Buscar todos los suministros.

Parámetros:
  • authorized_nif (Optional[str]) – Si queremos buscar suministros de personas que hemos autorizado, podemos buscarlo con el NIF de las personas autorizadas.

  • distributor_code (Optional[str]) – Código del distribuidor, que se obtiene con la solicitud de distribuidoras con suministros: /get-distributors-with-supplies. Para consultar los suministros de una sola distribuidora.

Devuelve:

Respuesta con suministros validados y errores de distribuidora en formato v2.

Tipo del valor devuelto:

SuppliesResponse

class datadis_python.client.v2.SimpleDatadisClientV2(username, password, timeout=120, retries=3)[fuente]

Bases: object

Cliente simplificado para la API V2 de Datadis con manejo mejorado de errores.

Este cliente implementa la versión 2 de la API de Datadis, que incluye mejoras significativas sobre la V1, especialmente en el manejo de errores por distribuidor y estructuras de respuesta más robustas. La V2 es la versión recomendada para nuevas implementaciones.

Principales diferencias con V1:
  • Manejo de errores por distribuidor: Respuestas incluyen distributorError

  • Estructuras de respuesta mejoradas: Objetos tipados (SuppliesResponse, etc.)

  • Nueva funcionalidad: Datos de energía reactiva (get_reactive_data())

  • Validación mejorada: Validaciones específicas para types y rangos

  • Compatibilidad: Mantiene la misma interfaz simple que V1

Características principales:
  • Autenticación automática y renovación de tokens

  • Manejo robusto de timeouts y reintentos con backoff exponencial

  • Validación de datos con Pydantic para máxima seguridad

  • Soporte para tipos flexibles en parámetros de entrada

  • Context manager para gestión automática de recursos

  • Manejo de errores por distribuidor (exclusivo de V2)

  • Respuestas estructuradas con información de errores detallada

Ventajas de la API V2:
  • Robustez: Mejor manejo de fallos de distribuidores específicos

  • Información detallada: Códigos y descripciones de errores por distribuidor

  • Funcionalidad extendida: Acceso a datos de energía reactiva

  • Compatibilidad futura: Preparada para nuevas funcionalidades

Nota

La API V2 acepta las mismas limitaciones que V1: solo fechas en formato mensual (YYYY/MM) y disponibilidad limitada de datos cuarto-horarios.

Ejemplo

Uso básico con manejo de errores V2:

from datadis_python.client.v2 import SimpleDatadisClientV2

with SimpleDatadisClientV2("12345678A", "mi_password") as client:
    # Obtener suministros con información de errores
    supplies_response = client.get_supplies()

    print(f"Suministros obtenidos: {len(supplies_response.supplies)}")

    # Verificar errores por distribuidor
    if supplies_response.distributor_error:
        for error in supplies_response.distributor_error:
            print(f"Error en {error.distributorName}: {error.errorDescription}")

    # Trabajar con los suministros válidos
    for supply in supplies_response.supplies:
        print(f"CUPS: {supply.cups} - Distribuidor: {supply.distributor}")

Comparación con V1:

# V1 - Lista simple
supplies_v1 = client_v1.get_supplies()  # List[SupplyData]

# V2 - Respuesta estructurada con manejo de errores
supplies_v2 = client_v2.get_supplies()  # SuppliesResponse
actual_supplies = supplies_v2.supplies  # List[SupplyData]
errors = supplies_v2.distributor_error   # List[DistributorError]

Funcionalidad exclusiva de V2 - Energía reactiva:

reactive_data = client.get_reactive_data(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12"
)
Parámetros:
  • username (str) – NIF del usuario registrado en Datadis (ej: «12345678A»)

  • password (str) – Contraseña de acceso a la plataforma Datadis

  • timeout (int) – Timeout para requests HTTP en segundos. 120s por defecto debido a la lentitud característica de la API de Datadis

  • retries (int) – Número de reintentos automáticos en caso de fallos de red o timeouts. 3 intentos por defecto

Muestra:

Added in version 2.0: Soporte para estructuras de respuesta mejoradas y manejo de errores por distribuidor

Ver también

  • SimpleDatadisClientV1 - Versión anterior con respuestas simples

  • Para migración de V1 a V2: Las interfaces son compatibles, solo cambian los tipos de retorno

__enter__()[fuente]

Método de entrada del context manager - Permite usar with statement.

Implementa el protocolo de context manager de Python, permitiendo que el cliente se use con la declaración with para gestión automática de recursos.

¿Qué hace este método?
  • Retorna la instancia actual: Permite acceso a todos los métodos del cliente

  • Inicialización implícita: La autenticación se realiza de forma lazy en el primer request

  • Establece el contexto: Prepara el cliente para uso dentro del bloque with

Ventajas del patrón context manager:
  1. Gestión automática: Los recursos se liberan automáticamente al salir

  2. Robustez ante errores: Cleanup garantizado incluso si ocurren excepciones

  3. Código más limpio: No necesidad de llamadas manuales a close()

  4. Mejores prácticas: Patrón estándar en Python para gestión de recursos

V1 vs V2 - Context manager:
  • V1: Implementación básica del patrón

  • V2: Implementación mejorada con mejor gestión de excepciones y recursos

Ejemplo

Uso estándar con context manager:

# __enter__() se llama automáticamente aquí ↓
with SimpleDatadisClientV2("12345678A", "password") as client:
    # 'client' es lo que retorna __enter__()
    supplies = client.get_supplies()

    for supply in supplies.supplies:
        consumption = client.get_consumption(
            cups=supply.cups,
            distributor_code=supply.distributorCode,
            date_from="2024/01",
            date_to="2024/03"
        )
        print(f"Consumo: {len(consumption)} registros")
# __exit__() se llama automáticamente aquí ↑

print("✓ Recursos liberados automáticamente")

Context manager anidado:

with SimpleDatadisClientV2("12345678A", "password") as client:
    supplies = client.get_supplies()

    # Múltiples operaciones en el mismo contexto
    for supply in supplies.supplies[:3]:  # Primeros 3 suministros
        distributors = client.get_distributors()
        contracts = client.get_contract_detail(
            cups=supply.cups,
            distributor_code=supply.distributorCode
        )

        # V2 exclusive: Energía reactiva
        reactive_data = client.get_reactive_data(
            cups=supply.cups,
            distributor_code=supply.distributorCode,
            date_from="2024/01",
            date_to="2024/03"
        )

        print(f"CUPS: {supply.cups}")
        print(f"- Contratos: {len(contracts)}")
        print(f"- Energía reactiva: {len(reactive_data)} registros")

Comparación con uso manual:

# ❌ Uso manual (más propenso a errores)
client = SimpleDatadisClientV2("12345678A", "password")
try:
    supplies = client.get_supplies()
    # ... hacer trabajo ...
finally:
    client.close()  # ← Fácil de olvidar

# ✅ Context manager (recomendado)
with SimpleDatadisClientV2("12345678A", "password") as client:
    supplies = client.get_supplies()
    # ... hacer trabajo ...
# ← Cleanup automático garantizado

Manejo de excepciones transparente:

try:
    with SimpleDatadisClientV2("invalid_nif", "wrong_pass") as client:
        supplies = client.get_supplies()  # ← AuthenticationError
except AuthenticationError as e:
    print(f"Error de autenticación: {e}")
# ← close() se ejecuta incluso con excepción
Devuelve:

La propia instancia del cliente, permitiendo acceso a todos sus métodos

Tipo del valor devuelto:

SimpleDatadisClientV2

Nota

Este método NO realiza la autenticación. La autenticación se hace de forma lazy en el primer request que requiera token.

Ver también

  • __exit__() para el método de salida del context manager

  • close() para limpieza manual de recursos

  • PEP 343 - Especificación del protocolo context manager

Added in version 2.0: Implementación mejorada del context manager con mejor gestión de recursos

__exit__(exc_type, exc_val, exc_tb)[fuente]

Método de salida del context manager - Garantiza limpieza automática de recursos.

Se ejecuta automáticamente al salir del bloque with, independientemente de si el código terminó normalmente o con una excepción. Garantiza que los recursos se liberen correctamente en todos los casos.

¿Qué hace este método?
  • Llamada automática a close(): Libera sesiones HTTP y tokens

  • Cleanup garantizado: Se ejecuta incluso si ocurren excepciones

  • No suprime excepciones: Permite que las excepciones se propaguen normalmente

  • Gestión robusta: Implementación defensiva ante posibles errores

Flujo de ejecución:
  1. Entrada: __enter__() retorna la instancia del cliente

  2. Trabajo: Se ejecuta el código dentro del bloque with

  3. Salida: __exit__() se llama automáticamente (incluso con excepciones)

  4. Cleanup: close() libera todos los recursos

  5. Propagación: Las excepciones originales se mantienen

V1 vs V2 - Gestión de excepciones:
  • V1: Implementación básica de cleanup

  • V2: Gestión más robusta, mejor logging de errores durante cleanup

Ejemplo

Flujo normal (sin excepciones):

with SimpleDatadisClientV2("12345678A", "password") as client:
    # __enter__() ejecutado ↑

    supplies = client.get_supplies()
    print(f"Suministros: {len(supplies.supplies)}")

    # Código se ejecuta normalmente
    consumption = client.get_consumption(
        cups=supplies.supplies[0].cups,
        distributor_code=supplies.supplies[0].distributorCode,
        date_from="2024/01",
        date_to="2024/03"
    )

# __exit__(None, None, None) ejecutado aquí ↑
# Recursos liberados automáticamente
print("✓ Operación completada, recursos liberados")

Flujo con excepción controlada:

try:
    with SimpleDatadisClientV2("12345678A", "wrong_password") as client:
        # __enter__() ejecutado ↑

        supplies = client.get_supplies()  # ← AuthenticationError

except AuthenticationError as e:
    # __exit__(AuthenticationError, e, traceback) ya ejecutado ↑
    print(f"Error de autenticación: {e}")
    print("✓ Recursos liberados automáticamente (con excepción)")

Flujo con excepción inesperada:

with SimpleDatadisClientV2("12345678A", "password") as client:
    # __enter__() ejecutado ↑

    supplies = client.get_supplies()

    # Error inesperado en el código del usuario
    result = 1 / 0  # ← ZeroDivisionError

# __exit__(ZeroDivisionError, exception, traceback) ejecutado ↑
# Recursos liberados automáticamente
# ZeroDivisionError se propaga normalmente

Múltiples context managers:

# Cada context manager gestiona sus propios recursos
with SimpleDatadisClientV2("user1_nif", "pass1") as client1:
    with SimpleDatadisClientV2("user2_nif", "pass2") as client2:
        # Ambos clientes activos
        supplies1 = client1.get_supplies()
        supplies2 = client2.get_supplies()

        # Comparar datos entre usuarios
        print(f"Usuario 1: {len(supplies1.supplies)} suministros")
        print(f"Usuario 2: {len(supplies2.supplies)} suministros")
    # client2.__exit__() ejecutado aquí
# client1.__exit__() ejecutado aquí

print("✓ Ambos clientes cerrados correctamente")

Debugging del context manager:

class DebuggingDatadisClient(SimpleDatadisClientV2):
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(f"Saliendo del context manager...")
        if exc_type:
            print(f"- Con excepción: {exc_type.__name__}: {exc_val}")
        else:
            print("- Terminación normal")

        # Llamar al método padre para cleanup real
        super().__exit__(exc_type, exc_val, exc_tb)
        print("✓ Recursos liberados")

with DebuggingDatadisClient("12345678A", "password") as client:
    supplies = client.get_supplies()
    # raise ValueError("Error de prueba")  # ← Descomentar para probar
Parámetros:
  • exc_type (Optional[Type[BaseException]]) – Tipo de excepción que causó la salida, o None si terminó normalmente

  • exc_val (Optional[BaseException]) – Instancia de la excepción que causó la salida, o None si terminó normalmente

  • exc_tb (Optional[TracebackType]) – Traceback de la excepción, o None si terminó normalmente

Devuelve:

None (no suprime excepciones, permite propagación normal)

Tipo del valor devuelto:

None

Nota

Este método NUNCA suprime excepciones (siempre retorna None/False). Las excepciones se propagan normalmente después del cleanup.

Advertencia

NO llame este método manualmente. Es invocado automáticamente por Python al salir del bloque with. La llamada manual puede causar doble cleanup.

Ver también

Added in version 2.0: Implementación mejorada con mejor gestión de excepciones durante cleanup

__init__(username, password, timeout=120, retries=3)[fuente]

Inicializa el cliente simplificado V2.

Parámetros:
  • username (str) – NIF del usuario

  • password (str) – Contraseña

  • timeout (int) – Timeout en segundos (120s por defecto para Datadis)

  • retries (int) – Número de reintentos

authenticate()[fuente]

Autentica con la API de Datadis y obtiene el token de acceso para V2.

Realiza una petición POST al endpoint /nikola-auth/tokens/login para obtener un token Bearer válido para la API V2. El proceso de autenticación es idéntico entre V1 y V2, pero el token obtenido es compatible con ambas versiones de endpoints.

Nota

Este método normalmente NO necesita ser llamado manualmente. La autenticación se realiza automáticamente en la primera petición que requiera acceso a la API. La V2 utiliza el mismo sistema de autenticación que V1.

Advertencia

Los tokens tienen expiración limitada, pero la renovación automática está implementada para todos los endpoints V2 cuando se detecta un error 401.

Ejemplo

Verificación manual de credenciales (opcional):

client = SimpleDatadisClientV2("12345678A", "mi_password")

try:
    if client.authenticate():
        print("✓ Credenciales válidas para API V2")

        # Ahora se pueden hacer peticiones autenticadas
        supplies_response = client.get_supplies()
        print(f"Suministros encontrados: {len(supplies_response.supplies)}")
    else:
        print("✗ Error en autenticación")

except AuthenticationError as e:
    print(f"Error de credenciales: {e}")
except DatadisError as e:
    print(f"Error de conexión: {e}")
Devuelve:

True si la autenticación fue exitosa, False en caso contrario

Tipo del valor devuelto:

bool

Muestra:
  • AuthenticationError – Si las credenciales (NIF/contraseña) son inválidas, el servidor devuelve un error de autenticación, o la respuesta del servidor está vacía

  • DatadisError – Si ocurre un timeout durante la autenticación o error de conexión

Ver también

  • Documentación oficial: POST /nikola-auth/tokens/login

  • Los tokens son válidos para ambas versiones V1 y V2 de la API

  • Renovación automática implementada en _make_authenticated_request()

Nota

El token obtenido se almacena automáticamente en self.token y se añade a los headers de la sesión HTTP como Authorization: Bearer <token>.

close()[fuente]

Cierra explícitamente la sesión HTTP y limpia los recursos del cliente V2.

Realiza las siguientes operaciones de limpieza:
  • Cierra la sesión HTTP: Libera conexiones TCP activas

  • Invalida el token: Establece el token a None por seguridad

  • Libera recursos: Evita memory leaks en aplicaciones de larga duración

¿Cuándo llamar manualmente?

Normalmente NO es necesario llamar este método explícitamente cuando se usa el patrón with (context manager), ya que __exit__ lo llama automáticamente.

Sin embargo, puede ser útil en estos casos:
  • Aplicaciones de larga duración: Cuando el cliente se mantiene activo mucho tiempo

  • Gestión manual de recursos: Cuando no se usa context manager

  • Problemas de conectividad: Para forzar reconexión después de errores

  • Testing y debugging: Para controlar explícitamente el ciclo de vida

V1 vs V2 - Diferencias en gestión de recursos:
  • V1: Gestión de recursos más simple, principalmente HTTP sessions

  • V2: Gestión más robusta con mejor manejo de tokens y sesiones

Ejemplo

Uso con context manager (recomendado):

# El método close() se llama automáticamente
with SimpleDatadisClientV2("12345678A", "password") as client:
    supplies = client.get_supplies()
    # Al salir del bloque 'with', close() se ejecuta automáticamente

print("✓ Sesión cerrada automáticamente")

Uso manual (casos especiales):

client = SimpleDatadisClientV2("12345678A", "password")
try:
    supplies = client.get_supplies()
    consumption = client.get_consumption(
        cups=supplies.supplies[0].cups,
        distributor_code=supplies.supplies[0].distributorCode,
        date_from="2024/01",
        date_to="2024/03"
    )

    # Procesar muchos datos...

finally:
    client.close()  # ← Llamada manual obligatoria
    print("✓ Recursos liberados manualmente")

Aplicación de larga duración:

class DatadisService:
    def __init__(self):
        self.client = None

    def connect(self):
        self.client = SimpleDatadisClientV2("12345678A", "password")

    def disconnect(self):
        if self.client:
            self.client.close()  # ← Limpieza explícita
            self.client = None

    def get_recent_consumption(self):
        if not self.client:
            self.connect()
        return self.client.get_consumption(...)

Debugging y reconexión:

client = SimpleDatadisClientV2("12345678A", "password")

# Primer intento
try:
    supplies = client.get_supplies()
except Exception as e:
    print(f"Error: {e}")
    client.close()  # ← Limpiar estado

    # Reintentar con nueva sesión
    client = SimpleDatadisClientV2("12345678A", "password")
    supplies = client.get_supplies()

Nota

Este método es idempotente: se puede llamar múltiples veces sin efectos secundarios. Si la sesión ya está cerrada, no hace nada.

Advertencia

Después de llamar a close(), el cliente queda inutilizable. Cualquier intento de hacer requests fallará. Cree una nueva instancia si necesita continuar usando la API.

Ver también

  • __enter__() y __exit__() para el patrón context manager

  • Documentación de requests.Session.close() para detalles técnicos

get_consumption(cups, distributor_code, date_from, date_to, measurement_type=0, point_type=None, authorized_nif=None)[fuente]

Obtiene los datos de consumo eléctrico con validaciones mejoradas (V2).

Consulta el endpoint GET /api-private/api/get-consumption-data-v2 para obtener la curva de carga con manejo mejorado de errores y validaciones específicas V2. Incluye todas las funcionalidades de V1 más validaciones automáticas de rangos, manejo robusto de errores por distribuidor y soporte nativo para NIFs autorizados.

IMPORTANTE - Limitaciones idénticas a V1:
  • Solo fechas en formato mensual (YYYY/MM)

  • Datos cuarto-horarios limitados según tipo de punto

  • Conversión automática de fechas datetime/date

Mejoras de V2 sobre V1:
  • Validación automática: measurement_type y point_type se validan automáticamente

  • Manejo de errores por distribuidor: Operación exitosa aunque algunos distribuidores fallen

  • Soporte nativo para NIFs autorizados: Parámetro authorized_nif integrado

  • Respuesta estructurada: ConsumptionResponse con curva de tiempo y errores separados

  • Mejor diagnóstico: Información detallada de problemas específicos por distribuidor

Validaciones automáticas V2:
  • measurement_type: Se valida que esté en rango [0, 1]

  • point_type: Se valida que esté en rango [1, 5] si se proporciona

  • Compatibilidad cuarto-horaria: Se verifica automáticamente según tipo de punto

Ejemplo

Obtener consumo con manejo de errores V2:

with SimpleDatadisClientV2("12345678A", "password") as client:
    supplies_response = client.get_supplies()

    if supplies_response.supplies:
        supply = supplies_response.supplies[0]

        # Consumo horario del año 2024
        consumption_response = client.get_consumption(
            cups=supply.cups,
            distributor_code=supply.distributorCode,
            date_from="2024/01",
            date_to="2024/12",
            measurement_type=0  # Horarios - se valida automáticamente
        )

        print(f"✓ Registros obtenidos: {len(consumption_response.time_curve)}")

        # Analizar consumo
        total_kwh = sum(c.consumptionKWh for c in consumption_response.time_curve
                      if c.consumptionKWh)
        print(f"Consumo total 2024: {total_kwh:.2f} kWh")

        # Verificar errores específicos
        if consumption_response.distributor_error:
            print("⚠️  Errores encontrados:")
            for error in consumption_response.distributor_error:
                print(f"- {error.distributorName}: {error.errorDescription}")
        else:
            print("✓ Datos obtenidos sin errores")

Obtener datos cuarto-horarios con validación automática:

# V2 valida automáticamente la compatibilidad
try:
    consumption_response = client.get_consumption(
        cups="ES001234567890123456AB",
        distributor_code="2",  # E-distribución
        date_from="2024/06",
        date_to="2024/06",
        measurement_type=1,    # Cuarto-horarios - se valida automáticamente
        point_type=3           # Tipo 3 - se valida que esté en [1-5]
    )

    print(f"Datos cada 15 min: {len(consumption_response.time_curve)} registros")

except ValidationError as e:
    print(f"Error de validación V2: {e}")
except APIError as e:
    print(f"API rechazó la petición: {e}")

Consultar consumo con NIF autorizado:

consumption_response = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/03",
    authorized_nif="87654321B"  # NIF que nos autorizó
)

if consumption_response.time_curve:
    print(f"Datos autorizados obtenidos: {len(consumption_response.time_curve)}")

Comparación V1 vs V2:

# V1 - Lista simple, validación manual
consumption_v1 = client_v1.get_consumption(cups, dist, date_from, date_to)  # List[ConsumptionData]

# V2 - Respuesta estructurada, validación automática
response_v2 = client_v2.get_consumption(cups, dist, date_from, date_to)     # ConsumptionResponse
consumption_v2 = response_v2.time_curve                                     # List[ConsumptionData]
errors_v2 = response_v2.distributor_error                                   # List[DistributorError]
Parámetros:
  • cups (str) – Código CUPS del punto de suministro (22 caracteres alfanuméricos)

  • distributor_code (Union[str, int]) – Código del distribuidor eléctrico (acepta int o str, se convierte automáticamente)

  • date_from (Union[str, datetime, date]) – Fecha de inicio en formato YYYY/MM. También acepta objetos datetime/date que se convertirán automáticamente

  • date_to (Union[str, datetime, date]) – Fecha de fin en formato YYYY/MM. También acepta objetos datetime/date que se convertirán automáticamente

  • measurement_type (Union[int, float, str]) – Tipo de medición - 0: horarios (defecto), 1: cuarto-horarios. Se valida automáticamente en V2 que esté en rango [0, 1]

  • point_type (Optional[Union[int, float, str]]) – Tipo de punto de medida (1-5). Requerido para datos cuarto-horarios. Se valida automáticamente en V2 que esté en rango [1, 5]

  • authorized_nif (Optional[str]) – NIF de la persona que autorizó la consulta de sus datos. Si se especifica, se consultarán los datos de esa persona

Devuelve:

Objeto ConsumptionResponse que contiene: - time_curve: Lista de objetos ConsumptionData validados - distributor_error: Lista de errores por distribuidor si los hay

Tipo del valor devuelto:

ConsumptionResponse

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP crítico (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si las fechas no están en formato mensual válido, los tipos de medición/punto están fuera de rango, o los datos no pasan la validación Pydantic mejorada de V2

  • ValueError – Si se solicitan datos cuarto-horarios para un tipo de punto no compatible

Ver también

  • Documentación oficial: GET /api-private/api/get-consumption-data-v2

  • Comparar con SimpleDatadisClientV1.get_consumption() para diferencias

  • Para obtener CUPS: get_supplies()

  • Para datos de potencia máxima: get_max_power()

Added in version 2.0: Validaciones automáticas de rangos, soporte para authorized_nif y manejo de errores por distribuidor

Advertencia

Los datos cuarto-horarios siguen teniendo las mismas limitaciones que en V1: solo disponibles para tipos de punto 1, 2, y 3 en E-distribución.

get_contract_detail(cups, distributor_code, authorized_nif=None)[fuente]

Obtiene los detalles del contrato eléctrico con manejo mejorado de errores (V2).

Consulta el endpoint GET /api-private/api/get-contract-detail-v2 para obtener información detallada del contrato asociado a un CUPS específico. La V2 incluye manejo mejorado de errores por distribuidor y soporte nativo para consultas con NIFs autorizados, proporcionando mayor robustez y flexibilidad.

Ventajas de V2 sobre V1:
  • Manejo de errores por distribuidor: Información detallada de fallos específicos

  • Soporte nativo para NIFs autorizados: Parámetro authorized_nif integrado

  • Respuesta estructurada: ContractResponse con contratos y errores separados

  • Mayor robustez: Operación exitosa aunque haya problemas con algunos distribuidores

Información del contrato incluida (idéntica a V1):
  • Datos básicos: CUPS, distribuidor, comercializadora

  • Características técnicas: Tensión, potencia contratada, tipo de punto

  • Datos tarifarios: Tarifa de acceso, discriminación horaria

  • Ubicación: Provincia, municipio, código postal

  • Fechas: Inicio y fin de contrato, historial de cambios

  • Autoconsumo: Tipo, características y CAU si aplica

  • Control de potencia: ICP o Maxímetro

Ejemplo

Obtener detalles de contrato con manejo de errores V2:

with SimpleDatadisClientV2("12345678A", "password") as client:
    # Primero obtener suministros
    supplies_response = client.get_supplies()

    if supplies_response.supplies:
        supply = supplies_response.supplies[0]

        # Obtener detalles del contrato
        contract_response = client.get_contract_detail(
            cups=supply.cups,
            distributor_code=supply.distributorCode
        )

        print(f"✓ Contratos obtenidos: {len(contract_response.contract)}")

        # Mostrar información de contratos
        for contract in contract_response.contract:
            print(f"CUPS: {contract.cups}")
            print(f"Distribuidor: {contract.distributor}")
            print(f"Potencia contratada: {contract.contractedPowerkW} kW")
            print(f"Tarifa de acceso: {contract.accessFare}")
            if contract.marketer:
                print(f"Comercializadora: {contract.marketer}")
            print("---")

        # Verificar errores específicos del distribuidor
        if contract_response.distributor_error:
            print("⚠️  Errores en la consulta:")
            for error in contract_response.distributor_error:
                print(f"- {error.distributorName}: {error.errorDescription}")
        else:
            print("✓ Consulta exitosa sin errores")

Consultar contrato con NIF autorizado:

# Obtener contrato de un suministro autorizado por tercero
contract_response = client.get_contract_detail(
    cups="ES001234567890123456AB",
    distributor_code="2",
    authorized_nif="87654321B"  # NIF que nos autorizó
)

if contract_response.contract:
    contract = contract_response.contract[0]
    print(f"Contrato autorizado - Potencia: {contract.contractedPowerkW} kW")
elif contract_response.distributor_error:
    for error in contract_response.distributor_error:
        print(f"Error en autorización: {error.errorDescription}")

Comparación V1 vs V2:

# V1 - Lista simple, fallo total si hay errores
contracts_v1 = client_v1.get_contract_detail(cups, dist_code)  # List[ContractData]

# V2 - Respuesta robusta con manejo de errores
response_v2 = client_v2.get_contract_detail(cups, dist_code)    # ContractResponse
contracts_v2 = response_v2.contract                            # List[ContractData]
errors_v2 = response_v2.distributor_error                      # List[DistributorError]
Parámetros:
  • cups (str) – Código CUPS del punto de suministro (22 caracteres alfanuméricos que identifican únicamente el punto de suministro eléctrico)

  • distributor_code (str) – Código del distribuidor eléctrico como string (ej: «2» para E-distribución). V2 requiere string

  • authorized_nif (Optional[str]) – NIF de la persona que autorizó la consulta de sus datos. Si se especifica, se consultará el contrato de esa persona en lugar del usuario autenticado

Devuelve:

Objeto ContractResponse que contiene: - contract: Lista de objetos ContractData validados - distributor_error: Lista de errores por distribuidor si los hay

Tipo del valor devuelto:

ContractResponse

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP crítico (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si los datos devueltos no pasan la validación Pydantic

  • ValueError – Si el CUPS no tiene el formato correcto (22 caracteres)

Ver también

  • Documentación oficial: GET /api-private/api/get-contract-detail-v2

  • Comparar con SimpleDatadisClientV1.get_contract_detail() para diferencias

  • Para obtener la lista de CUPS: get_supplies()

  • Para datos de consumo del contrato: get_consumption()

Added in version 2.0: Soporte nativo para authorized_nif y manejo de errores por distribuidor

Nota

El CUPS debe ser exactamente de 22 caracteres alfanuméricos. La V2 incluye validación mejorada y mensajes de error más descriptivos.

get_distributors(authorized_nif=None)[fuente]

Obtiene la lista de distribuidores con estructura mejorada (V2).

Consulta el endpoint GET /api-private/api/get-distributors-with-supplies-v2 para obtener información sobre las distribuidoras eléctricas donde el usuario tiene suministros activos. La V2 incluye manejo mejorado de errores y estructura de respuesta más detallada que proporciona mejor información diagnóstica.

Mejoras de V2 sobre V1:
  • Estructura de respuesta mejorada: DistributorsResponse con metadatos

  • Información de errores: Detalles específicos de fallos por distribuidor

  • Soporte para NIFs autorizados: Consultar distribuidores de terceros

  • Manejo robusto: Operación exitosa aunque algunos distribuidores fallen

La respuesta incluye:
  • dist_existence_user: Objeto con distributorCodes (lista de códigos)

  • distributor_error: Lista de errores específicos por distribuidor si los hay
    • Información detallada de qué distribuidores no respondieron correctamente

    • Códigos de error específicos y descripciones

Ejemplo

Obtener distribuidores del usuario autenticado:

with SimpleDatadisClientV2("12345678A", "password") as client:
    response = client.get_distributors()

    # Obtener códigos de distribuidores
    distributor_codes = response.dist_existence_user.get("distributorCodes", [])

    print(f"✓ Distribuidores encontrados: {len(distributor_codes)}")

    # Mapear códigos a nombres (referencia)
    distributor_names = {
        "1": "Viesgo", "2": "E-distribución", "3": "E-redes",
        "4": "ASEME", "5": "UFD", "6": "EOSA", "7": "CIDE", "8": "IDE"
    }

    for code in distributor_codes:
        name = distributor_names.get(code, f"Distribuidor {code}")
        print(f"- {name} (código: {code})")

    # Verificar errores
    if response.distributor_error:
        print(f"⚠️  Errores en {len(response.distributor_error)} distribuidores:")
        for error in response.distributor_error:
            print(f"- {error.distributorName}: {error.errorDescription}")

    # Usar códigos para consultas posteriores
    if distributor_codes:
        first_code = distributor_codes[0]
        supplies_response = client.get_supplies(distributor_code=first_code)
        print(f"Suministros en {distributor_names.get(first_code)}: {len(supplies_response.supplies)}")

Consultar distribuidores de una persona autorizada:

# Obtener distribuidores de un NIF autorizado
response = client.get_distributors(authorized_nif="87654321B")

auth_distributors = response.dist_existence_user.get("distributorCodes", [])
print(f"Distribuidores del NIF autorizado: {auth_distributors}")

Comparación V1 vs V2:

# V1 - Lista simple de objetos DistributorData
distributors_v1 = client_v1.get_distributors()  # List[DistributorData]
codes_v1 = [d.distributorCode for d in distributors_v1]

# V2 - Respuesta estructurada con manejo de errores
response_v2 = client_v2.get_distributors()     # DistributorsResponse
codes_v2 = response_v2.dist_existence_user.get("distributorCodes", [])
errors_v2 = response_v2.distributor_error       # Lista de errores si los hay
Parámetros:

authorized_nif (Optional[str]) – NIF de una persona autorizada para consultar sus distribuidores. Si se especifica, se obtendrán los distribuidores donde esa persona tiene suministros en lugar del usuario autenticado

Devuelve:

Objeto DistributorsResponse que contiene: - dist_existence_user: Dict con distributorCodes (lista de códigos de distribuidor) - distributor_error: Lista de errores por distribuidor si los hay

Tipo del valor devuelto:

DistributorsResponse

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP crítico (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si los datos devueltos no pasan la validación Pydantic

Ver también

  • Documentación oficial: GET /api-private/api/get-distributors-with-supplies-v2

  • Comparar con SimpleDatadisClientV1.get_distributors() para diferencias

  • Los códigos obtenidos se usan en get_supplies(), get_consumption(), etc.

Added in version 2.0: Soporte para NIFs autorizados y estructura de respuesta mejorada

Nota

Solo se devuelven códigos de distribuidores donde el usuario (o NIF autorizado) tiene suministros activos. La lista puede estar vacía si no hay suministros.

get_max_power(cups, distributor_code, date_from, date_to, authorized_nif=None)[fuente]

Obtiene los datos de potencia máxima demandada con manejo mejorado de errores (V2).

Consulta el endpoint GET /api-private/api/get-max-power-v2 para obtener las potencias máximas registradas en cada período tarifario con manejo mejorado de errores por distribuidor y soporte nativo para NIFs autorizados. Mantiene toda la funcionalidad de V1 con mayor robustez y mejor información diagnóstica.

IMPORTANTE - Limitación idéntica a V1:

Solo acepta fechas en formato mensual (YYYY/MM). El SDK convierte automáticamente fechas datetime/date al formato requerido.

Mejoras de V2 sobre V1:
  • Manejo de errores por distribuidor: Información detallada de fallos específicos

  • Soporte nativo para NIFs autorizados: Parámetro authorized_nif integrado

  • Respuesta estructurada: MaxPowerResponse con potencias y errores separados

  • Mayor robustez: Operación exitosa aunque algunos distribuidores fallen

  • Mejor diagnóstico: Códigos y descripciones de errores específicos

Información de potencia máxima (idéntica a V1):
  • Potencia en Vatios (W): Demanda máxima registrada en cada período

  • Períodos tarifarios: VALLE, LLANO, PUNTA, P1-P6

  • Timestamp completo: Fecha y hora exacta del pico de potencia

  • Aplicaciones: Optimización de potencia contratada, identificación de picos

Ejemplo

Obtener potencias máximas con manejo de errores V2:

with SimpleDatadisClientV2("12345678A", "password") as client:
    supplies_response = client.get_supplies()

    if supplies_response.supplies:
        supply = supplies_response.supplies[0]

        # Potencias máximas de 2024
        max_power_response = client.get_max_power(
            cups=supply.cups,
            distributor_code=supply.distributorCode,
            date_from="2024/01",
            date_to="2024/12"
        )

        print(f"✓ Registros de potencia: {len(max_power_response.max_power)}")

        # Analizar potencias por período
        periods = {}
        for power in max_power_response.max_power:
            period = power.period
            if period not in periods:
                periods[period] = []
            periods[period].append(power.maxPower)

        # Mostrar potencia máxima por período
        for period, powers in periods.items():
            max_power_w = max(powers)
            max_power_kw = max_power_w / 1000
            print(f"Período {period}: {max_power_kw:.2f} kW")

        # Verificar errores específicos
        if max_power_response.distributor_error:
            print("⚠️  Errores encontrados:")
            for error in max_power_response.distributor_error:
                print(f"- {error.distributorName}: {error.errorDescription}")
        else:
            print("✓ Datos obtenidos sin errores")

Consultar potencias con NIF autorizado:

max_power_response = client.get_max_power(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    authorized_nif="87654321B"  # NIF que nos autorizó
)

if max_power_response.max_power:
    # Encontrar la potencia máxima absoluta del período
    all_powers = [p.maxPower for p in max_power_response.max_power]
    peak_power_w = max(all_powers)
    peak_power_kw = peak_power_w / 1000
    print(f"Pico máximo autorizado: {peak_power_kw:.2f} kW")

Identificar mes con mayor demanda:

# Agrupar por mes (idéntico a V1)
monthly_max = {}
for power in max_power_response.max_power:
    month = power.date[:7]  # YYYY/MM
    if month not in monthly_max:
        monthly_max[month] = 0
    monthly_max[month] = max(monthly_max[month], power.maxPower)

if monthly_max:
    peak_month = max(monthly_max, key=monthly_max.get)
    peak_power_kw = monthly_max[peak_month] / 1000
    print(f"Mayor demanda: {peak_power_kw:.2f} kW en {peak_month}")

Comparación V1 vs V2:

# V1 - Lista simple, fallo total si hay errores
max_power_v1 = client_v1.get_max_power(cups, dist, date_from, date_to)  # List[MaxPowerData]

# V2 - Respuesta robusta con manejo de errores
response_v2 = client_v2.get_max_power(cups, dist, date_from, date_to)    # MaxPowerResponse
max_power_v2 = response_v2.max_power                                     # List[MaxPowerData]
errors_v2 = response_v2.distributor_error                               # List[DistributorError]
Parámetros:
  • cups (str) – Código CUPS del punto de suministro (22 caracteres alfanuméricos)

  • distributor_code (str) – Código del distribuidor eléctrico como string (ej: «2» para E-distribución). V2 requiere string

  • date_from (str) – Fecha de inicio en formato YYYY/MM. Se convierte automáticamente si se pasa como datetime/date

  • date_to (str) – Fecha de fin en formato YYYY/MM. Se convierte automáticamente si se pasa como datetime/date

  • authorized_nif (Optional[str]) – NIF de la persona que autorizó la consulta de sus datos. Si se especifica, se consultarán los datos de esa persona

Devuelve:

Objeto MaxPowerResponse que contiene: - max_power: Lista de objetos MaxPowerData validados - distributor_error: Lista de errores por distribuidor si los hay

Tipo del valor devuelto:

MaxPowerResponse

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP crítico (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si las fechas no están en formato mensual válido o los datos no pasan la validación Pydantic

  • ValueError – Si el CUPS no tiene el formato correcto

Ver también

Added in version 2.0: Soporte nativo para authorized_nif y manejo de errores por distribuidor

Nota

Las potencias se devuelven en Vatios (W) como en V1. Para obtener kilovatios (kW) divida el valor entre 1000.

get_reactive_data(cups, distributor_code, date_from, date_to, authorized_nif=None)[fuente]

Obtiene datos de energía reactiva - Funcionalidad EXCLUSIVA de la API V2.

Consulta el endpoint GET /api-private/api/get-reactive-data-v2 para obtener información sobre la energía reactiva consumida por el punto de suministro. Esta funcionalidad es completamente nueva en V2 y no está disponible en V1.

¿Qué es la energía reactiva?

La energía reactiva es la energía eléctrica que no realiza trabajo útil pero es necesaria para el funcionamiento de equipos inductivos (motores, transformadores, etc.). Se mide en kVARh y puede generar penalizaciones en la factura eléctrica.

IMPORTANTE - Limitación de fechas:

Al igual que otros endpoints, solo acepta fechas en formato mensual (YYYY/MM). No se permiten fechas con días específicos.

Información incluida en los datos reactivos:
  • Energía reactiva por período: P1, P2, P3, P4, P5, P6

  • Código y descripción: Información del tipo de medición

  • Períodos mensuales: Datos agregados por mes

  • CUPS asociado: Identificación del punto de suministro

Períodos tarifarios de energía reactiva:
  • P1-P6: Períodos tarifarios según discriminación horaria

  • Valores en kVARh: Energía reactiva consumida en cada período

  • Agregación mensual: Datos totalizados por mes del período consultado

Applications:
  • Análisis de eficiencia energética: Identificar equipos ineficientes

  • Optimización de costes: Reducir penalizaciones por energía reactiva

  • Gestión técnica: Mejorar el factor de potencia de la instalación

  • Auditorías energéticas: Análisis completo del comportamiento eléctrico

Ejemplo

Obtener datos de energía reactiva (exclusivo V2):

with SimpleDatadisClientV2("12345678A", "password") as client:
    supplies_response = client.get_supplies()

    if supplies_response.supplies:
        supply = supplies_response.supplies[0]

        # Energía reactiva del año 2024
        reactive_data = client.get_reactive_data(
            cups=supply.cups,
            distributor_code=supply.distributorCode,
            date_from="2024/01",
            date_to="2024/12"
        )

        print(f"✓ Datos de energía reactiva: {len(reactive_data)} registros")

        for data in reactive_data:
            print(f"CUPS: {data.reactive_energy.cups}")
            print(f"Código: {data.reactive_energy.code}")
            print(f"Descripción: {data.reactive_energy.code_desc}")

            # Analizar energía por períodos
            for energy_record in data.reactive_energy.energy:
                date = energy_record.date
                total_reactive = sum([
                    energy_record.energy_p1 or 0,
                    energy_record.energy_p2 or 0,
                    energy_record.energy_p3 or 0,
                    energy_record.energy_p4 or 0,
                    energy_record.energy_p5 or 0,
                    energy_record.energy_p6 or 0
                ])
                print(f"{date}: {total_reactive:.2f} kVARh total")

            print("---")

Analizar penalizaciones potenciales:

# Buscar meses con alta energía reactiva
for data in reactive_data:
    for energy_record in data.reactive_energy.energy:
        # Calcular energía reactiva total del mes
        monthly_reactive = sum([
            energy_record.energy_p1 or 0,
            energy_record.energy_p2 or 0,
            energy_record.energy_p3 or 0,
            energy_record.energy_p4 or 0,
            energy_record.energy_p5 or 0,
            energy_record.energy_p6 or 0
        ])

        if monthly_reactive > 1000:  # Umbral de ejemplo
            print(f"⚠️  {energy_record.date}: Alta energía reactiva ({monthly_reactive:.2f} kVARh)")
            print("   → Revisar equipos inductivos para optimizar factor de potencia")

Consultar con NIF autorizado:

reactive_data = client.get_reactive_data(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/06",
    authorized_nif="87654321B"
)

if reactive_data:
    print("Datos de energía reactiva obtenidos con autorización")

¿Por qué no está disponible en V1?:

# V1 - Esta funcionalidad NO EXISTE
# client_v1.get_reactive_data()  # ← AttributeError: no existe

# V2 - Funcionalidad completamente nueva
reactive_data = client_v2.get_reactive_data(...)  # ✓ Disponible
Parámetros:
  • cups (str) – Código CUPS del punto de suministro (22 caracteres alfanuméricos)

  • distributor_code (str) – Código del distribuidor eléctrico como string (ej: «2» para E-distribución)

  • date_from (str) – Fecha de inicio en formato YYYY/MM

  • date_to (str) – Fecha de fin en formato YYYY/MM

  • authorized_nif (Optional[str]) – NIF de la persona que autorizó la consulta de sus datos. Si se especifica, se consultarán los datos de esa persona

Devuelve:

Lista de objetos ReactiveData validados con Pydantic. Cada objeto contiene información detallada de energía reactiva por períodos tarifarios y fechas

Tipo del valor devuelto:

List[ReactiveData]

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si las fechas no están en formato mensual válido o los datos no pasan la validación Pydantic

  • ValueError – Si el CUPS no tiene el formato correcto

Ver también

  • Documentación oficial: GET /api-private/api/get-reactive-data-v2

  • Para datos de energía activa: get_consumption()

  • Para datos de potencia máxima: get_max_power()

  • Información sobre factor de potencia y energía reactiva en documentación técnica

Added in version 2.0: Funcionalidad completamente nueva, no disponible en V1

Nota

Esta funcionalidad puede no estar disponible para todos los tipos de punto o distribuidores. Consulte con su distribuidor la disponibilidad de estos datos.

Advertencia

La energía reactiva puede generar penalizaciones en la factura eléctrica. Use estos datos para optimizar el factor de potencia de su instalación.

get_supplies(authorized_nif=None, distributor_code=None)[fuente]

Obtiene la lista de puntos de suministro con manejo mejorado de errores (V2).

Consulta el endpoint GET /api-private/api/get-supplies-v2 para obtener todos los puntos de suministro eléctrico con manejo mejorado de errores por distribuidor. A diferencia de V1, la V2 devuelve una respuesta estructurada que incluye tanto los suministros válidos como información detallada de errores por cada distribuidor.

Ventajas de V2 sobre V1:
  • Manejo de errores por distribuidor: Información detallada de fallos específicos

  • Respuesta estructurada: SuppliesResponse con supplies y distributor_error

  • Mayor robustez: Operación exitosa aunque algunos distribuidores fallen

  • Información diagnóstica: Códigos y descripciones de errores específicos

La respuesta incluye:
  • supplies: Lista de puntos de suministro válidos (idénticos a V1)

  • distributor_error: Lista de errores específicos por distribuidor
    • distributorCode: Código del distribuidor con problemas

    • distributorName: Nombre del distribuidor

    • errorCode: Código específico del error

    • errorDescription: Descripción detallada del problema

Ejemplo

Uso básico con manejo de errores V2:

with SimpleDatadisClientV2("12345678A", "password") as client:
    response = client.get_supplies()

    print(f"✓ Suministros obtenidos: {len(response.supplies)}")

    # Mostrar información de suministros
    for supply in response.supplies:
        print(f"CUPS: {supply.cups}")
        print(f"Distribuidor: {supply.distributor} (código: {supply.distributorCode})")
        print(f"Dirección: {supply.address}")
        print("---")

    # Verificar y manejar errores por distribuidor
    if response.distributor_error:
        print(f"⚠️  Errores encontrados en {len(response.distributor_error)} distribuidores:")
        for error in response.distributor_error:
            print(f"- {error.distributorName} ({error.distributorCode}): {error.errorDescription}")
    else:
        print("✓ Todos los distribuidores respondieron correctamente")

Comparación V1 vs V2:

# V1 - Lista simple, fallo total si hay errores
supplies_v1 = client_v1.get_supplies()  # List[SupplyData] or Exception

# V2 - Respuesta robusta con información de errores
response_v2 = client_v2.get_supplies()   # SuppliesResponse
supplies_v2 = response_v2.supplies       # List[SupplyData]
errors_v2 = response_v2.distributor_error # List[DistributorError]

Filtrar por distribuidor específico:

# Solo suministros de E-distribución
response = client.get_supplies(distributor_code="2")

if response.supplies:
    print("Suministros de E-distribución encontrados")
elif response.distributor_error:
    for error in response.distributor_error:
        if error.distributorCode == "2":
            print(f"Error en E-distribución: {error.errorDescription}")
Parámetros:
  • authorized_nif (Optional[str]) – NIF de una persona autorizada para consultar sus suministros. Si se especifica, se obtendrán los suministros de esa persona autorizada en lugar de los del usuario autenticado

  • distributor_code (Optional[str]) – Código del distribuidor para filtrar suministros. Solo acepta strings en V2 (ej: «2» para E-distribución)

Devuelve:

Objeto SuppliesResponse que contiene: - supplies: Lista de objetos SupplyData validados - distributor_error: Lista de errores por distribuidor si los hay

Tipo del valor devuelto:

SuppliesResponse

Muestra:
  • AuthenticationError – Si las credenciales son inválidas o el token expira

  • APIError – Si la API devuelve un error HTTP crítico (400, 403, 404, 500, etc.)

  • DatadisError – Si ocurren errores de conexión o timeouts repetidos

  • ValidationError – Si los datos devueltos no pasan la validación Pydantic

Ver también

  • Documentación oficial: GET /api-private/api/get-supplies-v2

  • Comparar con SimpleDatadisClientV1.get_supplies() para diferencias

  • Para obtener detalles del contrato: get_contract_detail()

Added in version 2.0: Manejo de errores por distribuidor y respuesta estructurada

Nota

A diferencia de V1, esta operación puede tener éxito parcial: obtener suministros de algunos distribuidores aunque otros fallen.