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 "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.
| Scope | Permite |
|---|---|
offers:read | Consultar ofertas, comparar y recomendaciones |
offers:write | Crear, editar y eliminar ofertas |
offers:export | Exportar ofertas a CSV |
commissions:read | Consultar tramos de comisión y calculadora |
indexed_prices:read | Consultar precios indexados históricos |
companies:read | Consultar comercializadoras |
catalog:read | Consultar catálogo de ofertas compartidas |
catalog:write | Crear, 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ódigo | Significado |
|---|---|
400 | Petición o formato de archivo inválido. |
401 | Falta la API key o es inválida/inactiva. |
403 | Sin el scope requerido o sin acceso a esa asesoría. |
404 | El recurso no existe. |
409 | Conflicto (nombre duplicado, estado incompatible). |
413 | Archivo mayor de 10 MB. |
422 | Validación de negocio (territorio, tipo de cliente, etc.). |
429 | Límite de peticiones superado. |
Listar tarifas
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ámetro | Tipo | Descripción |
|---|---|---|
| supply_type | LUZ · GAS | Tipo de suministro (por defecto LUZ). |
| tariff_type | string | Tarifa de acceso. Ej. 2.0TD, 3.0TD, RL.1. |
| company_id | int | Filtrar por comercializadora. |
| company_name | string | Búsqueda parcial por nombre (sin distinción de mayúsculas). |
| territory | enum | peninsula, canarias, baleares, ceuta_melilla. |
| community | enum | Comunidad autónoma (incluye ofertas sin restricción geográfica). |
| placas_solares | bool | Filtrar ofertas con placas solares. |
| client_type | dni · cif | Particulares (DNI) o empresas (CIF). |
| client_id | int | Filtrar por asesoría (forzado si la key está vinculada). |
| include_inactive | bool | Incluir ofertas inactivas. |
| limit / offset | int | Paginación. |
curl "https://pricevault.es/v1/offers?supply_type=LUZ&tariff_type=2.0TD&territory=peninsula&limit=20" \
-H "X-API-Key: $PV_KEY"
{
"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
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)
| Campo | Tipo | Descripción |
|---|---|---|
| supply_type obligatorio | LUZ · GAS | Tipo de suministro. |
| energia | objeto e1..e6 | Consumo anual por periodo, kWh. |
| potencia | objeto p1..p6 | Potencia contratada por periodo, kW. |
| fee_energia / fee_potencia | float 1–30 | Fee en €/MWh. |
| w | float 0–1 | Peso ahorro↔comisión (1 = solo ahorro, 0 = solo comisión; por defecto 0.5). |
| tariff_type, territory, company_id, limit | — | Filtros del universo a rankear. |
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
}'
{
"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
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 "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
Devuelve el detalle completo de entre 2 y 10 ofertas para mostrarlas lado a lado. Repite el parámetro ids por cada oferta.
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
Calcula el importe exacto de comisión por consumo y/o potencia para una oferta concreta, indicando el tramo aplicado.
curl "https://pricevault.es/v1/offers/412/commission-calculator?consumption_mwh=10&power_kw=4.6" \
-H "X-API-Key: $PV_KEY"
{
"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
Devuelve la oferta completa, incluyendo tramos de comisión por consumo y potencia, precios indexados históricos y comunidades autónomas cubiertas.
curl "https://pricevault.es/v1/offers/412" \
-H "X-API-Key: $PV_KEY"
Crear y editar ofertas
Operaciones de escritura sobre una oferta individual. El borrado es lógico: la oferta queda inactiva, no se elimina.
/v1/offersCrear una oferta.offers:write/v1/offers/{id}Editar campos (parcial).offers:write/v1/offers/{id}/toggleActivar / desactivar.offers:write/v1/offers/{id}Desactivar (soft delete).offers:writefee_power y placas_solares solo en LUZ · precio_excedentes requiere placas_solares: true.
Crea una oferta. Puedes incluir tramos de comisión por consumo (commission_tiers) y por potencia (commission_power_tiers) en la misma llamada.
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.
/v1/offers/bulk-patchAplicar los mismos cambios a un lote (hasta 500 ofertas), vía JSON.30/minoffers:write/v1/offers/bulk-updateSubir un XLSX (≤10 MB) con hojas de ofertas, indexados y borrados.10/horaoffers:writeEdición masiva por JSON
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 -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).
/v1/offers/{id}/indexed-pricesListar el histórico de una oferta.indexed_prices:read/v1/offers/{id}/indexed-pricesUpsert del precio de un mes.offers:write/v1/offers/{id}/indexed-prices/{month}Borrar el precio de un mes.offers:writecurl -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.
/v1/companiesListar (paginado).companies:read/v1/companies/{id}Detalle.companies:read/v1/companiesCrear (requiere client_id y name).sin scope/v1/companies/{id}Editar.sin scope/v1/companies/{id}/toggleActivar / desactivar.sin scope/v1/companies/{id}Desactivar.sin scopecurl -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).
/v1/clientsListar (paginado).sin scope/v1/clients/{id}Detalle.sin scope/v1/clientsCrear. 409 si el nombre existe, 403 si superas el límite del plan.sin scope/v1/clients/{id}Editar.sin scope/v1/clients/{id}/toggleActivar / desactivar.sin scope/v1/clients/{id}Desactivar.sin scopeEstadísticas y exportación
/v1/offers/statsTotales por suministro, asesorías, comercializadoras y cargas.offers:read/v1/offers/exportExportar ofertas a CSV (máx. 2000 filas).offers:exportcurl "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.
/v1/catalog/companiesEmpresas del catálogo.catalog:read/v1/catalog/offersOfertas del catálogo (filtros company_id, supply_type, client_type).catalog:read/v1/catalog/offers/{id}/indexed-pricesHistórico indexado de una oferta del catálogo.catalog:readcurl "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).
/v1/accountDatos de la cuenta.sin scope/v1/accountActualizar nombre o email (409 si el email ya existe).sin scope/v1/account/passwordCambiar la contraseña (mínimo 8 caracteres).5/5minsin scopecurl "https://pricevault.es/v1/account" \
-H "X-API-Key: $PV_KEY"
{
"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 -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.
/v1/subscriptionPlan, estado y límite de asesorías.sin scope{
"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.
/v1/usageRegistro de llamadas. Filtros: endpoint, status_code, from, to (ISO 8601), paginado.sin scope/v1/usage/summaryTotal de llamadas, desglose por endpoint y p95 de latencia.sin scopecurl "https://pricevault.es/v1/usage/summary" \
-H "X-API-Key: $PV_KEY"
{
"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í.
/v1/uploadsListar. Filtros: status, client_id, paginado.sin scope/v1/uploads/{id}Detalle de una carga.sin scope/v1/uploadsRegistrar una carga (queda en estado pending).sin scope/v1/uploads/{id}Reintentar una carga fallida (409 si no está failed).sin scope/v1/uploads/{id}Cancelar una carga pendiente (409 si no está pending).sin scopecurl "https://pricevault.es/v1/uploads?status=completed&limit=20" \
-H "X-API-Key: $PV_KEY"