API Inventario

API REST para concesionarios Inventario.pro

v1.0.0

Introducción

API REST para concesionarios integrados con Inventario.pro. Permite consultar el catálogo de vehículos (coches, motos, campers, renting y gama), contenido web (blog, promociones, sliders, landings, SEO), accesorios, recambios y datos del concesionario. Incluye endpoints de escritura para formularios de contacto y reservas con TPV Redsys.

Base URL

https://api-web.inventario.pro
Importante: Esta API es principalmente de solo lectura (GET). Las excepciones son POST /form para el envío de formularios de contacto, POST /price-notices para el registro de avisos de precio, y POST /reservation / POST /reservation/confirm para la gestión de reservas con TPV Redsys.

Autenticación

Las credenciales corresponden a la web configurada en web.webs y sus accounts en web.webs_accounts.

Headers requeridos en todas las peticiones

X-API-Key: api_key_de_la_web
X-API-Token: api_token_de_la_web

Los endpoints de vehículos (/cars, /motorcycles, /campers, /renting) soportan multicuenta: si la web tiene varios accounts asociados, devuelven el catálogo combinado con los vehículos del account principal primero.

Seguridad: Las credenciales deben mantenerse privadas.

Endpoint de Customer

Endpoint para obtener la información del customer autenticado junto con su location principal.

GET /customer

Devuelve los datos del customer autenticado con su location principal anidada (incluyendo región).

Ejemplo de respuesta

{
    "data": {
        "full_name": "Concesionario Example",
        "nombre_sociedad": "Example S.L.",
        "email_exportacion": "export@example.com",
        "telefono_exportacion": "912345678",
        "url": "https://www.example.com",
        "url_local": "https://local.example.com",
        "is_webcliente": true,
        "location_principal": {
            "id": 6,
            "name": "Tienda Principal",
            "address": "Calle Example, 1",
            "postal_code": "08001",
            "city": "Barcelona",
            "region": {"id": 52, "name": "Barcelona", "code": "8"},
            "phone_number": "93 000 00 00",
            "mobile_number": "600000000",
            "email": "info@example.com",
            "lat": "41.38879",
            "lng": "2.15899",
            "photo": "https://webclients.inventario.pro/location/1/foto.jpg",
            "horario": "L-V 9:00-20:00",
            "descripcion": null,
            "url_seo": null,
            "title_seo": null,
            "description_seo": null
        }
    }
}

Endpoint de Locations

Endpoint para obtener todas las locations/tiendas del customer autenticado.

GET /locations

Lista todas las locations activas del customer, ordenadas con la location principal primero y después por nombre alfabéticamente. Cada location incluye su región.

Ejemplo de respuesta

{
    "data": [
        {
            "id": 6,
            "name": "Tienda Principal",
            "address": "Calle Example, 1",
            "postal_code": "08001",
            "city": "Barcelona",
            "region": {"id": 52, "name": "Barcelona", "code": "8"},
            "phone_number": "93 000 00 00",
            "mobile_number": "600000000",
            "email": "info@example.com",
            "lat": "41.38879",
            "lng": "2.15899",
            "photo": "https://webclients.inventario.pro/location/1/foto.jpg",
            "horario": "L-V 9:00-20:00",
            "descripcion": null,
            "url_seo": null,
            "title_seo": null,
            "description_seo": null
        }
    ],
    "total": 3
}
GET /locations/{id}

Obtiene una location por su ID.

Endpoints de Coches

Filtrado automático: Todos los coches devueltos pertenecen al customer autenticado (o sus cuentas asociadas si existen) y están publicados en la web.
GET /cars

Lista paginada de coches del customer autenticado.

Parámetros de paginación y ordenación

ParámetroTipoDefaultDescripción
per_pageinteger16Resultados por página
pageinteger1Número de página
sort_bystring|arrayidCampo(s) para ordenar. Acepta valor único o array: sort_by[]=destacado&sort_by[]=price (ver opciones abajo)
sort_orderstring|arraydescDirección: asc o desc. Acepta valor único (aplica a todos) o array paralelo a sort_by
ignore_account_priorityboolean0Si 1, desactiva el orden por cuenta principal y aplica solo el sort_by sobre todos los registros
max_photosintegernullLimitar número de fotos devueltas

Campos disponibles para ordenación (sort_by)

ValorDescripción
idID del vehículo
tituloTítulo del anuncio
kilometrosKilómetros
registration_dateFecha de matriculación
pricePrecio de venta
financing_pricePrecio financiado
financing_monthly_feeCuota mensual financiación
multioption_financing_pricePrecio financiado multiopción
multioption_monthly_feeCuota mensual multiopción
destacadoVehículos destacados primero

Ejemplo de respuesta

{
    "data": [...],
    "total": 150,
    "per_page": 16,
    "current_page": 1,
    "total_pages": 10
}
GET /cars/{id}

Obtiene un coche específico con todos sus detalles.

Parámetros opcionales

ParámetroTipoDescripción
max_photosintegerLimitar número de fotos devueltas

Estructura de respuesta del vehículo

Los datos del vehículo se organizan en bloques:

BloqueDescripciónCampos principales
id, customer_id, featuredCampos raízID del vehículo, ID del customer propietario, destacado
dataDatos principalesmake, model, version, title, body_style, color, registration_date, kilometers...
locationUbicaciónname, city, postal_code, region, address
characteristicsCaracterísticas técnicaspower, transmission, gears, doors, seats, cylinder_capacity...
more_informationInformación adicionalnumber_of_owners, has_service_book, is_national, is_crashed...
consumptionConsumo y emisionesfuel, average_consumption, environmental_badge, autonomy...
dimensionsDimensionesheight, width, longitude, trunk_capacity, tank_capacity, tare
pricesPreciosprice, previous_price, financing, multioption_financing...
paymentPagobank (si hay banco configurado), tpv (si hay TPV configurado: tpv_id, tpv_name, price, price_type)
equipmentEquipamientostandard, extra, inventario
picturesFotosoriginal, large, medium, order, is_main

Sitemap

GET /cars/sitemap

Listado ligero de coches para generación de sitemap. Sin paginación. Acepta los mismos filtros dinámicos que /cars (FILTR_, INC_, etc.).

Ejemplo de respuesta

[
    {
        "id": 334760,
        "offer_type_id": 1,
        "make": "BMW",
        "model": "Serie 3",
        "fuel_id": 3,
        "transmission_id": 2,
        "body_style_id": 1
    }
]

Endpoints de Renting

Endpoints para vehículos disponibles en modalidad de renting/suscripción.

GET /cars/renting

Lista paginada de coches con renting disponible. Incluye el campo renting_cuota_minima con la cuota mensual mínima.

Parámetros adicionales de filtrado

ParámetroDescripciónEjemplo
BT_renting_cuota_minimaCuota mínima mayor o igual aBT_renting_cuota_minima=200
ST_renting_cuota_minimaCuota mínima menor o igual aST_renting_cuota_minima=500
FILTR_total_monthsMeses de contrato exactosFILTR_total_months=36
FILTR_kilometers_includedKilómetros incluidos exactosFILTR_kilometers_included=15000

Campo de ordenación adicional

renting_cuota_minima - Ordenar por cuota mínima de renting

Ejemplo de respuesta

{
    "data": [
        {
            "id": 334760,
            "titulo": "BMW Serie 3...",
            "renting_cuota_minima": 232,
            ...
        }
    ],
    "total": 15,
    "per_page": 16,
    "current_page": 1,
    "total_pages": 1
}
GET /cars/renting/{id}

Obtiene todas las subscriptions/planes de renting disponibles para un vehículo específico.

Ejemplo de respuesta

{
    "data": [
        {
            "id": 25,
            "total_months": 12,
            "kilometers_included": 2000,
            "monthly_fee": 232,
            "conditions": "Condiciones del contrato...",
            "is_professional_sale": false,
            "is_private_sale": true
        },
        {
            "id": 7,
            "total_months": 60,
            "kilometers_included": 15000,
            "monthly_fee": 500,
            "conditions": null,
            "is_professional_sale": true,
            "is_private_sale": true
        }
    ],
    "total": 2
}

Respuesta de error (vehículo no encontrado)

{"error": "Not found", "message": "Vehículo no encontrado"}

Endpoints de Filtros

Endpoints para obtener las opciones disponibles para cada filtro. Devuelven solo valores que existen en el inventario actual del customer.

Filtrado cruzado: Todos estos endpoints aceptan los mismos parámetros de filtrado dinámico (FILTR_, INC_, etc.) que el listado de coches. Esto permite obtener, por ejemplo, solo las marcas que tienen coches de gasolina: /cars/filters/makes?FILTR_combustible_id=3

Filtros con opciones (devuelven lista con conteo)

GET /cars/filters/makes

Marcas disponibles

[{"id": 1, "name": "BMW", "total": 15}]
GET /cars/filters/models/{marcaId}

Modelos de una marca específica

[{"id": 10, "name": "Serie 3", "total": 5}]
GET /cars/filters/fuels

Tipos de combustible

[{"id": 1, "name": "Gasolina", "total": 45}]
GET /cars/filters/colors

Colores disponibles

[{"id": 5, "name": "Negro", "total": 30}]
GET /cars/filters/transmissions

Tipos de transmisión

[{"id": 1, "name": "Manual", "total": 60}]
GET /cars/filters/seats

Número de asientos

[{"value": 5, "total": 80}]
GET /cars/filters/doors

Número de puertas

[{"value": 5, "total": 70}]
GET /cars/filters/years

Años de matriculación

[{"value": 2024, "total": 25}]
GET /cars/filters/ad-subtypes

Tipos de carrocería (SUV, Sedán...)

[{"id": 1, "name": "SUV", "total": 40}]
GET /cars/filters/badges

Distintivos ambientales

[{"id": 4, "name": "ECO", "total": 20}]
GET /cars/filters/offer-types

Tipo de oferta (Ocasión, Nuevo, KM0...)

[{"id": 1, "name": "Ocasión", "total": 100}]

Filtros de rango (devuelven min/max)

GET /cars/filters/prices

Rango de precios de venta

{"min": 5000, "max": 150000}
GET /cars/filters/financed-prices

Rango de precios financiados

{"min": 4500, "max": 140000}
GET /cars/filters/installments

Rango de cuotas mensuales (financiación básica)

{"min": 99, "max": 1500}
GET /cars/filters/multioption-installments

Rango de cuotas mensuales (multiopción)

{"min": 149, "max": 1200}
GET /cars/filters/mileage

Rango de kilómetros

{"min": 0, "max": 250000}
GET /cars/filters/power

Rango de potencia (CV)

{"min": 75, "max": 500}
GET /cars/filters/status

Estados disponibles (Nuevo, Usado, etc.)

[{"id": 1, "name": "Usado", "total": 120}]

Búsqueda Heurística

Endpoint especial para búsqueda por texto libre y resolución de slugs a IDs de filtro.

Búsqueda por texto ?query=

GET /cars/filters/heuristic?query={texto}

Busca coincidencias en la tabla heurística y devuelve resultados agrupados por marcas, modelos y carrocerías. El texto se normaliza (tildes, mayúsculas, caracteres especiales) antes de comparar. Los resultados se filtran por el catálogo activo del customer.

ParámetroTipoDescripción
querystringTexto libre a buscar (ej: "bmw serie", "SUV")
{
  "total": 3,
  "marcas": [
    {"nombre": "BMW", "valor": "bmw", "marca_id": 3}
  ],
  "modelos": [
    {"nombre": "BMW Serie 3", "valor": "bmw-serie-3", "marca_id": 3, "modelo_id": 12}
  ],
  "carrocerias": [
    {"nombre": "SUV", "valor": "suv", "carroceria_id": 5}
  ]
}

Lookup exacto ?url=

GET /cars/filters/heuristic?url={slug}

Resuelve un slug heurístico a sus IDs de marca, modelo y carrocería para aplicar filtros directamente. Devuelve null en los campos que no corresponden al tipo de entrada.

ParámetroTipoDescripción
urlstringSlug exacto del valor heurístico (ej: "bmw-serie-3")
{"marca_id": 3, "modelo_id": 12, "carroceria_id": null}

Endpoints de Motos

Endpoints para consultar el catálogo de motos del customer. Similar a coches pero sin ads_exports/ads_pricings (precios directos de la tabla moto).

Paginación: Siempre paginado con per_page=16 por defecto.
Campo destacado: El campo destacar_oferta en la tabla moto es el equivalente a destacado de coches.
GET /motorcycles

Lista paginada de motos del customer autenticado.

Parámetros de paginación y ordenación

ParámetroTipoDefaultDescripción
per_pageinteger16Resultados por página
pageinteger1Número de página
sort_bystring|arrayidCampo(s) para ordenar: id, titulo, kilometros, matriculacion_year, precio, destacar_oferta. Acepta array: sort_by[]=destacar_oferta&sort_by[]=precio
sort_orderstring|arraydescDirección: asc o desc. Acepta valor único o array paralelo a sort_by
ignore_account_priorityboolean0Si 1, desactiva el orden por cuenta principal y aplica solo el sort_by sobre todos los registros
max_photosintegernullLimitar número de fotos devueltas

Filtrado dinámico (FILTR_, INC_, EXC_, BTW_, BT_, ST_, LIKE_)

Campos permitidos: marca_id, combustible_id, cambio_id, color_id, tipo_id, estado_id, location_id, tipo_carnet_id, kilometros, potencia, matriculacion_year, matriculacion_month, precio, precio_ant, cilindrada, titulo, modelo, referencia, descripcion, destacar_oferta, tipo_operacion
Campo especial (solo BT_/ST_): photo_count — filtra por número de fotos

Ejemplo de respuesta

{
    "data": [
        {
            "id": "7890",
            "featured": false,
            "data": {
                "make": {"id": 56, "name": "Yamaha"},
                "model": "MT-07",
                "title": "Yamaha MT-07 ABS",
                "body_style": {"id": 8, "name": "Naked"},
                "offer_type": {"id": 1, "name": "Ocasión"},
                "license_type": {"id": 1, "name": "A2"},
                "color": {"id": 3, "name": "Negro"},
                "reference": "MOT-001",
                "url": "yamaha-mt-07-abs",
                "registration_year": 2022,
                "registration_month": 5,
                "kilometers": 8500,
                "operation_type": 1,
                "sold_date": null,
                "created_at": "2025-01-10 10:30:00",
                "updated_at": "2025-02-01 14:20:00"
            },
            "location": {
                "id": 6,
                "name": "Tienda Principal",
                "city": "Barcelona",
                "postal_code": "08001",
                "region": {"id": 52, "name": "Barcelona"},
                "address": "Calle Example, 1"
            },
            "characteristics": {
                "power": 73,
                "transmission": {"id": 1, "name": "Manual"},
                "cylinder_capacity": 689
            },
            "consumption": {
                "fuel": {"id": 1, "name": "Gasolina"},
                "environmental_badge": {"id": 4, "name": "ECO"}
            },
            "prices": {
                "price": 5990.00,
                "previous_price": 6500.00,
                "professional_price": null,
                "is_vat_deductible": false
            },
            "description": "Moto en perfecto estado...",
            "pictures": [
                {
                    "original": "https://webclients.inventario.pro/moto/1/7890/abc123_original.jpg",
                    "large": "https://webclients.inventario.pro/moto/1/7890/abc123_large.jpg",
                    "medium": "https://webclients.inventario.pro/moto/1/7890/abc123_medium.jpg",
                    "order": 1,
                    "is_main": true
                }
            ]
        }
    ],
    "total": 45,
    "per_page": 16,
    "current_page": 1,
    "total_pages": 3
}
GET /motorcycles/{id}

Obtiene una moto específica con todos sus detalles. Sin wrapper data en la respuesta.

Parámetros opcionales

ParámetroTipoDescripción
max_photosintegerLimitar número de fotos devueltas
Sección payment: Solo incluye bank (si hay banco configurado). El bloque tpv no está disponible para motos — la reserva por TPV Redsys solo es funcional para coches.

Filtros de Motos

Endpoints para obtener las opciones disponibles. Devuelven solo valores del inventario actual del customer.

GET /motorcycles/filters/makes

Marcas de motos disponibles

[{"id": 56, "name": "Yamaha", "total": 12}]
GET /motorcycles/filters/models/{marcaId}

Modelos de una marca específica

[{"value": "MT-07", "total": 3}]
GET /motorcycles/filters/fuels

Tipos de combustible

[{"id": 1, "name": "Gasolina", "total": 40}]
GET /motorcycles/filters/transmissions

Tipos de transmisión

[{"id": 1, "name": "Manual", "total": 35}]
GET /motorcycles/filters/colors

Colores disponibles

[{"id": 3, "name": "Negro", "total": 15}]
GET /motorcycles/filters/status

Estados de las motos

[{"id": 1, "name": "Nuevo", "total": 10}]
GET /motorcycles/filters/offer-types

Tipos de oferta

[{"id": 1, "name": "Ocasión", "total": 30}]
GET /motorcycles/filters/license-types

Tipos de carnet necesarios

[{"id": 1, "name": "A2", "total": 20}]
GET /motorcycles/filters/years

Años de matriculación

[{"value": 2023, "total": 8}]
GET /motorcycles/filters/mileage

Rango de kilómetros

{"min": 0, "max": 50000}
GET /motorcycles/filters/power

Rango de potencia (CV)

{"min": 15, "max": 200}
GET /motorcycles/filters/prices

Rango de precios

{"min": 2000, "max": 25000}

Endpoints de Campers

Endpoints para consultar el catálogo de autocaravanas del customer. Similar a motos, sin ads_exports/ads_pricings (precios directos de la tabla camper).

Paginación: Siempre paginado con per_page=16 por defecto.
Estructura similar a coches: Los campers usan las mismas secciones characteristics y dimensions. Characteristics incluye seats, bunks, bedrooms y bed_types. Dimensions incluye longitude (longitud), height, width, tare, total_weight y payload.
Tipos de cama: El campo bed_types devuelve un array de objetos con valores fijos: Plegable (0), Individual (1), Doble (2), Literas (3).
GET /campers

Lista paginada de campers del customer autenticado.

Parámetros de paginación y ordenación

ParámetroTipoDefaultDescripción
per_pageinteger16Resultados por página
pageinteger1Número de página
sort_bystring|arrayidCampo(s) para ordenar: id, titulo, kilometros, matriculacion_year, precio, destacar_oferta. Acepta array: sort_by[]=destacar_oferta&sort_by[]=precio
sort_orderstring|arraydescDirección: asc o desc. Acepta valor único o array paralelo a sort_by
ignore_account_priorityboolean0Si 1, desactiva el orden por cuenta principal y aplica solo el sort_by sobre todos los registros
max_photosintegernullLimitar número de fotos devueltas

Filtrado dinámico (FILTR_, INC_, EXC_, BTW_, BT_, ST_, LIKE_)

Campos permitidos: marca_id, ad_subtype_id, combustible_id, cambio_id, color_id, tipo_id, estado_id, disponibilidad_id, location_id, kilometros, potencia, matriculacion_year, matriculacion_month, precio, precio_ant, precio_pro, longitud, anchura, altura, peso_total, tara, carga_util, literas, plazas, tipo_camas_ids, num_habs, titulo, referencia, modelo, equipamiento, garantia, destacar_oferta, tipo_operacion
Campo especial (solo BT_/ST_): photo_count — filtra por número de fotos

Ejemplo de respuesta

{
    "data": [
        {
            "id": "96",
            "featured": true,
            "data": {
                "make": {"id": 1536, "name": "Hymer"},
                "model": "B-Klasse 580",
                "title": "Hymer B-Klasse 580 Automática",
                "title_complement": "Equipamiento Premium",
                "body_style": {"id": 14, "name": "Integral"},
                "offer_type": {"id": 1, "name": "Ocasión"},
                "availability": {"id": 1, "name": "Disponible"},
                "status": {"id": 2, "name": "Seminuevo"},
                "color": {"id": 1, "name": "Blanco"},
                "reference": "CAMP-001",
                "url": "hymer-b-klasse-580-auto",
                "registration_year": 2020,
                "registration_month": 6,
                "kilometers": 35000,
                "itv_year": 2024,
                "itv_month": 5,
                "operation_type": 1,
                "sold_date": null,
                "created_at": "2025-10-16 13:21:21",
                "updated_at": "2025-11-28 10:45:30"
            },
            "location": {
                "id": 6,
                "name": "Tienda Principal",
                "city": "Barcelona",
                "postal_code": "08001",
                "region": {"id": 52, "name": "Barcelona"},
                "address": "Calle Example, 1"
            },
            "characteristics": {
                "power": 177,
                "transmission": {"id": 2, "name": "Automático"},
                "seats": "4",
                "bunks": "4",
                "bedrooms": 2,
                "bed_types": [
                    {"id": 2, "nombre": "Doble"},
                    {"id": 3, "nombre": "Literas"}
                ]
            },
            "dimensions": {
                "height": 295,
                "width": 233,
                "longitude": 699,
                "tare": 3100,
                "total_weight": 3500,
                "payload": 400
            },
            "consumption": {
                "fuel": {"id": 2, "name": "Diesel"}
            },
            "prices": {
                "warranty": "2 años",
                "price": 59900.00,
                "previous_price": 65000.00,
                "professional_price": 57000.00,
                "is_vat_deductible": true
            },
            "description": "Autocaravana en perfecto estado...",
            "equipment": "Aire acondicionado, calefacción Truma, placa solar...",
            "pictures": [
                {
                    "original": "https://webclients.inventario.pro/camper/1/96/abc123_original.jpg",
                    "large": "https://webclients.inventario.pro/camper/1/96/abc123_large.jpg",
                    "medium": "https://webclients.inventario.pro/camper/1/96/abc123_medium.jpg",
                    "order": 1,
                    "is_main": true
                }
            ]
        }
    ],
    "total": 18,
    "per_page": 16,
    "current_page": 1,
    "total_pages": 2
}
GET /campers/{id}

Obtiene un camper específico con todos sus detalles. Sin wrapper data en la respuesta.

Parámetros opcionales

ParámetroTipoDescripción
max_photosintegerLimitar número de fotos devueltas
Sección payment: Solo incluye bank (si hay banco configurado). El bloque tpv no está disponible para campers — la reserva por TPV Redsys solo es funcional para coches.

Filtros de Campers

Endpoints para obtener las opciones disponibles. Devuelven solo valores del inventario actual del customer.

GET /campers/filters/makes

Marcas de campers disponibles

[{"id": 1536, "name": "Hymer", "total": 5}]
GET /campers/filters/ad-subtypes

Tipos de carrocería (Integral, Perfilada...)

[{"id": 14, "name": "Integral", "total": 8}]
GET /campers/filters/fuels

Tipos de combustible

[{"id": 2, "name": "Diesel", "total": 15}]
GET /campers/filters/transmissions

Tipos de transmisión

[{"id": 2, "name": "Automático", "total": 12}]
GET /campers/filters/colors

Colores disponibles

[{"id": 1, "name": "Blanco", "total": 10}]
GET /campers/filters/status

Estados de los campers

[{"id": 2, "name": "Seminuevo", "total": 6}]
GET /campers/filters/offer-types

Tipos de oferta

[{"id": 1, "name": "Ocasión", "total": 14}]
GET /campers/filters/years

Años de matriculación

[{"value": 2020, "total": 4}]
GET /campers/filters/mileage

Rango de kilómetros

{"min": 5000, "max": 120000}
GET /campers/filters/power

Rango de potencia (CV)

{"min": 120, "max": 200}
GET /campers/filters/prices

Rango de precios

{"min": 25000, "max": 150000}

Sistema de Filtrado Dinámico

El listado de coches y los endpoints de filtros soportan un sistema de filtrado dinámico mediante prefijos en los parámetros de query. Esto permite construir consultas complejas de forma flexible.

Prefijos disponibles

PrefijoOperaciónEjemploSQL Equivalente
FILTR_ Igualdad exacta FILTR_combustible_id=3 WHERE combustible_id = 3
INC_ Incluir (IN) INC_marca_id[]=1&INC_marca_id[]=2 WHERE marca_id IN (1, 2)
EXC_ Excluir (NOT IN) EXC_color_id[]=5&EXC_color_id[]=6 WHERE color_id NOT IN (5, 6)
BTW_ Entre (BETWEEN) BTW_kilometros[]=0&BTW_kilometros[]=50000 WHERE kilometros BETWEEN 0 AND 50000
BT_ Mayor o igual (>=) BT_price=15000 WHERE price >= 15000
ST_ Menor o igual (<=) ST_kilometros=100000 WHERE kilometros <= 100000
LIKE_ Búsqueda parcial LIKE_titulo=mercedes WHERE titulo LIKE 'mercedes%'

Campos permitidos

Campos del vehículo (coche)

marca_id, modelo_id, combustible_id, color_id, cambio_id, tipo_id, estado_id, disponibilidad_id, ad_subtype_id, location_id, emisiones_id, distintivo_ambiental, kilometros, potencia, puertas, asientos, cilindrada, marchas, registration_date, manufacturing_year, titulo, version, referencia, accidentado, nacional, clasico, competicion, metalizado

Campos de precios (ads_pricings)

price, previous_price, financing_price, repair_price, professional_price, new_price, financing_monthly_fee, financing_number_fees, multioption_financing_price, multioption_monthly_fee, multioption_number_fees, multioption_tin, multioption_tae, multioption_entry, multioption_final_installment, is_vat_deductible

Campos especiales

destacado - Indica si el vehículo está destacado (1 o 0)
region_id - Filtra por región de la location (JOIN automático a tabla location)
year - Filtra por año: usa YEAR(registration_date) si existe, sino manufacturing_year
photo_count - Solo con BT_ / ST_. Filtra por número de fotos comerciales (subquery sobre photo_coche). Ejemplo: BT_photo_count=5 devuelve coches con 5 o más fotos

Ejemplos de uso

Coches BMW o Audi de gasolina

GET /cars?INC_marca_id[]=1&INC_marca_id[]=2&FILTR_combustible_id=3

Coches entre 15.000€ y 30.000€ con menos de 50.000km

GET /cars?BT_price=15000&ST_price=30000&ST_kilometros=50000

Coches automáticos matriculados desde 2020

GET /cars?FILTR_cambio_id=2&BT_registration_date=2020-01-01

Buscar coches que contengan "mercedes" en el título, ordenados por precio

GET /cars?LIKE_titulo=mercedes&sort_by=price&sort_order=asc

Obtener marcas disponibles para coches de gasolina

GET /cars/filters/makes?FILTR_combustible_id=3

Endpoints de Gama

Endpoints para consultar la gama de vehículos nuevos: secciones (marcas), promociones, modelos de gama, versiones, características y multimedia.

Jerarquía: Sección → Gama / Promoción → Versiones / Características / Multimedia. La sección es la entidad principal asociada al customer. Todas las URLs están anidadas bajo /model-sections.
Imágenes: Todos los campos de imagen devuelven la URL completa (ej: https://webclients.inventario.pro/gama/{customerId}/seccion/{seccionId}/...). Si no hay imagen, el campo devuelve null.
Textos traducidos: Algunos recursos (Gama, Promoción, Característica) incluyen campos de texto (titulo, texto, descripcion_titulo, etc.) obtenidos de la tabla de traducciones. Devuelven null si no hay traducción disponible.

Secciones de Gama

GET /model-sections

Lista las secciones de gama del customer autenticado, ordenadas por orden.

Parámetros opcionales

ParámetroTipoDescripción
limitintegerLimitar número de resultados

Ejemplo de respuesta

{
    "data": [
        {
            "id": 1,
            "titulo": "BMW",
            "logo": "https://webclients.inventario.pro/gama/1/seccion/1/logo.png",
            "url_seo": "bmw",
            "imagen_principal": "https://webclients.inventario.pro/gama/1/seccion/1/bmw.jpg",
            "imagen_principal_hover": "https://webclients.inventario.pro/gama/1/seccion/1/bmw-hover.jpg",
            "orden": 1,
            "color": "#1c69d4",
            "email": "gama@concesionario.com",
            "marca": {"id": 5, "nombre": "BMW"}
        }
    ],
    "total": 3
}
GET /model-sections/url/{url}

Obtiene una sección de gama por su URL SEO.

GET /model-sections/{seccionId}

Obtiene una sección de gama por su ID.

Promociones de Gama

GET /model-sections/{seccionId}/offers

Lista las promociones de una sección de gama.

Ejemplo de respuesta

{
    "data": [
        {
            "id": 10,
            "gama_seccion_id": 1,
            "titulo": "Oferta de verano BMW",
            "texto": "<p>Descripción de la promoción...</p>",
            "url_seo": "oferta-verano",
            "destacado": true,
            "imagen_listado": "https://webclients.inventario.pro/gama/1/seccion/1/promocion/10/listado.jpg",
            "imagen_principal": "https://webclients.inventario.pro/gama/1/seccion/1/promocion/10/principal.jpg",
            "fecha_inicio": "2025-06-01",
            "fecha_fin": "2025-09-30",
            "tipo": {"id": 1, "name": "Oferta"}
        }
    ],
    "total": 2
}
GET /model-sections/{seccionId}/offers/url/{url}

Obtiene una promoción por sección y URL SEO.

GET /model-sections/{seccionId}/offers/{id}

Obtiene una promoción por su ID dentro de una sección.

Gamas (Modelos)

GET /model-sections/{seccionId}/gamas

Lista las gamas de una sección. Incluye precio_min (precio mínimo de sus versiones).

Ejemplo de respuesta

{
    "data": [
        {
            "id": 5,
            "gama_seccion_id": 1,
            "titulo": "Serie 3",
            "url_seo": "serie-3",
            "imagen_listado": "https://webclients.inventario.pro/gama/1/seccion/1/modelo/5/listado.jpg",
            "imagen_principal": "https://webclients.inventario.pro/gama/1/seccion/1/modelo/5/principal.jpg",
            "descripcion_titulo": "La nueva Serie 3",
            "descripcion_texto": "<p>Texto de descripción...</p>",
            "video_titulo": "Descubre la Serie 3",
            "video_texto": "<p>Texto del vídeo...</p>",
            "precio_min": 35900,
            "model_characteristics": {
                "warranty": 24, "body_style_id": 3,
                "doors": 4, "seats": 5,
                "trunk_capacity": 480
            },
            "modelo": {"id": 10, "nombre": "Serie 3"}
        }
    ],
    "total": 5
}
GET /model-sections/{seccionId}/gamas/url/{url}

Obtiene una gama por sección y URL SEO.

GET /model-sections/{seccionId}/gamas/{gamaId}

Obtiene una gama por su ID dentro de una sección.

Sub-recursos de Gama

GET /model-sections/{seccionId}/gamas/{gamaId}/features

Lista las características de una gama. Incluye titulo y texto traducidos.

GET /model-sections/{seccionId}/gamas/{gamaId}/features/{id}

Obtiene una característica por su ID.

GET /model-sections/{seccionId}/gamas/{gamaId}/versions

Lista las versiones/acabados de una gama con precios y equipamiento.

Ejemplo de respuesta

{
    "data": [
        {
            "id": 20,
            "gama_id": 5,
            "titulo": "318d Business",
            "precio": 35900,
            "entrada": 5000,
            "cuota_mensual": 299,
            "ultima_cuota": 15000,
            "potencia": 150,
            "imagen": "https://webclients.inventario.pro/gama/1/seccion/1/modelo/5/version/20/foto.jpg",
            "condiciones": "Oferta válida hasta...",
            "equipamiento": ["Navegador", "Faros LED", "Cámara", null]
        }
    ],
    "total": 4
}
GET /model-sections/{seccionId}/gamas/{gamaId}/versions/{id}

Obtiene una versión por su ID.

GET /model-sections/{seccionId}/gamas/{gamaId}/multimedia

Lista los recursos multimedia de una gama (fotos, vídeos).

GET /model-sections/{seccionId}/gamas/{gamaId}/multimedia/{id}

Obtiene un recurso multimedia por su ID.

Endpoints de Accesorios

Endpoints para consultar el catálogo de accesorios del customer.

Paginación opcional: Por defecto devuelve todos los accesorios. Usa per_page para activar paginación.
Categorías jerárquicas: Al filtrar por category_id, se incluyen automáticamente los accesorios de las subcategorías hijas.
GET /accessories

Lista los accesorios del customer, ordenados por título ascendente.

Parámetros opcionales

ParámetroTipoDescripción
ad_type_idintegerFiltrar por tipo de anuncio
category_idintegerFiltrar por categoría (incluye subcategorías)
precio_minfloatPrecio mínimo (>=)
precio_maxfloatPrecio máximo (<=)
per_pageintegerActivar paginación con N resultados por página
pageintegerNúmero de página (solo con per_page)

Ejemplo de respuesta

{
    "data": [
        {
            "id": 455,
            "titulo": "Casco integral GT",
            "descripcion": "Casco de alta protección...",
            "precio": 249.99,
            "precio_ant": 299.99,
            "marca": "AGV",
            "color": "Negro",
            "referencia": "AGV-GT-001",
            "ad_type_id": 2,
            "location_id": 6,
            "category": {"id": 80, "name": "Accesorios cascos"},
            "photos": [
                {
                    "principal": true,
                    "medium": "https://webclients.inventario.pro/accesorio/1/455/abc123_medium.jpg",
                    "large": "https://webclients.inventario.pro/accesorio/1/455/abc123_large.jpg",
                    "original": "https://webclients.inventario.pro/accesorio/1/455/abc123_original.jpg"
                }
            ],
            "idate": "2025-10-16 13:21:21"
        }
    ],
    "total": 15
}
GET /accessories/categories

Lista las categorías de accesorios en estructura jerárquica (padres con subcategorías hijas).

Parámetros opcionales

ParámetroTipoDescripción
ad_type_idintegerFiltrar categorías por tipo de anuncio

Ejemplo de respuesta

{
    "data": [
        {
            "id": 16,
            "name": "Agua - Aseo",
            "ad_type_id": 1,
            "children": [
                {"id": 18, "name": "Bombas"},
                {"id": 19, "name": "Baños"}
            ]
        }
    ],
    "total": 52
}
GET /accessories/{id}

Obtiene un accesorio por su ID con todas sus fotos.

Endpoints de Recambios

Endpoints para consultar el catálogo de recambios del customer. Misma estructura que accesorios con campos adicionales estado_id y disponibilidad_id.

Categorías propias: Los recambios usan la tabla categoria_recambio (diferente de la de accesorios). Al filtrar por category_id, se incluyen subcategorías hijas.
GET /spare-parts

Lista los recambios del customer, ordenados por título ascendente.

Parámetros opcionales

ParámetroTipoDescripción
ad_type_idintegerFiltrar por tipo de anuncio
category_idintegerFiltrar por categoría (incluye subcategorías)
precio_minfloatPrecio mínimo (>=)
precio_maxfloatPrecio máximo (<=)
per_pageintegerActivar paginación con N resultados por página
pageintegerNúmero de página (solo con per_page)

Ejemplo de respuesta

{
    "data": [
        {
            "id": 126,
            "titulo": "Amortiguador delantero",
            "descripcion": "Amortiguador compatible con...",
            "precio": 123.99,
            "precio_ant": 150.00,
            "marca": "Monroe",
            "color": "Negro",
            "referencia": "MON-AD-500",
            "ad_type_id": 2,
            "location_id": 6,
            "estado_id": 1,
            "disponibilidad_id": 1,
            "category": {"id": 146, "name": "Por correa"},
            "photos": [
                {
                    "principal": true,
                    "medium": "https://webclients.inventario.pro/recambio/1/126/abc123_medium.jpg",
                    "large": "https://webclients.inventario.pro/recambio/1/126/abc123_large.jpg",
                    "original": "https://webclients.inventario.pro/recambio/1/126/abc123_original.jpg"
                }
            ],
            "idate": "2025-11-04 15:32:53"
        }
    ],
    "total": 8
}
GET /spare-parts/categories

Lista las categorías de recambios en estructura jerárquica (padres con subcategorías hijas). Usa la tabla categoria_recambio.

Parámetros opcionales

ParámetroTipoDescripción
ad_type_idintegerFiltrar categorías por tipo de anuncio
GET /spare-parts/{id}

Obtiene un recambio por su ID con todas sus fotos.

Endpoints de Blog

Endpoints para consultar las entradas del blog del customer.

Paginación opcional: Por defecto devuelve todas las entradas. Si se pasa per_page, se activa la paginación con los campos total, per_page, current_page y total_pages. Usa page para navegar entre páginas.
GET /blog

Lista las entradas del blog, ordenadas por destacado y luego por ID descendente.

Parámetros opcionales

ParámetroTipoDescripción
categoriastringFiltrar por categoría
per_pageintegerActivar paginación con N resultados por página
pageintegerNúmero de página (solo con per_page)

Ejemplo de respuesta (sin paginación)

{
    "data": [
        {
            "id": 5,
            "titulo": "Novedades del mes",
            "descripcion": "<p>Contenido del artículo...</p>",
            "photo": "https://webclients.inventario.pro/blog/1/foto.jpg",
            "alt_imagen": "Texto alternativo",
            "url": "novedades-del-mes",
            "destacado": true,
            "categoria": "noticias",
            "meta_title": "Novedades",
            "meta_description": "Descripción SEO",
            "idate": "2025-01-15"
        }
    ],
    "total": 12
}
GET /blog/{id}

Obtiene una entrada de blog por su ID.

Endpoints de Promociones

Endpoints para consultar las promociones/ofertas del customer.

Paginación opcional: Mismo comportamiento que Blog. Por defecto devuelve todas las entradas. Usa per_page para activar paginación.
GET /offers

Lista las promociones, ordenadas por campo orden ascendente.

Parámetros opcionales

ParámetroTipoDescripción
tipo_idintegerFiltrar por tipo de oferta
ad_type_idintegerFiltrar por tipo de anuncio
per_pageintegerActivar paginación con N resultados por página
pageintegerNúmero de página (solo con per_page)

Ejemplo de respuesta

{
    "data": [
        {
            "id": 3,
            "titulo": "Oferta especial primavera",
            "desc_corta": "Descuentos en toda la gama",
            "descripcion": "<p>Descripción completa...</p>",
            "precio": 15990.00,
            "photo_s": "https://webclients.inventario.pro/offers/1/thumb.jpg",
            "photo_b": "https://webclients.inventario.pro/offers/1/grande.jpg",
            "alt_imagen": "Oferta primavera",
            "valido_hasta": "2025-06-30",
            "destacado": false,
            "orden": 1,
            "campo_libre": "Texto adicional",
            "ad_type_id": 1,
            "meta_title": "Oferta primavera",
            "meta_description": "Descripción SEO",
            "idate": "2025-03-01",
            "tipo": {"id": 1, "nombre": "Oferta"}
        }
    ],
    "total": 5
}
GET /offers/{id}

Obtiene una promoción por su ID. Incluye el objeto tipo con id y nombre.

Endpoints de SEO

Endpoints para consultar contenidos SEO y colecciones del customer.

Colecciones

GET /seo/collections

Lista todas las colecciones del customer, ordenadas alfabéticamente por h1_pagina. Devuelve solo campos básicos. Con paginación opcional mediante per_page.

Ejemplo de respuesta

{
    "data": [
        {
            "id": 74,
            "carpeta_seo": "coleccionestest",
            "url_semantica": "furgonetas-en-badalona",
            "h1_pagina": "Prueba New landing",
            "mostrar_home": 1,
            "mostrar_listado": 1,
            "mostrar_listadoseo": 1
        }
    ],
    "total": 5
}
GET /seo/collections?url={url}

Obtiene una colección por su URL compuesta (carpeta_seo/url_semantica). Sin wrapper data en la respuesta.

Contenidos SEO

GET /seo/content

Lista todos los contenidos SEO del customer, ordenados por ID descendente. Con paginación opcional mediante per_page.

Ejemplo de respuesta

{
    "data": [
        {
            "id": 25,
            "pagina": "/ocasion",
            "seccion": "hero",
            "titulo": "Coches de Ocasión",
            "contenido": "<p>Encuentra tu coche ideal...</p>",
            "meta_title": "Coches de Ocasión | Concesionario",
            "meta_description": "Amplia selección de coches de ocasión...",
            "orden": 1,
            "created_at": "2025-01-05"
        }
    ],
    "total": 12
}
GET /seo/content?url={url}

Obtiene un contenido SEO por su URL. Sin wrapper data en la respuesta.

Endpoints de Sliders Web

Endpoints para consultar los sliders configurados para el customer.

GET /web-sliders

Lista todos los sliders web del customer, ordenados por orden ascendente.

Ejemplo de respuesta

{
    "data": [
        {
            "id": 3,
            "nombre": "Slider Homepage",
            "ubicacion": "home",
            "orden": 1,
            "items": [
                {
                    "titulo": "Ofertas de Enero",
                    "subtitulo": "Hasta 30% de descuento",
                    "imagen": "https://webclients.inventario.pro/web-slider/1/3/item1.jpg",
                    "link": "/offers/ofertas-enero",
                    "target": "_self",
                    "orden": 1
                }
            ]
        }
    ],
    "total": 2
}
GET /web-sliders/{id}

Obtiene un slider por su ID con sus items. Sin wrapper data en la respuesta.

Endpoints de Landings

Endpoints para consultar landings personalizadas con sus diferentes secciones (FAQs, Forms, Heroes, Icons).

Plantillas: Cada landing tiene asociada una plantilla que define su estructura y layout.
URL SEO: Las landings se consultan principalmente por su URL SEO mediante el parámetro ?url=.
GET /landings?url={seoUrl}

Obtiene una landing por su URL SEO. El parámetro url es obligatorio. Sin wrapper data en la respuesta.

Parámetros requeridos

ParámetroTipoDescripción
url *stringURL SEO de la landing

Ejemplo de respuesta

{
    "id": 5,
    "titulo": "Landing Renting",
    "seo_url": "renting",
    "meta_title": "Renting de Coches | Concesionario",
    "meta_description": "Descubre nuestras ofertas de renting...",
    "template": {
        "id": 2,
        "name": "Template Renting"
    },
    "details": [
        {
            "seccion": "hero",
            "titulo": "Renting flexible",
            "contenido": "<p>Sin entrada, sin permanencia...</p>",
            "orden": 1
        }
    ]
}

Sub-recursos de Landing

GET /landings/{id}/faqs

Obtiene las FAQs de una landing con sus items. Sin wrapper data en la respuesta.

Ejemplo de respuesta

{
    "id": 8,
    "landing_id": 5,
    "titulo": "Preguntas Frecuentes",
    "items": [
        {
            "pregunta": "¿Qué incluye el renting?",
            "respuesta": "El renting incluye mantenimiento, seguro...",
            "orden": 1
        }
    ]
}
GET /landings/{id}/forms

Obtiene el formulario de contacto de una landing. Sin wrapper data en la respuesta.

GET /landings/{id}/heroes

Obtiene la sección hero de una landing con sus imágenes. Sin wrapper data en la respuesta.

GET /landings/{id}/icons

Obtiene los iconos/características de una landing con sus items. Sin wrapper data en la respuesta.

Página web — Configuración

Endpoints del schema web. Devuelven la configuración y contenido de la página web identificada por el X-API-Key.

GET /web

Devuelve la configuración completa de la web: idiomas, dominios, logos y code injections (solo los no borradores).

Cache: 15 min · clave web:{id}:config

Ejemplo de respuesta

{
    "id": "abc123",
    "name": "Mi Concesionario",
    "language_seo_type": "subdomain",
    "configuration": { ... },
    "theme": { ... },
    "languages": [{ "language_id": 1, "code": "es", "is_default": true, "seo": { ... } }],
    "domains": [{ "domain": "www.ejemplo.com", "redirect_to": null, "is_main": true }],
    "logos": [{ "device_id": 1, "image_name": "logo.png", "url": "https://..." }],
    "code_injections": [{ "name": "GA", "code": "...", "location": "head", "position": 1 }],
    "contact": { "email": "info@ejemplo.com", "phone": "912345678" }
}
language_seo_type: ENUM('subdomain', 'folder', 'parameter')
code_injections.location: ENUM('head', 'body_start', 'body_end')

Página web — Socials

GET /web/socials

Lista las redes sociales configuradas para la web, ordenadas por posición. Acepta un filtro opcional de idioma.

Cache: 15 min · clave web:{id}:socials (sin filtro) o web:{id}:socials:{language_id} (con filtro)

Parámetros

ParámetroTipoRequeridoDescripción
language_idintegerNoSi se indica, devuelve solo las redes del idioma especificado

Ejemplo de respuesta

{
    "data": [
        { "social_id": 1, "social_name": "Instagram", "language_id": 40, "name": "@miempresa", "url": "https://instagram.com/...", "position": 1 }
    ]
}

Página web — Redirects

GET /web/redirects

Lista las redirecciones activas (is_draft=false), ordenadas por posición.

Cache: 15 min · clave web:{id}:redirects

Ejemplo de respuesta

{
    "data": [
        { "route_from": "/old-path", "route_to": "/new-path", "position": 1 }
    ]
}

Página web — Páginas

Gestión de páginas y sus componentes. Solo se devuelven páginas y componentes con is_draft=false.

GET /web/pages

Devuelve las páginas activas en estructura de árbol recursiva. Las páginas raíz incluyen un array children con sus páginas hijas (que a su vez pueden tener sus propios children), soportando cualquier nivel de profundidad.

Cache: 15 min · clave web:{id}:pages

Ejemplo de respuesta

{
    "data": [
        {
            "id": 1, "web_page_id": null, "type_id": 3, "type_name": "home",
            "name": "Inicio", "show_in_nav": true, "show_in_footer": false, "show_in_legal": false, "position": 1,
            "languages": [{ "language_id": 1, "code": "es", "title": "Inicio", "route": "/", "seo": { ... } }],
            "children": []
        },
        {
            "id": 2, "web_page_id": null, "type_id": 2, "type_name": "listing",
            "name": "Coches", "show_in_nav": true, "show_in_footer": false, "show_in_legal": false, "position": 2,
            "languages": [{ "language_id": 1, "code": "es", "title": "Coches", "route": "/cars", "seo": { ... } }],
            "children": [
                {
                    "id": 10, "web_page_id": 2, "type_id": 2, "type_name": "listing",
                    "name": "Ocasión", "show_in_nav": true, "show_in_footer": false, "show_in_legal": false, "position": 1,
                    "languages": [{ "language_id": 1, "code": "es", "title": "Ocasión", "route": "/cars/ocasion", "seo": { ... } }],
                    "children": []
                }
            ]
        }
    ]
}
GET /web/pages/{id}

Devuelve el detalle de una página con sus componentes, traducciones y fotos por dispositivo. Sin wrapper data.

Ejemplo de respuesta

{
    "id": 1, "web_page_id": null, "type_id": 3, "type_name": "home",
    "name": "Inicio", "show_in_nav": true, "show_in_footer": false, "show_in_legal": false, "position": 1,
    "languages": [{ "language_id": 1, "code": "es", "title": "Inicio", "route": "/", "seo": { ... } }],
    "components": [
        {
            "id": 10, "component_id": 5, "keyname": "hero-banner", "category": "heroes",
            "ad_type_id": null, "configuration": { ... }, "position": 1,
            "languages": [{ "language_id": 1, "keyname": "titulo", "value": "Bienvenido" }],
            "photos": [
                { "keyname": "bg", "position": 1, "devices": [{ "device_id": 1, "image_name": "bg.jpg", "url": "https://..." }] }
            ]
        }
    ]
}

Página web — Reglas SEO

GET /web/seo-rules

Lista todas las reglas SEO de las páginas activas de la web, con sus filtros y traducciones. Ordenadas por web_page_id, priority.

Ejemplo de respuesta

{
    "data": [
        {
            "id": 1, "web_page_id": 3, "slug_pattern": "/cars/{marca}/{modelo}", "priority": 1,
            "filters": [{ "filter_type": "marca", "filter_value_id": 12, "position": 1 }],
            "languages": [{ "language_id": 1, "code": "es", "h1": "Coches BMW de ocasión", "seo": { ... } }]
        }
    ]
}

Página web — Resolución de URL

GET /web/pages/resolve

Resuelve una URL arbitraria a la página web correspondiente y devuelve la información completa de la página (igual que /web/pages/{id}: componentes, traducciones, fotos) junto con la regla SEO aplicable y sus filtros resueltos. Endpoint principal para el renderizado de páginas en el frontend.

Parámetros

ParámetroTipoRequeridoDescripción
urlstringRuta de la URL a resolver (ej. /cars/audi/suv)
language_idintegerID del idioma

Lógica de resolución

  1. Busca la página cuyo route sea prefijo de la URL (match más largo primero).
  2. Si no hay match → 404.
  3. Si la URL coincide exactamente con el route, o la página no es de tipo listing → devuelve la página con seo_rule: null.
  4. Si hay sufijo, busca la regla SEO cuyo slug_pattern encaje con los segmentos del sufijo, por orden de prioridad (número más bajo = mayor prioridad).
  5. Si ninguna regla encaja → 404 (URL no válida).
  6. Devuelve los filtros resueltos con su filter_value_id y el segmento de URL correspondiente.

Ejemplo de respuesta — con seo_rule

{
    "page": {
        "id": 2, "web_page_id": null, "type_id": 3, "type_name": "listing",
        "name": "Coches", "show_in_nav": true, "show_in_footer": false, "show_in_legal": false, "position": 2,
        "languages": [{ "language_id": 1, "code": "es", "title": "Coches de ocasión", "route": "/cars", "seo": { ... } }],
        "components": [
            {
                "id": 10, "component_id": 5, "keyname": "hero-banner", "category": "heroes",
                "ad_type_id": null, "configuration": { ... }, "position": 1,
                "languages": [{ "language_id": 1, "keyname": "titulo", "value": "Coches de ocasión" }],
                "photos": [{ "keyname": "bg", "position": 1, "devices": [{ "device_id": 1, "image_name": "bg.jpg", "url": "https://..." }] }]
            }
        ]
    },
    "seo_rule": {
        "id": 1,
        "slug_pattern": "{{make}}/{{body_style}}",
        "priority": 2,
        "language": {
            "language_id": 1, "code": "es",
            "h1": "Audi SUV de segunda mano",
            "seo": { ... }
        },
        "resolved_filters": [
            { "filter_type": "make",       "filter_value_id": 852, "url_segment": "audi" },
            { "filter_type": "body_style", "filter_value_id": 7,   "url_segment": "suv"  }
        ]
    }
}

Ejemplo de respuesta — sin seo_rule

{
    "page": { ... },
    "seo_rule": null
}
Tipos de filtro soportados en resolved_filters: make, model, body_style, fuel, transmission, drivetrain
Cache interna de slugs: la resolución de slugs a IDs usa tablas de lookup cacheadas — marcas y modelos (24 h), carrocerías, combustibles, cambios y tracciones (7 días). El endpoint en sí no tiene cache de respuesta.

Estructura de Respuestas

La API utiliza diferentes estructuras de respuesta según el tipo de endpoint para mayor claridad y consistencia.

1. Recursos únicos (detalle/show)

Sin wrapper data - El objeto se devuelve directamente en la raíz de la respuesta.

Endpoints afectados: /cars/{id}, /motorcycles/{id}, /campers/{id}, /blog/{id}, /offers/{id}, /customer, /locations/{id}, /accessories/{id}, /spare-parts/{id}, todos los endpoints de gama (/model-sections/{id}, /models/{id}, etc.), y todos los sub-recursos de landings.

Ejemplo:

{
    "id": "334760",
    "data": { "make": {...}, "model": {...} },
    "location": {...},
    "characteristics": {...},
    "prices": {...}
}

2. Colecciones (listados/index)

Con wrapper data - Los elementos se devuelven dentro de un campo data, junto con metadatos de paginación (total, per_page, current_page, total_pages).

Endpoints afectados: /cars, /motorcycles, /campers, /blog, /offers, /locations, /accessories, /spare-parts, /model-sections, /gamas, etc.

Ejemplo:

{
    "data": [
        {"id": 1, ...},
        {"id": 2, ...}
    ],
    "total": 150,
    "per_page": 16,
    "current_page": 1,
    "total_pages": 10
}

3. Endpoints de filtros

Sin wrapper - Devuelven directamente un array de opciones o un objeto con min/max.

Endpoints afectados: Todos los endpoints bajo /cars/filters/*, /motorcycles/filters/*, /campers/filters/*, /accessories/categories, /spare-parts/categories.

Ejemplo (lista con conteo):

[
    {"id": 1, "name": "BMW", "total": 15},
    {"id": 2, "name": "Audi", "total": 20}
]

Ejemplo (rango):

{"min": 5000, "max": 150000}
Nota: Esta estructura normalizada facilita el consumo de la API desde aplicaciones frontend, permitiendo anticipar el formato de respuesta según el tipo de endpoint.

Formulario de Contacto

Endpoint para enviar formularios de contacto. Envía un email al customer, registra el lead en base de datos y genera un JSONLead para integración CRM.

POST /form

Envía un formulario de contacto. Soporta adjuntos, GDPR, parámetros UTM, JSONLead con información del vehículo y tasación.

El cuerpo de la petición debe ser multipart/form-data (si se adjuntan archivos) o application/x-www-form-urlencoded.

Parámetros del formulario

ParámetroTipoRequeridoDescripción
formularioarrayCampos del formulario. Cada campo: formulario[clave][valor], formulario[clave][nombre], formulario[clave][tipo]
asuntostringNoAsunto del email. Default: "Formulario de contacto desde tu web"
email_tostringNoEmail destinatario. Default: email1_exportacion del customer
ccstringNoEmails en copia separados por comas
ccostringNoEmails en copia oculta separados por comas
gdprboolNoConsentimiento GDPR. Se muestra al final del email como "Acepta comunicaciones comerciales"
files[]fileNoAdjuntos. MIME permitidos: jpg, png, gif, webp, pdf
ad_idintNoID del anuncio de interés (para incluir datos del vehículo en el JSONLead)
ad_type_idintNoTipo de anuncio: 1=camper, 2=moto, 5=coche
urlstringNoURL de origen de la petición
sourcestringNoUTM source
mediumstringNoUTM medium
campaignstringNoUTM campaign
gclidstringNoGoogle Click ID
contact_type_idintNoTipo de contacto. Default: 1. Usar 6 para tasación (activa appraisal_lead)
include_appraisal_leadboolNoFuerza la inclusión del bloque appraisal_lead en el JSONLead
customJLarrayNoCampos custom para el JSONLead. Ej: customJL[sales_lead][landing]=home. Tipos permitidos: client, sales_lead, appraisal_lead

Tipos de campo en formulario

TipoDescripción
textTexto corto (una línea)
text_largeTexto largo (multiline)
numberValor numérico
checkCheckbox (sí/no)
gdprConsentimiento GDPR (uso interno, mejor usar el parámetro gdpr top-level)

Campos lead reconocidos en formulario

Los siguientes nombres de clave dentro de formulario se extraen automáticamente para el registro del lead y el JSONLead:

Lead: first_name, last_name, email, phone, inquiry, postal_code, province

Tasación (appraisal_lead): make, model, mileage, year, fuel, transmission, color, horsepower, doors, comment, due_date

Respuesta exitosa

{
  "success": true,
  "message": "Formulario enviado correctamente",
  "contact_id": 42
}

Errores

CódigoCausa
422formulario ausente o no es un array
422Adjunto con MIME type no permitido
500Error al enviar el email

Ejemplo de petición

POST /form
Content-Type: application/x-www-form-urlencoded

formulario[first_name][valor]=John
formulario[first_name][nombre]=Nombre
formulario[first_name][tipo]=text
formulario[email][valor]=john@example.com
formulario[email][nombre]=Email
formulario[email][tipo]=text
formulario[inquiry][valor]=Me interesa el vehículo
formulario[inquiry][nombre]=Mensaje
formulario[inquiry][tipo]=text_large
gdpr=1
ad_id=12345
ad_type_id=5
source=google
medium=cpc

Avisos de Precio

Endpoint para registrar avisos de bajada de precio para un anuncio. Almacena el registro en web.webs_prices_notices. El web_id se inyecta automáticamente desde la autenticación.

POST /price-notices Auth requerida

Crea un aviso de precio para el usuario indicado. Requiere autenticación (API Key + Token).

Parámetros

ParámetroTipoRequeridoDescripción
ad_idintegerID del anuncio
language_idintegerID del idioma
emailstring (email, max 150)Email del usuario que solicita el aviso
pricenumeric (min 0)Precio actual del anuncio en el momento del registro
urlstring (max 500)URL canónica del anuncio

Respuesta exitosa (HTTP 201)

{
  "success": true,
  "id": 123
}

Errores

CódigoCausa
422Falta algún parámetro requerido o formato inválido

Reserva (TPV Redsys)

Endpoints para gestionar reservas de vehículos mediante TPV Redsys (HMAC_SHA512_V2). Al confirmar el pago se actualiza el estado del vehículo y se envían emails al concessionari y al comprador.

POST /reservation

Crea un registro en web.payments_orders y devuelve los parámetros necesarios para el formulario de pago de Redsys. Requiere autenticación (API Key + Token).

El importe de la reserva (booking_price) se calcula automáticamente a partir de la configuración del TPV (webs_tpvs.configuration: price / price_type) — no se envía en la petición.

El código de pedido Redsys (id_external) se genera automáticamente con el formato YYYY + 8 caracteres alfanuméricos en mayúsculas (12 chars totales, los primeros 4 numéricos según requisito Redsys). Ejemplo: 2026HIBN0GKZ.

Parámetros

ParámetroTipoRequeridoDescripción
namestringNombre del comprador
surnamestringApellidos del comprador
emailstringEmail del comprador
phonestringTeléfono del comprador
ad_idintegerID del anuncio
pricenumericPrecio del anuncio en euros (precio de venta del vehículo)
urlstringNoURL canónica del anuncio (para redirect post-pago)
email_tostringNoEmail del concessionari. Default: email1_exportacion del customer
orderstringNoid_external de una reserva existente para actualizarla (reintento de pago)

Respuesta exitosa

{
  "success": true,
  "data": {
    "order": "2026HIBN0GKZ",
    "booking_price": 300,
    "ad_price": 23900,
    "redsys_url": "https://sis-t.redsys.es:25443/sis/realizarPago",
    "Ds_SignatureVersion": "HMAC_SHA512_V2",
    "Ds_MerchantParameters": "eyJEU19NRVJDSEFOVF...",
    "Ds_Signature": "abc123..."
  }
}

Errores

CódigoCausa
409Vehículo no disponible para reserva (ya reservado o vendido)
422TPV no configurado para este customer
POST /reservation/confirm

Endpoint server-to-server (S2S) de Redsys. La autenticidad se verifica mediante firma HMAC_SHA512_V2.

Al confirmar el pago (código Redsys 0000–0099):

  • Actualiza payments_orders.estado a 2 (confirmado) o 3 (fallido)
  • Marca el vehículo como reservado (estado_id=2) vía API Reserves (coches) o directamente en BD (motos, campers)
  • Envía email de confirmación al concessionari (email1_exportacion/email_to) con JSONLead
  • Envía email de confirmación al comprador (correo)

Siempre devuelve HTTP 200 con cuerpo OK (requisito Redsys).

Códigos de Estado

CódigoDescripción
200Petición exitosa
401No autorizado (falta auth, API Key o Token inválido)
404Recurso no encontrado

Ejemplos de errores

{"error": "No autorizado", "message": "Se requieren los headers X-API-Key y X-API-Token"}
{"error": "No autorizado", "message": "Token inválido"}
{"error": "No autorizado", "message": "API Key inválida"}