# 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 `. 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:** ```json { "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:** ```json { "message": "Registration successful. Account pending activation." } ``` **Response 409:** ```json { "error": "Email already registered" } ``` --- ### POST /api/auth/login Autentica un usuario y retorna access + refresh tokens. **Auth:** No requerida **Request body:** ```json { "email": "juan@taller.com", "password": "secreto123" } ``` **Response 200:** ```json { "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:** ```json { "refresh_token": "abc123def456..." } ``` **Response 200:** ```json { "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:** ```json { "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:** ```json [ { "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:** ```json { "is_active": true } ``` **Response 200:** ```json { "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:** ```json { "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):** ```json ["ACURA", "AUDI", "BMW", "CHEVROLET", "FORD", "HONDA", "TOYOTA"] ``` **Response 200 (detailed=true):** ```json [ { "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):** ```json ["4RUNNER", "CAMRY", "COROLLA", "HIGHLANDER", "RAV4"] ``` **Response 200 (detailed=true&brand=TOYOTA):** ```json [ { "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:** ```json [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:** ```json ["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:** ```json { "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:** ```json { "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:** ```json { "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:** ```json [ { "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:** ```json [ { "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:** ```json { "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:** ```json { "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:** ```json [ { "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:** ```json [ { "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:** ```json { "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:** ```json [ { "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:** ```json [ { "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:** ```json [ { "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:** ```json [ { "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:** ```json { "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:** ```json { "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:** ```json [ { "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" } ] ``` --- ## 6. Search ### 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:** ```json { "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:** ```json { "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:** ```json { "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:** ```json { "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:** ```json { "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:** ```json [ { "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:** ```json { "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:** ```json { "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:** ```json { "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:** ```json { "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:** ```json { "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:** ```json [ { "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:** ```json { "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:** ```json { "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 | ### Fitment (Vehicle-Part Links) | 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:** ```json { "records": [ { "name": "Engine", "name_es": "Motor", "slug": "engine" } ] } ``` **Response 200:** ```json { "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:** ```json { "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:** ```json { "image": "data:image/png;base64,iVBORw0KGgo..." } ``` **Response 200:** ```json { "url": "/static/parts_images/abc123.png", "filename": "abc123.png" } ``` --- ## Formato de Paginacion Todos los endpoints paginados retornan: ```json { "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 |