Files
Autoparts-DB/docs/API.md
consultoria-as fb6ea31100 docs: add README, API reference, and architecture documentation
- README.md: project overview, features, quick start, API overview
- docs/API.md: full endpoint reference with examples
- docs/ARCHITECTURE.md: system diagram, DB schema, data pipeline, auth flow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 22:30:53 +00:00

27 KiB

API Reference - Nexus Autoparts

Documentacion completa de la API REST del sistema Nexus Autoparts.

Base URL

http://localhost:5000

Autenticacion

Los endpoints protegidos requieren un header Authorization: Bearer <access_token>. Los access tokens tienen una duracion de 15 minutos. Usa el endpoint /api/auth/refresh para obtener uno nuevo.


1. Auth

POST /api/auth/register

Registra un nuevo usuario. La cuenta inicia inactiva (requiere activacion por ADMIN).

Auth: No requerida

Request body:

{
  "name": "Juan Perez",
  "email": "juan@taller.com",
  "password": "secreto123",
  "role": "TALLER",
  "business_name": "Taller Perez",
  "phone": "555-1234",
  "address": "Calle 1 #123"
}
Campo Tipo Requerido Descripcion
name string Si Nombre del usuario
email string Si Email (unico)
password string Si Password (se hashea con bcrypt)
role string Si TALLER o BODEGA
business_name string Si Nombre del negocio
phone string No Telefono
address string No Direccion

Response 201:

{
  "message": "Registration successful. Account pending activation."
}

Response 409:

{
  "error": "Email already registered"
}

POST /api/auth/login

Autentica un usuario y retorna access + refresh tokens.

Auth: No requerida

Request body:

{
  "email": "juan@taller.com",
  "password": "secreto123"
}

Response 200:

{
  "access_token": "eyJhbGci...",
  "refresh_token": "abc123def456...",
  "user": {
    "id": 1,
    "name": "Juan Perez",
    "role": "TALLER",
    "business_name": "Taller Perez"
  }
}

Errores:

  • 401 - Email o password invalido
  • 403 - Cuenta no activa

POST /api/auth/refresh

Renueva un access token usando un refresh token valido.

Auth: No requerida

Request body:

{
  "refresh_token": "abc123def456..."
}

Response 200:

{
  "access_token": "eyJhbGci..."
}

Errores:

  • 401 - Refresh token invalido o expirado

GET /api/auth/me

Retorna la informacion del usuario autenticado (extraida del JWT).

Auth: Cualquier rol autenticado

Response 200:

{
  "user_id": 1,
  "role": "TALLER",
  "business_name": "Taller Perez"
}

2. Admin - User Management

GET /api/admin/users

Lista todos los usuarios registrados.

Auth: ADMIN, OWNER

Response 200:

[
  {
    "id": 1,
    "name": "Juan Perez",
    "email": "juan@taller.com",
    "business_name": "Taller Perez",
    "phone": "555-1234",
    "is_active": true,
    "created_at": "2026-03-01T10:00:00",
    "last_login": "2026-03-18T08:30:00",
    "role": "TALLER"
  }
]

PUT /api/admin/users/{user_id}/activate

Activa o desactiva un usuario.

Auth: ADMIN, OWNER

Request body:

{
  "is_active": true
}

Response 200:

{
  "message": "User updated",
  "is_active": true
}

GET /api/admin/stats

Estadisticas generales del catalogo. Usa pg_class.reltuples para tablas grandes (performance).

Auth: No requerida (publico)

Response 200:

{
  "categories": 10,
  "groups": 150,
  "manufacturers": 200,
  "parts": 1400000,
  "aftermarket": 300000,
  "fitment": 12000000000
}

3. Catalog - Brands, Models, Years, Engines

GET /api/brands

Lista todas las marcas que tienen vehiculos en la base de datos.

Auth: No requerida

Query params:

Param Tipo Descripcion
detailed bool Si true, incluye model_count y vehicle_count
region int Bitmask de region para filtrar marcas

Response 200 (simple):

["ACURA", "AUDI", "BMW", "CHEVROLET", "FORD", "HONDA", "TOYOTA"]

Response 200 (detailed=true):

[
  {
    "name": "TOYOTA",
    "model_count": 85,
    "vehicle_count": 4200
  }
]

GET /api/models

Lista modelos, opcionalmente filtrados por marca.

Auth: No requerida

Query params:

Param Tipo Descripcion
brand string Nombre de la marca (ILIKE)
detailed bool Si true con brand, incluye year_min/max, vehicle_count, engine_count

Response 200 (simple):

["4RUNNER", "CAMRY", "COROLLA", "HIGHLANDER", "RAV4"]

Response 200 (detailed=true&brand=TOYOTA):

[
  {
    "name": "CAMRY",
    "year_min": 1987,
    "year_max": 2026,
    "year_count": 40,
    "vehicle_count": 320,
    "engine_count": 15
  }
]

GET /api/years

Lista anos disponibles, opcionalmente filtrados.

Auth: No requerida

Query params:

Param Tipo Descripcion
brand string Filtrar por marca
model string Filtrar por modelo

Response 200:

[2026, 2025, 2024, 2023, 2022]

GET /api/engines

Lista motores disponibles, opcionalmente filtrados.

Auth: No requerida

Query params:

Param Tipo Descripcion
brand string Filtrar por marca
model string Filtrar por modelo
year int Filtrar por ano

Response 200:

["1.8L I4 Gas", "2.0L I4 Hybrid", "2.5L I4 Gas"]

GET /api/vehicles

Busqueda de vehiculos con filtros y paginacion.

Auth: No requerida

Query params:

Param Tipo Default Descripcion
brand string - Filtrar por marca
model string - Filtrar por modelo
year int - Filtrar por ano
engine string - Filtrar por motor
page int 1 Pagina
per_page int 50 Items por pagina (max 100)

Response 200:

{
  "data": [
    {
      "brand": "TOYOTA",
      "model": "CAMRY",
      "year": 2020,
      "engine": "2.5L I4 Gas",
      "power_hp": 203,
      "torque_nm": 250,
      "displacement_cc": 2487,
      "cylinders": 4,
      "fuel_type": "gasoline",
      "trim_level": "LE",
      "drivetrain": "FWD",
      "transmission": "automatic"
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 50,
    "total": 320,
    "total_pages": 7
  }
}

GET /api/model-year-engine

Similar a /api/vehicles pero retorna id (mye_id) para navegacion al catalogo de partes.

Auth: No requerida

Query params: Igual que /api/vehicles, mas with_parts (bool) para filtrar solo vehiculos con partes catalogadas.

Response 200:

{
  "data": [
    {
      "id": 12345,
      "brand": "TOYOTA",
      "model": "CAMRY",
      "year": 2020,
      "engine": "2.5L I4 Gas",
      "trim_level": "LE",
      "drivetrain": "FWD",
      "transmission": "automatic"
    }
  ],
  "pagination": { "page": 1, "per_page": 50, "total": 120, "total_pages": 3 }
}

GET /api/catalog/stats

Estadisticas basicas del catalogo.

Auth: No requerida

Response 200:

{
  "brands": 107,
  "models": 10923,
  "vehicles": 82456,
  "parts": 1400000
}

4. Parts Catalog

GET /api/categories

Lista categorias de partes en estructura de arbol.

Auth: No requerida

Response 200:

[
  {
    "id": 1,
    "name": "Engine",
    "name_es": "Motor",
    "slug": "engine",
    "icon_name": "engine",
    "display_order": 1,
    "children": [
      {
        "id": 5,
        "name": "Engine Electrical",
        "name_es": "Electrico del Motor",
        "slug": "engine-electrical",
        "icon_name": null,
        "display_order": 2,
        "children": []
      }
    ]
  }
]

GET /api/categories/{category_id}/groups

Lista grupos (subcategorias) dentro de una categoria.

Auth: No requerida

Response 200:

[
  {
    "id": 10,
    "name": "Oil Filter",
    "name_es": "Filtro de Aceite",
    "slug": "oil-filter",
    "display_order": 1
  }
]

GET /api/parts

Lista partes con paginacion y filtros.

Auth: No requerida

Query params:

Param Tipo Descripcion
group_id int Filtrar por grupo
category_id int Filtrar por categoria
search string Busqueda por nombre o numero OEM (ILIKE)
page int Pagina (default 1)
per_page int Items por pagina (max 100)

Response 200:

{
  "data": [
    {
      "id": 500,
      "oem_part_number": "04152-YZZA1",
      "name": "Oil Filter",
      "name_es": "Filtro de Aceite",
      "group_id": 10,
      "group_name": "Oil Filters",
      "category_name": "Engine",
      "image_url": "/static/parts_images/abc.jpg"
    }
  ],
  "pagination": { "page": 1, "per_page": 50, "total": 200, "total_pages": 4 }
}

GET /api/parts/{part_id}

Detalle de una parte especifica.

Auth: No requerida

Response 200:

{
  "id": 500,
  "oem_part_number": "04152-YZZA1",
  "name": "Oil Filter",
  "name_es": "Filtro de Aceite",
  "description": "Engine oil filter element",
  "description_es": "Elemento de filtro de aceite del motor",
  "group_id": 10,
  "group_name": "Oil Filters",
  "group_name_es": "Filtros de Aceite",
  "category_id": 1,
  "category_name": "Engine",
  "category_name_es": "Motor",
  "image_url": null
}

GET /api/vehicles/{mye_id}/categories

Categorias de partes disponibles para un vehiculo especifico.

Auth: No requerida

Response 200:

[
  {
    "id": 1,
    "name": "Engine",
    "name_es": "Motor",
    "slug": "engine",
    "icon_name": "engine",
    "display_order": 1
  }
]

GET /api/vehicles/{mye_id}/groups

Grupos de partes disponibles para un vehiculo, opcionalmente filtrado por categoria.

Auth: No requerida

Query params:

Param Tipo Descripcion
category_id int Filtrar por categoria

Response 200:

[
  {
    "id": 10,
    "name": "Oil Filters",
    "name_es": "Filtros de Aceite",
    "slug": "oil-filters",
    "display_order": 1,
    "parts_count": 5
  }
]

GET /api/vehicles/{mye_id}/parts

Partes para un vehiculo especifico con paginacion.

Auth: No requerida

Query params:

Param Tipo Descripcion
category_id int Filtrar por categoria
group_id int Filtrar por grupo
page int Pagina (default 1)
per_page int Items por pagina (max 100)

Response 200:

{
  "data": [
    {
      "id": 500,
      "oem_part_number": "04152-YZZA1",
      "name": "Oil Filter",
      "name_es": "Filtro de Aceite",
      "quantity_required": 1,
      "position": "front",
      "category_name": "Engine",
      "group_name": "Oil Filters",
      "image_url": null
    }
  ],
  "pagination": { "page": 1, "per_page": 50, "total": 45, "total_pages": 1 }
}

5. Cross-References and Aftermarket

GET /api/manufacturers

Lista fabricantes (OEM y aftermarket).

Auth: No requerida

Query params:

Param Tipo Descripcion
type string oem, aftermarket, remanufactured
quality_tier string economy, standard, premium, oem

Response 200:

[
  {
    "id": 1,
    "name": "DENSO",
    "type": "aftermarket",
    "quality_tier": "premium",
    "country": "Japan",
    "logo_url": null,
    "website": "https://denso.com"
  }
]

GET /api/parts/{part_id}/alternatives

Alternativas aftermarket para una parte OEM.

Auth: No requerida

Query params:

Param Tipo Descripcion
quality_tier string Filtrar por calidad
manufacturer_id int Filtrar por fabricante

Response 200:

[
  {
    "id": 100,
    "part_number": "XP-1234",
    "name": "Premium Oil Filter",
    "name_es": "Filtro de Aceite Premium",
    "manufacturer_name": "DENSO",
    "manufacturer_id": 1,
    "quality_tier": "premium",
    "price_usd": 12.50,
    "warranty_months": 24,
    "in_stock": null
  }
]

GET /api/parts/{part_id}/cross-references

Cross-references (numeros alternos) para una parte.

Auth: No requerida

Response 200:

[
  {
    "id": 50,
    "cross_reference_number": "90915-YZZF1",
    "reference_type": "oem_alternate",
    "source": "TecDoc",
    "notes": null
  }
]

GET /api/parts/{part_id}/availability

Disponibilidad en bodegas activas que tienen la parte en stock.

Auth: TALLER, ADMIN, OWNER

Response 200:

[
  {
    "bodega": "Refacciones del Norte",
    "price": 125.50,
    "stock": 15,
    "location": "Principal",
    "updated_at": "2026-03-18T10:00:00"
  }
]

GET /api/parts/{part_id}/aftermarket

Alternativas aftermarket y cross-references combinadas (endpoint publico).

Auth: No requerida

Response 200:

{
  "alternatives": [
    {
      "id": 100,
      "part_number": "XP-1234",
      "name": "Premium Oil Filter",
      "manufacturer": "DENSO",
      "quality_tier": "premium",
      "price": 12.50,
      "source": "aftermarket"
    }
  ],
  "cross_references": [
    {
      "number": "90915-YZZF1",
      "source": "TecDoc",
      "notes": null
    }
  ]
}

GET /api/aftermarket

Lista partes aftermarket con paginacion y filtros.

Auth: No requerida

Query params:

Param Tipo Descripcion
manufacturer_id int Filtrar por fabricante
quality_tier string Filtrar por calidad
search string Buscar por nombre, part number o OEM number
page int Pagina (default 1)
per_page int Items por pagina (max 100)

Response 200:

{
  "data": [
    {
      "id": 100,
      "part_number": "XP-1234",
      "name": "Premium Oil Filter",
      "oem_part_number": "04152-YZZA1",
      "manufacturer_name": "DENSO",
      "quality_tier": "premium",
      "price_usd": 12.50
    }
  ],
  "pagination": { "page": 1, "per_page": 50, "total": 300000, "total_pages": 6000 }
}

GET /api/search/part-number/{part_number}

Busqueda por numero de parte en OEM, aftermarket y cross-references.

Auth: No requerida

Response 200:

[
  {
    "id": 500,
    "oem_part_number": "04152-YZZA1",
    "name": "Oil Filter",
    "name_es": "Filtro de Aceite",
    "match_type": "oem",
    "matched_number": "04152-YZZA1"
  },
  {
    "id": 500,
    "oem_part_number": "04152-YZZA1",
    "name": "Oil Filter",
    "name_es": "Filtro de Aceite",
    "match_type": "cross_reference",
    "matched_number": "90915-YZZF1"
  }
]

GET /api/search

Busqueda combinada inteligente. Detecta automaticamente vehiculo + parte en el query.

Auth: No requerida

Query params:

Param Tipo Default Descripcion
q string (requerido) Texto de busqueda
type string all all, parts, vehicles
category_id int - Filtrar partes por categoria
limit int 50 Limite de resultados
offset int 0 Offset para paginacion

Ejemplo: GET /api/search?q=Toyota Corolla 2020 oil filter

Response 200:

{
  "parts": [
    {
      "id": 500,
      "oem_part_number": "04152-YZZA1",
      "name": "Oil Filter",
      "name_es": null,
      "image_url": null,
      "group_name": "Oil Filters",
      "category_name": "Engine",
      "match_type": "oem"
    }
  ],
  "vehicles": [
    {
      "id": 12345,
      "brand": "TOYOTA",
      "model": "COROLLA",
      "year": 2020,
      "engine": "1.8L I4 Gas"
    }
  ],
  "vehicle_parts": [
    {
      "id": 500,
      "oem_part_number": "04152-YZZA1",
      "name": "Oil Filter",
      "group_name": "Oil Filters",
      "category_name": "Engine",
      "quantity": 1,
      "position": null,
      "match_type": "vehicle_part"
    }
  ],
  "matched_vehicle": {
    "id": 12345,
    "brand": "TOYOTA",
    "model": "COROLLA",
    "year": 2020,
    "engine": "1.8L I4 Gas"
  },
  "total_count": 5
}

GET /api/search/parts

Busqueda full-text en partes usando PostgreSQL tsvector.

Auth: No requerida

Query params:

Param Tipo Descripcion
q string (requerido) Texto de busqueda
category_id int Filtrar por categoria
group_id int Filtrar por grupo
page int Pagina (default 1)
per_page int Items por pagina (max 100)

Response 200:

{
  "data": [
    {
      "id": 500,
      "oem_part_number": "04152-YZZA1",
      "name": "Oil Filter",
      "name_es": "Filtro de Aceite",
      "description": "Engine oil filter",
      "group_name": "Oil Filters",
      "category_name": "Engine",
      "rank": 0.85
    }
  ],
  "pagination": { "page": 1, "per_page": 50, "total": 25, "total_pages": 1 }
}

7. VIN Decoder

GET /api/vin/decode/{vin}

Decodifica un VIN de 17 caracteres via la API de NHTSA. Cacheado por 30 dias.

Auth: No requerida

Response 200:

{
  "vin": "1HGBH41JXMN109186",
  "make": "HONDA",
  "model": "CIVIC",
  "year": 2021,
  "engine_info": {
    "configuration": "In-Line",
    "cylinders": 4,
    "displacement_l": 2.0,
    "fuel_type": "Gasoline"
  },
  "body_class": "Sedan/Saloon",
  "drive_type": "FWD",
  "matched_vehicle": {
    "mye_id": 5678,
    "brand": "HONDA",
    "model": "CIVIC",
    "year": 2021,
    "engine": "2.0L I4 Gas"
  },
  "cached": false
}

GET /api/vin/{vin}/parts

Retorna partes organizadas por categoria para un VIN previamente decodificado.

Auth: No requerida

Query params:

Param Tipo Descripcion
category_id int Filtrar por categoria

Response 200:

{
  "vin": "1HGBH41JXMN109186",
  "vehicle_info": {
    "vin": "1HGBH41JXMN109186",
    "make": "HONDA",
    "model": "CIVIC",
    "year": 2021,
    "mye_id": 5678
  },
  "categories": [
    {
      "id": 1,
      "name": "Engine",
      "name_es": "Motor",
      "parts": [
        {
          "id": 500,
          "oem_part_number": "15400-RTA-004",
          "name": "Oil Filter",
          "name_es": "Filtro de Aceite",
          "group_name": "Oil Filters",
          "quantity_required": 1,
          "position": null
        }
      ]
    }
  ]
}

GET /api/vin/{vin}/match

Vincula manualmente un VIN a un vehiculo (model_year_engine).

Auth: No requerida

Query params:

Param Tipo Descripcion
mye_id int (requerido) ID del model_year_engine

Response 200:

{
  "success": true,
  "vin": "1HGBH41JXMN109186",
  "mye_id": 5678
}

8. Diagrams

GET /api/diagrams

Lista diagramas, opcionalmente filtrados por grupo.

Auth: No requerida

Query params:

Param Tipo Descripcion
group_id int Filtrar por grupo de partes

Response 200:

[
  {
    "id": 1,
    "name": "Front Suspension Assembly",
    "name_es": "Ensamble de Suspension Delantera",
    "group_id": 20,
    "group_name": "Suspension",
    "thumbnail_path": "/static/diagrams/thumb_001.jpg",
    "display_order": 1
  }
]

GET /api/diagrams/{diagram_id}

Detalle de un diagrama con hotspots.

Auth: No requerida

Response 200:

{
  "id": 1,
  "name": "Front Suspension Assembly",
  "name_es": "Ensamble de Suspension Delantera",
  "group_id": 20,
  "group_name": "Suspension",
  "image_path": "static/diagrams/moog/front_suspension.png",
  "image_url": "/static/diagrams/moog/front_suspension.png",
  "svg_content": null,
  "width": null,
  "height": null,
  "hotspots": [
    {
      "id": 10,
      "part_id": 500,
      "callout_number": 1,
      "label": null,
      "shape": "circle",
      "coords": "150,200,25",
      "color": null,
      "part_name": "Ball Joint",
      "part_number": "K500123"
    }
  ]
}

GET /api/vehicles/{mye_id}/diagrams

Diagramas disponibles para un vehiculo especifico.

Auth: No requerida


GET /api/vehicles/{mye_id}/diagrams/by-category

Diagramas agrupados por categoria para un vehiculo.

Auth: No requerida

Query params:

Param Tipo Descripcion
category_id int Filtrar por categoria

GET /api/diagrams/{diagram_id}/hotspots

Lista hotspots de un diagrama.

Auth: No requerida


GET /api/diagrams/{diagram_id}/parts

Partes asociadas a un diagrama (con cross-references).

Auth: No requerida

Query params:

Param Tipo Descripcion
mye_id int Filtrar por vehiculo especifico

GET /api/diagrams/search

Busqueda de diagramas por nombre o vehiculo.

Auth: No requerida

Query params:

Param Tipo Descripcion
q string Texto de busqueda en nombre
brand string Filtrar por marca
model string Filtrar por modelo

9. Inventory (BODEGA)

GET /api/inventory/mapping

Retorna el mapeo de columnas configurado para el usuario actual.

Auth: BODEGA, ADMIN

Response 200:

{
  "mapping": {
    "part_number": "NUMERO_PARTE",
    "price": "PRECIO",
    "stock": "EXISTENCIA",
    "location": "ALMACEN"
  }
}

PUT /api/inventory/mapping

Guarda o actualiza el mapeo de columnas CSV/Excel.

Auth: BODEGA, ADMIN

Request body:

{
  "mapping": {
    "part_number": "NUMERO_PARTE",
    "price": "PRECIO",
    "stock": "EXISTENCIA",
    "location": "ALMACEN"
  }
}

Los campos part_number, price y stock son requeridos en el mapeo. location es opcional (default: "Principal").

Response 200:

{
  "message": "Mapping saved",
  "mapping": { "part_number": "NUMERO_PARTE", "price": "PRECIO", "stock": "EXISTENCIA" }
}

POST /api/inventory/upload

Sube un archivo CSV o Excel (.xlsx) de inventario. Aplica el mapeo de columnas y hace UPSERT en warehouse_inventory.

Auth: BODEGA, ADMIN

Request: multipart/form-data con campo file

Proceso:

  1. Lee el mapeo de columnas del usuario
  2. Parsea el archivo (CSV o Excel)
  3. Para cada fila, busca la parte por OEM part number (o aftermarket part number)
  4. UPSERT en warehouse_inventory (user_id, part_id, warehouse_location)

Response 200:

{
  "message": "Upload processed",
  "upload_id": 5,
  "imported": 450,
  "errors": 12,
  "error_samples": [
    { "row": 15, "error": "Part not found: XYZ-999" }
  ]
}

GET /api/inventory/uploads

Historial de uploads del usuario (ultimos 50).

Auth: BODEGA, ADMIN

Response 200:

[
  {
    "id": 5,
    "filename": "inventario_marzo.xlsx",
    "status": "completed",
    "rows_total": 462,
    "rows_imported": 450,
    "rows_errors": 12,
    "created_at": "2026-03-18T10:00:00",
    "completed_at": "2026-03-18T10:00:15"
  }
]

GET /api/inventory/items

Lista paginada del inventario del usuario actual.

Auth: BODEGA, ADMIN

Query params:

Param Tipo Default Descripcion
page int 1 Pagina
per_page int 50 Items por pagina (max 200)
q string - Buscar por OEM number o nombre

Response 200:

{
  "data": [
    {
      "id": 100,
      "part_id": 500,
      "oem_part_number": "04152-YZZA1",
      "name": "Oil Filter",
      "price": 125.50,
      "stock": 15,
      "location": "Principal",
      "updated_at": "2026-03-18T10:00:00"
    }
  ],
  "pagination": { "page": 1, "per_page": 50, "total": 450, "total_pages": 9 }
}

DELETE /api/inventory/items

Elimina todo el inventario del usuario actual.

Auth: BODEGA, ADMIN

Response 200:

{
  "message": "Inventory cleared",
  "deleted": 450
}

10. Admin CRUD

Todos los endpoints CRUD de admin no requieren autenticacion actualmente (a implementar).

Categories

Metodo Endpoint Descripcion
POST /api/admin/categories Crear categoria
PUT /api/admin/categories/{id} Actualizar categoria
DELETE /api/admin/categories/{id} Eliminar categoria

Groups

Metodo Endpoint Descripcion
GET /api/admin/groups?category_id=X Listar grupos
POST /api/admin/groups Crear grupo
PUT /api/admin/groups/{id} Actualizar grupo
DELETE /api/admin/groups/{id} Eliminar grupo

Parts

Metodo Endpoint Descripcion
POST /api/admin/parts Crear parte
PUT /api/admin/parts/{id} Actualizar parte
DELETE /api/admin/parts/{id} Eliminar parte

Manufacturers

Metodo Endpoint Descripcion
POST /api/admin/manufacturers Crear fabricante
PUT /api/admin/manufacturers/{id} Actualizar fabricante
DELETE /api/admin/manufacturers/{id} Eliminar fabricante

Aftermarket Parts

Metodo Endpoint Descripcion
POST /api/admin/aftermarket Crear parte aftermarket
PUT /api/admin/aftermarket/{id} Actualizar parte aftermarket
DELETE /api/admin/aftermarket/{id} Eliminar parte aftermarket

Cross-References

Metodo Endpoint Descripcion
GET /api/admin/crossref?page=1&per_page=50 Listar cross-refs (paginado)
POST /api/admin/crossref Crear cross-reference
PUT /api/admin/crossref/{id} Actualizar cross-reference
DELETE /api/admin/crossref/{id} Eliminar cross-reference
Metodo Endpoint Descripcion
GET /api/admin/fitment?brand=X&model=Y&mye_id=Z Listar fitment (paginado)
POST /api/admin/fitment Crear fitment
DELETE /api/admin/fitment/{id} Eliminar fitment

CSV Import

POST /api/admin/import/{type}

Tipos validos: categories, groups, parts, manufacturers, aftermarket, crossref, fitment

Request body:

{
  "records": [
    { "name": "Engine", "name_es": "Motor", "slug": "engine" }
  ]
}

Response 200:

{
  "imported": 10,
  "errors": ["Row 3: duplicate key..."]
}

CSV Export

GET /api/admin/export/{type}?page=1&per_page=1000

Tipos validos: categories, groups, parts, manufacturers, aftermarket, crossref, fitment

Response 200:

{
  "data": [ { "id": 1, "name": "Engine", "name_es": "Motor" } ],
  "pagination": { "page": 1, "per_page": 1000, "total": 10, "total_pages": 1 }
}

11. Image Upload

POST /api/admin/upload-image

Sube una imagen en base64 para partes.

Auth: No requerida (a proteger)

Request body:

{
  "image": "data:image/png;base64,iVBORw0KGgo..."
}

Response 200:

{
  "url": "/static/parts_images/abc123.png",
  "filename": "abc123.png"
}

Formato de Paginacion

Todos los endpoints paginados retornan:

{
  "data": [],
  "pagination": {
    "page": 1,
    "per_page": 50,
    "total": 1000,
    "total_pages": 20
  }
}

Codigos de Error

Codigo Descripcion
400 Bad request (datos faltantes o invalidos)
401 No autenticado (token faltante, invalido o expirado)
403 Sin permisos (rol insuficiente o cuenta inactiva)
404 Recurso no encontrado
409 Conflicto (e.g., email duplicado)
500 Error interno del servidor
502 Error en API externa (NHTSA)
503 API externa no disponible