Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/juadariasmar/inventory_project/llms.txt

Use this file to discover all available pages before exploring further.

The Products API manages the core of your inventory catalog. Every product belongs to a company tenant (empresaId is resolved automatically from the authenticated session) and must be assigned to a category. When a product is created or its quantity is increased via an edit, an entrada movement is automatically recorded to maintain a complete audit trail. Decreasing stock must always be done through a movement — the PUT endpoint rejects any edit that would lower the current quantity.

Endpoints

MethodPathDescriptionAuth required
GET/api/productosList all products (cursor pagination)Active session
POST/api/productosCreate a new productADMIN
GET/api/productos/[id]Get a single product by IDActive session
PUT/api/productos/[id]Update a productADMIN
DELETE/api/productos/[id]Delete a productADMIN
POST/api/productos/bulk-deleteDelete multiple products at onceADMIN
POST/api/productos/importarImport products from CSV or ExcelADMIN
GET/api/productos/plantillaDownload the CSV import templateADMIN
GET/api/productos/sugerir-codigoSuggest the next auto-generated code for a categoryADMIN
GET/api/productos/[id]/historial-preciosGet price change history for a productActive session

GET /api/productos

Returns a paginated list of all products belonging to the authenticated user’s company. Pagination uses a cursor (the last product id seen) rather than offset pages, which stays fast as the catalog grows.
cursor
number
The id of the last product received. Omit to fetch from the beginning.
limite
number
default:"50"
Number of products to return per page. Maximum 100.
Response
items
Producto[]
Array of product objects for this page.
nextCursor
number | null
Pass this value as cursor in the next request. null when there are no more pages.
total
number
Number of items returned in this page (not the total catalog count).
Each item in items contains:
id
number
Unique product identifier.
nombre
string
Product name.
descripcion
string | null
Optional description.
codigo
string
Unique product code within the company (e.g. BEB-001).
precio
number
Unit sale price.
cantidad
number
Current stock on hand.
stockMinimo
number
Low-stock alert threshold.
categoriaId
number
ID of the assigned category.
categoria
object
Embedded category object with id, nombre, and prefijo.
creadoEn
string
ISO 8601 creation timestamp.
curl -X GET "https://your-domain.com/api/productos?limite=20" \
  -H "Cookie: <session-cookie>"
Error cases
StatusCause
401No active session.
403User has no company assigned.
500Unexpected server error.

POST /api/productos

Creates a new product. If cantidad is greater than zero, an initial entrada movement labelled "Stock inicial" is created atomically in the same transaction. If codigo is omitted, the next sequential code for the chosen category is generated automatically (e.g. BEB-004).
nombre
string
required
Product name. Minimum 2 characters.
categoriaId
number
required
ID of the category this product belongs to. Must exist within the company.
precio
number
required
Unit sale price. Must be a non-negative finite number.
codigo
string
Product code. When omitted, the API auto-generates one using the category prefix (e.g. BEB-001). Must be unique within the company.
descripcion
string
Optional free-text description.
cantidad
number
default:"0"
Initial stock quantity. A non-zero value triggers an automatic entrada movement.
stockMinimo
number
default:"1"
Minimum stock level before a low-stock alert is triggered.
curl -X POST "https://your-domain.com/api/productos" \
  -H "Content-Type: application/json" \
  -H "Cookie: <session-cookie>" \
  -d '{
    "nombre": "Agua Mineral 600ml",
    "categoriaId": 3,
    "precio": 2500,
    "codigo": "BEB-001",
    "descripcion": "Sin gas, botella PET",
    "cantidad": 200,
    "stockMinimo": 40
  }'
Returns the created product object with HTTP 201 Created. Error cases
StatusCause
400Missing required fields or invalid values (e.g. negative price).
403Not an ADMIN, or user has no company assigned.
409A product with the same codigo already exists in the company.
500Unexpected server error.

GET /api/productos/[id]

Returns a single product by its numeric ID. The lookup is scoped to the authenticated user’s company — products from other tenants are invisible.
id
number
required
The product’s numeric ID.
curl -X GET "https://your-domain.com/api/productos/42" \
  -H "Cookie: <session-cookie>"
Returns a product object including the embedded categoria sub-object (id, nombre, prefijo). Error cases
StatusCause
401No active session.
403User has no company assigned.
404Product not found or belongs to a different company.
500Unexpected server error.

PUT /api/productos/[id]

Updates an existing product. All editable fields are replaced with the values provided — partial updates are not supported; send every field. The following stock rules apply:
  • If cantidad is greater than the current value, an entrada movement with the note "Ajuste por edición" is created automatically.
  • If cantidad is less than the current value, the request is rejected with 400. Use POST /api/movimientos to reduce stock.
  • If precio changes, an entry is added to HistorialPrecio automatically.
id
number
required
The product’s numeric ID.
nombre
string
required
Product name. Minimum 2 characters.
categoriaId
number
required
Category ID. Must exist within the company.
precio
number
required
Unit sale price. Must be non-negative.
codigo
string
required
Product code. Must be unique within the company.
cantidad
number
required
New stock quantity. Cannot be lower than the current value.
stockMinimo
number
required
Minimum stock threshold.
descripcion
string
Optional description.
curl -X PUT "https://your-domain.com/api/productos/42" \
  -H "Content-Type: application/json" \
  -H "Cookie: <session-cookie>" \
  -d '{
    "nombre": "Agua Mineral 600ml",
    "categoriaId": 3,
    "precio": 2800,
    "codigo": "BEB-001",
    "cantidad": 250,
    "stockMinimo": 40,
    "descripcion": "Sin gas, botella PET — precio actualizado"
  }'
Returns the updated product object. Error cases
StatusCause
400Validation failure, or cantidad is lower than the current value.
403Not an ADMIN, or user has no company assigned.
404Product not found.
409Another product already uses the given codigo.
500Unexpected server error.

DELETE /api/productos/[id]

Permanently deletes a product and all of its associated movements in a single transaction. If the product currently has stock (cantidad > 0), a salida movement is recorded before the deletion to keep the audit log coherent. Products that have line items in existing sales or quotes cannot be deleted — use POST /api/productos/bulk-delete for an informative error on blocked IDs.
id
number
required
The product’s numeric ID.
curl -X DELETE "https://your-domain.com/api/productos/42" \
  -H "Cookie: <session-cookie>"
Response
{ "mensaje": "Producto eliminado correctamente" }
Error cases
StatusCause
403Not an ADMIN.
404Product not found.
500Unexpected server error (e.g. FK constraint from sales/quotes).

POST /api/productos/bulk-delete

Deletes multiple products in a single database transaction. If any of the provided products have associated sale items (ItemVenta) or quote items (ItemCotizacion), the entire operation is rejected — nothing is deleted until the blocking references are removed. For each product with remaining stock, a salida movement is created before deletion.
ids
number[]
required
Array of product IDs to delete. Must contain at least one valid positive integer.
curl -X POST "https://your-domain.com/api/productos/bulk-delete" \
  -H "Content-Type: application/json" \
  -H "Cookie: <session-cookie>" \
  -d '{ "ids": [10, 11, 14] }'
Response
eliminados
number
Number of products successfully deleted.
ids
number[]
The IDs that were actually deleted.
Error cases
StatusCause
400Empty or invalid ids array.
403Not an ADMIN.
404None of the given IDs exist in the company.
409One or more products have linked sales or quotes. The response body names the blocking products.
500Unexpected server error.

POST /api/productos/importar

Imports products in bulk from a CSV or Excel (.xlsx / .xlsm) file. Accepts multipart/form-data with the file in the archivo field. The file size limit is 10 MB and the row limit is 5,000 rows per request. Column headers are matched flexibly — common synonyms are accepted (e.g. productonombre, valorprecio, stockcantidad). If a row does not include a codigo, one is generated automatically from the category prefix. If a row’s categoria does not exist, it is created on the fly with an auto-generated prefix.
archivo
file
required
CSV (.csv) or Excel (.xlsx, .xlsm) file. Sent as multipart/form-data. The first recognized header row may be preceded by title rows or blank lines.
Expected columns (header names are matched case-insensitively):
ColumnRequiredNotes
nombreAlso matched as producto, articulo
precioAlso matched as valor, pvp. Currency symbols and thousand separators are stripped.
codigoAuto-generated if absent
descripcion
cantidadDefaults to 0
stockMinimoDefaults to 1
categoriaCreates a new category if not found
curl -X POST "https://your-domain.com/api/productos/importar" \
  -H "Cookie: <session-cookie>" \
  -F "archivo=@/path/to/products.csv"
Response
formato
string
Detected file format: "csv" or "xlsx".
total
number
Total rows processed.
creados
number
Number of products successfully created.
errores
number
Number of rows that failed.
resultados
object[]
Per-row result array. Each entry contains linea (1-based row number), codigo, nombre, estado ("creado" | "error"), and an optional mensaje explaining the outcome.
Error cases
StatusCause
400No file provided, empty file, unrecognised required columns, or row count exceeds 5,000.
403Not an ADMIN.
413File exceeds 10 MB.
500Unexpected server error.

GET /api/productos/plantilla

Downloads a pre-filled CSV import template with the correct column headers and three example rows. Use this as the starting point for bulk imports.
curl -X GET "https://your-domain.com/api/productos/plantilla" \
  -H "Cookie: <session-cookie>" \
  -o plantilla_productos.csv
Returns a text/csv file named plantilla_productos.csv with columns: codigo, nombre, descripcion, precio, cantidad, stockMinimo, categoria. Error cases
StatusCause
403Not an ADMIN.

GET /api/productos/sugerir-codigo

Returns the next available auto-generated product code for a given category, based on the category’s prefix and the highest existing consecutive number. Useful for pre-filling the code field in the product creation form before the user saves.
categoria
number
required
The numeric ID of the category for which to suggest a code.
curl -X GET "https://your-domain.com/api/productos/sugerir-codigo?categoria=3" \
  -H "Cookie: <session-cookie>"
Response
codigo
string
The suggested next product code, e.g. "BEB-005".
Error cases
StatusCause
400Missing or invalid categoria query parameter.
403Not an ADMIN.
500Code could not be generated.

GET /api/productos/[id]/historial-precios

Returns the price change history for a product, ordered from most recent to oldest. Entries are recorded automatically every time a PUT /api/productos/[id] request changes the precio field.
id
number
required
The product’s numeric ID.
curl -X GET "https://your-domain.com/api/productos/42/historial-precios" \
  -H "Cookie: <session-cookie>"
Returns an array of up to 50 price-change records. Each record contains:
id
number
Record identifier.
productoId
number
The associated product ID.
precioAnterior
number
Price before the change.
precioNuevo
number
Price after the change.
creadoEn
string
ISO 8601 timestamp of the change.
cambiadoPor
object | null
Embedded user object with nombre and email, or null if the changing user no longer exists.
Error cases
StatusCause
401No active session or user is not in ACTIVO state.
403User has no company assigned.
404Product not found or belongs to a different company.
500Unexpected server error.

Build docs developers (and LLMs) love