Referencia de la API

Documentación de la API

Integra el catálogo de tarifas de luz y gas de PriceVault en tu CRM, ERP o comparador. Consulta ofertas, compáralas y encuentra la más eficiente — el equilibrio entre el mejor precio para tu cliente y la mejor comisión para ti.

Base URL https://pricevault.es/v1

Introducción

La API de PriceVault es REST sobre HTTPS, con peticiones y respuestas en JSON. Todos los endpoints programáticos viven bajo el prefijo /v1. Esta página documenta los endpoints destacados; para la referencia exhaustiva de todos los endpoints y esquemas dispones de la especificación OpenAPI:

  • Swagger UI — interactivo, prueba endpoints desde el navegador.
  • ReDoc — referencia completa, limpia y legible.

Autenticación

Cada petición se autentica con tu API key en la cabecera X-API-Key. Genera y gestiona tus claves desde el dashboard. Trátalas como un secreto: nunca las publiques en el frontend ni en repositorios.

cURL
curl "https://pricevault.es/v1/offers" \
  -H "X-API-Key: pv_live_xxxxxxxxxxxxxxxxxxxx"
  • API key inválida o inactiva → 401 Unauthorized.
  • Cuenta desactivada → 403 Forbidden.

Scopes

Cada API key puede limitarse a un conjunto de scopes (permisos). Si llamas a un endpoint sin el scope requerido, la respuesta es 403 con el scope que falta.

Una API key sin scopes asignados tiene acceso completo. Para integraciones, crea claves con el mínimo de scopes necesarios.
ScopePermite
offers:readConsultar ofertas, comparar y recomendaciones
offers:writeCrear, editar y eliminar ofertas
offers:exportExportar ofertas a CSV
commissions:readConsultar tramos de comisión y calculadora
indexed_prices:readConsultar precios indexados históricos
companies:readConsultar comercializadoras
catalog:readConsultar catálogo de ofertas compartidas
catalog:writeCrear, editar y eliminar entradas del catálogo

Claves vinculadas a una asesoría

Una API key puede estar vinculada a una sola asesoría. Cuando lo está, el parámetro client_id de las consultas se fuerza a esa asesoría; pasar otro distinto devuelve 403. Es el detalle que más confusión genera al integrar.

Convenciones

Paginación

Los listados aceptan limit (1–200, por defecto 50) y offset. La respuesta envuelve los datos: { "total", "limit", "offset", "results": [...] }.

Estado de los registros

Por defecto solo se devuelven registros activos; usa include_inactive=true para incluir los desactivados. El borrado (DELETE) sobre ofertas, asesorías y comercializadoras es lógico (is_active = false), no físico.

Códigos de error

CódigoSignificado
400Petición o formato de archivo inválido.
401Falta la API key o es inválida/inactiva.
403Sin el scope requerido o sin acceso a esa asesoría.
404El recurso no existe.
409Conflicto (nombre duplicado, estado incompatible).
413Archivo mayor de 10 MB.
422Validación de negocio (territorio, tipo de cliente, etc.).
429Límite de peticiones superado.

Listar tarifas

GET /v1/offers Scope: offers:read

El corazón de la API: lista las tarifas de tu organización con filtros ricos por suministro, tarifa de acceso, territorio, comunidad, tipo de cliente y comercializadora.

Parámetros de consulta

ParámetroTipoDescripción
supply_typeLUZ · GASTipo de suministro (por defecto LUZ).
tariff_typestringTarifa de acceso. Ej. 2.0TD, 3.0TD, RL.1.
company_idintFiltrar por comercializadora.
company_namestringBúsqueda parcial por nombre (sin distinción de mayúsculas).
territoryenumpeninsula, canarias, baleares, ceuta_melilla.
communityenumComunidad autónoma (incluye ofertas sin restricción geográfica).
placas_solaresboolFiltrar ofertas con placas solares.
client_typedni · cifParticulares (DNI) o empresas (CIF).
client_idintFiltrar por asesoría (forzado si la key está vinculada).
include_inactiveboolIncluir ofertas inactivas.
limit / offsetintPaginación.
cURL
curl "https://pricevault.es/v1/offers?supply_type=LUZ&tariff_type=2.0TD&territory=peninsula&limit=20" \
  -H "X-API-Key: $PV_KEY"
Respuesta 200
{
  "total": 134,
  "limit": 20,
  "offset": 0,
  "results": [
    {
      "id": 412,
      "offer_name": "Tarifa Hogar 2.0TD",
      "supply_type": "LUZ",
      "tariff_type": "2.0TD",
      "is_indexed": false,
      "company": {
        "id": 12, "name": "Energía X", "logo_url": "https://...",
        "client": { "id": 3, "name": "Asesoría Norte", "image_url": null }
      },
      "e1": 0.142, "e2": 0.108, "e3": 0.085,
      "p1": 0.084, "p2": 0.012,
      "commission": 25.0, "commission_type": "fixed",
      "acepta_dni": true, "acepta_cif": true,
      "is_active": true,
      "created_at": "2026-04-02T10:11:00Z",
      "updated_at": "2026-05-30T08:00:00Z"
    }
  ]
}

Oferta más eficiente

POST /v1/offers/efficient Scope: offers:read

El motor comparador. Dado un perfil de consumo y potencia, rankea las ofertas combinando coste y comisión con una nota de eficiencia. El peso w desplaza el equilibrio entre ahorro para el cliente y comisión para ti.

Cuerpo (JSON)

CampoTipoDescripción
supply_type obligatorioLUZ · GASTipo de suministro.
energiaobjeto e1..e6Consumo anual por periodo, kWh.
potenciaobjeto p1..p6Potencia contratada por periodo, kW.
fee_energia / fee_potenciafloat 1–30Fee en €/MWh.
wfloat 0–1Peso ahorro↔comisión (1 = solo ahorro, 0 = solo comisión; por defecto 0.5).
tariff_type, territory, company_id, limitFiltros del universo a rankear.
cURL
curl -X POST "https://pricevault.es/v1/offers/efficient" \
  -H "X-API-Key: $PV_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "supply_type": "LUZ",
    "energia": { "e1": 1200, "e2": 800, "e3": 600 },
    "potencia": { "p1": 4.6, "p2": 4.6 },
    "fee_energia": 5,
    "fee_potencia": 3,
    "w": 0.5,
    "tariff_type": "2.0TD",
    "limit": 10
  }'
Respuesta 200
{
  "w": 0.5,
  "total": 48,
  "excluded_count": 3,
  "mas_barata_id": 412,
  "mas_comision_id": 533,
  "mas_eficiente_id": 488,
  "results": [
    {
      "offer": {
        "id": 488, "offer_name": "Tarifa Óptima",
        "company": { "id": 12, "name": "Energía X", "logo_url": "..." }
      },
      "cost": { "energia": 312.4, "potencia": 145.0, "excedentes": 0.0, "servicios": 0.0, "total": 457.4 },
      "commission": { "energia": 18.0, "potencia": 6.0, "total": 24.0 },
      "nota": 8.7, "nota_precio": 9.1, "nota_comision": 8.3,
      "is_optimal": true
    }
  ]
}

Recomendar por consumo y potencia

GET /v1/offers/recommend Scope: offers:read

Ordena las ofertas por la comisión esperada según el consumo anual (consumption_mwh) y la potencia contratada (power_kw, solo LUZ). Cada resultado incluye la comisión por consumo y por potencia con el tramo aplicado.

cURL
curl "https://pricevault.es/v1/offers/recommend?consumption_mwh=10&power_kw=4.6&supply_type=LUZ&tariff_type=2.0TD&limit=10" \
  -H "X-API-Key: $PV_KEY"

Comparar ofertas

GET /v1/offers/compare Scope: offers:read

Devuelve el detalle completo de entre 2 y 10 ofertas para mostrarlas lado a lado. Repite el parámetro ids por cada oferta.

cURL
curl "https://pricevault.es/v1/offers/compare?ids=412&ids=488&ids=533" \
  -H "X-API-Key: $PV_KEY"

Calcular comisión de una oferta

GET /v1/offers/{id}/commission-calculator Scope: commissions:read

Calcula el importe exacto de comisión por consumo y/o potencia para una oferta concreta, indicando el tramo aplicado.

cURL
curl "https://pricevault.es/v1/offers/412/commission-calculator?consumption_mwh=10&power_kw=4.6" \
  -H "X-API-Key: $PV_KEY"
Respuesta 200
{
  "offer_id": 412,
  "consumption_mwh": 10,
  "power_kw": 4.6,
  "consumption_commission": {
    "value": 25.0, "commission_type": "fixed", "matched_tier": null
  },
  "power_commission": {
    "value": 6.0, "commission_type": "fixed",
    "matched_tier": { "power_from": 0, "power_to": 10 }
  }
}

Detalle de una oferta

GET /v1/offers/{id} Scope: offers:read

Devuelve la oferta completa, incluyendo tramos de comisión por consumo y potencia, precios indexados históricos y comunidades autónomas cubiertas.

cURL
curl "https://pricevault.es/v1/offers/412" \
  -H "X-API-Key: $PV_KEY"
Para la referencia exhaustiva de todos los endpoints y esquemas, consulta ReDoc.

Crear y editar ofertas

Operaciones de escritura sobre una oferta individual. El borrado es lógico: la oferta queda inactiva, no se elimina.

POST/v1/offersCrear una oferta.offers:write
PATCH/v1/offers/{id}Editar campos (parcial).offers:write
PATCH/v1/offers/{id}/toggleActivar / desactivar.offers:write
DELETE/v1/offers/{id}Desactivar (soft delete).offers:write
Validaciones de negocio (422): al menos un territorio activo · al menos un tipo de cliente (DNI o CIF) · fee_power y placas_solares solo en LUZ · precio_excedentes requiere placas_solares: true.
POST /v1/offers Scope: offers:write

Crea una oferta. Puedes incluir tramos de comisión por consumo (commission_tiers) y por potencia (commission_power_tiers) en la misma llamada.

cURL
curl -X POST "https://pricevault.es/v1/offers" \
  -H "X-API-Key: $PV_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "company_id": 12,
    "offer_name": "Tarifa Hogar 2.0TD",
    "supply_type": "LUZ",
    "tariff_type": "2.0TD",
    "territory_peninsula": true,
    "e1": 0.142, "e2": 0.108, "e3": 0.085,
    "p1": 0.084, "p2": 0.012,
    "commission": 25, "commission_type": "fixed",
    "acepta_dni": true, "acepta_cif": true,
    "commission_tiers": [
      { "consumption_from": 0,  "consumption_to": 10, "commission": 3, "commission_type": "fixed" },
      { "consumption_from": 10, "consumption_to": 50, "commission": 5, "commission_type": "fixed" }
    ]
  }'

Carga y edición masiva

Dos formas de actualizar muchas ofertas a la vez. Ambas son todo-o-nada: si una fila falla, no se aplica ningún cambio.

POST/v1/offers/bulk-patchAplicar los mismos cambios a un lote (hasta 500 ofertas), vía JSON.30/minoffers:write
POST/v1/offers/bulk-updateSubir un XLSX (≤10 MB) con hojas de ofertas, indexados y borrados.10/horaoffers:write

Edición masiva por JSON

cURL
curl -X POST "https://pricevault.es/v1/offers/bulk-patch" \
  -H "X-API-Key: $PV_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "offer_ids": [412, 488, 533],
    "updates": { "is_active": false, "commission": 30 }
  }'

Carga por archivo XLSX

cURL
curl -X POST "https://pricevault.es/v1/offers/bulk-update" \
  -H "X-API-Key: $PV_KEY" \
  -F "file=@tarifas.xlsx"

¿Necesitas la plantilla? Descárgala (precargada con tus ofertas) desde GET /v1/offers/bulk-template y /bulk-template-indexed (parámetro client_id).

Precios indexados

Histórico mensual de precios de las ofertas indexadas (is_indexed: true). El upsert crea o reemplaza el mes indicado en reference_month (formato YYYY-MM-DD).

GET/v1/offers/{id}/indexed-pricesListar el histórico de una oferta.indexed_prices:read
POST/v1/offers/{id}/indexed-pricesUpsert del precio de un mes.offers:write
DELETE/v1/offers/{id}/indexed-prices/{month}Borrar el precio de un mes.offers:write
cURL
curl -X POST "https://pricevault.es/v1/offers/488/indexed-prices" \
  -H "X-API-Key: $PV_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reference_month": "2026-06-01",
    "e1": 0.154, "e2": 0.143, "e3": 0.121,
    "p1": 0.079, "p2": 0.065
  }'

Comercializadoras

Las comercializadoras pertenecen a una asesoría (client_id). La lectura requiere el scope companies:read; la escritura funciona con cualquier API key válida.

GET/v1/companiesListar (paginado).companies:read
GET/v1/companies/{id}Detalle.companies:read
POST/v1/companiesCrear (requiere client_id y name).sin scope
PATCH/v1/companies/{id}Editar.sin scope
PATCH/v1/companies/{id}/toggleActivar / desactivar.sin scope
DELETE/v1/companies/{id}Desactivar.sin scope
cURL
curl -X POST "https://pricevault.es/v1/companies" \
  -H "X-API-Key: $PV_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "client_id": 3, "name": "Energía X", "logo_url": null }'

Asesorías (clientes)

Las asesorías son el primer nivel de tu organización: agrupan comercializadoras y ofertas. Estos endpoints funcionan con cualquier API key válida (sin scope específico).

GET/v1/clientsListar (paginado).sin scope
GET/v1/clients/{id}Detalle.sin scope
POST/v1/clientsCrear. 409 si el nombre existe, 403 si superas el límite del plan.sin scope
PATCH/v1/clients/{id}Editar.sin scope
PATCH/v1/clients/{id}/toggleActivar / desactivar.sin scope
DELETE/v1/clients/{id}Desactivar.sin scope

Estadísticas y exportación

GET/v1/offers/statsTotales por suministro, asesorías, comercializadoras y cargas.offers:read
GET/v1/offers/exportExportar ofertas a CSV (máx. 2000 filas).offers:export
cURL
curl "https://pricevault.es/v1/offers/stats" \
  -H "X-API-Key: $PV_KEY"

Catálogo compartido

El catálogo central de ofertas y empresas reutilizables al que se suscriben tus asesorías. Aquí cubrimos la lectura; la escritura (scope catalog:write, límite 120/min por key) está en la referencia completa.

GET/v1/catalog/companiesEmpresas del catálogo.catalog:read
GET/v1/catalog/offersOfertas del catálogo (filtros company_id, supply_type, client_type).catalog:read
GET/v1/catalog/offers/{id}/indexed-pricesHistórico indexado de una oferta del catálogo.catalog:read
cURL
curl "https://pricevault.es/v1/catalog/offers?supply_type=LUZ&client_type=cif" \
  -H "X-API-Key: $PV_KEY"

Cuenta

Datos de la organización propietaria de la API key. Estos endpoints funcionan con cualquier API key válida (sin scope específico).

GET/v1/accountDatos de la cuenta.sin scope
PATCH/v1/accountActualizar nombre o email (409 si el email ya existe).sin scope
POST/v1/account/passwordCambiar la contraseña (mínimo 8 caracteres).5/5minsin scope
cURL
curl "https://pricevault.es/v1/account" \
  -H "X-API-Key: $PV_KEY"
Respuesta 200
{
  "id": 3,
  "name": "Asesoría Norte",
  "email": "info@asesorianorte.es",
  "is_active": true,
  "created_at": "2026-01-15T09:00:00Z"
}

Cambiar la contraseña

cURL
curl -X POST "https://pricevault.es/v1/account/password" \
  -H "X-API-Key: $PV_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "current_password": "••••••••",
    "new_password": "••••••••"
  }'

Respuesta 204 No Content si el cambio es correcto; 401 si la contraseña actual no coincide.

Suscripción

El plan actual de la cuenta y sus límites. Devuelve 404 si la cuenta no tiene suscripción activa.

GET/v1/subscriptionPlan, estado y límite de asesorías.sin scope
Respuesta 200
{
  "id": 7,
  "plan": "pro",
  "status": "active",
  "clients_limit": 25,
  "trial_ends_at": null,
  "current_period_end": "2026-07-15T00:00:00Z",
  "created_at": "2026-01-15T09:00:00Z"
}

Uso de la API

Telemetría de tus llamadas: registro detallado y resumen agregado. Útil para depurar integraciones y vigilar el consumo.

GET/v1/usageRegistro de llamadas. Filtros: endpoint, status_code, from, to (ISO 8601), paginado.sin scope
GET/v1/usage/summaryTotal de llamadas, desglose por endpoint y p95 de latencia.sin scope
cURL
curl "https://pricevault.es/v1/usage/summary" \
  -H "X-API-Key: $PV_KEY"
Respuesta 200
{
  "total_calls": 18432,
  "calls_by_endpoint": [
    { "endpoint": "GET /v1/offers", "calls": 12045 },
    { "endpoint": "POST /v1/offers/efficient", "calls": 3210 }
  ],
  "p95_response_time_ms": 86
}

Cargas

Seguimiento de las cargas de archivos. Tanto las subidas desde el dashboard como las cargas masivas por API (bulk-update) quedan registradas aquí.

GET/v1/uploadsListar. Filtros: status, client_id, paginado.sin scope
GET/v1/uploads/{id}Detalle de una carga.sin scope
POST/v1/uploadsRegistrar una carga (queda en estado pending).sin scope
PATCH/v1/uploads/{id}Reintentar una carga fallida (409 si no está failed).sin scope
DELETE/v1/uploads/{id}Cancelar una carga pendiente (409 si no está pending).sin scope
cURL
curl "https://pricevault.es/v1/uploads?status=completed&limit=20" \
  -H "X-API-Key: $PV_KEY"