- 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>
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 |
| 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 invalido403- 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"
}
]
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:
{
"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:
- Lee el mapeo de columnas del usuario
- Parsea el archivo (CSV o Excel)
- Para cada fila, busca la parte por OEM part number (o aftermarket part number)
- 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 |
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:
{
"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 |