The Products API manages the core of your inventory catalog. Every product belongs to a company tenant (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.
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
| Method | Path | Description | Auth required |
|---|---|---|---|
| GET | /api/productos | List all products (cursor pagination) | Active session |
| POST | /api/productos | Create a new product | ADMIN |
| GET | /api/productos/[id] | Get a single product by ID | Active session |
| PUT | /api/productos/[id] | Update a product | ADMIN |
| DELETE | /api/productos/[id] | Delete a product | ADMIN |
| POST | /api/productos/bulk-delete | Delete multiple products at once | ADMIN |
| POST | /api/productos/importar | Import products from CSV or Excel | ADMIN |
| GET | /api/productos/plantilla | Download the CSV import template | ADMIN |
| GET | /api/productos/sugerir-codigo | Suggest the next auto-generated code for a category | ADMIN |
| GET | /api/productos/[id]/historial-precios | Get price change history for a product | Active session |
GET /api/productos
Returns a paginated list of all products belonging to the authenticated user’s company. Pagination uses a cursor (the last productid seen) rather than offset pages, which stays fast as the catalog grows.
The
id of the last product received. Omit to fetch from the beginning.Number of products to return per page. Maximum
100.Array of product objects for this page.
Pass this value as
cursor in the next request. null when there are no more pages.Number of items returned in this page (not the total catalog count).
items contains:
Unique product identifier.
Product name.
Optional description.
Unique product code within the company (e.g.
BEB-001).Unit sale price.
Current stock on hand.
Low-stock alert threshold.
ID of the assigned category.
Embedded category object with
id, nombre, and prefijo.ISO 8601 creation timestamp.
| Status | Cause |
|---|---|
401 | No active session. |
403 | User has no company assigned. |
500 | Unexpected server error. |
POST /api/productos
Creates a new product. Ifcantidad 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).
Product name. Minimum 2 characters.
ID of the category this product belongs to. Must exist within the company.
Unit sale price. Must be a non-negative finite number.
Product code. When omitted, the API auto-generates one using the category prefix (e.g.
BEB-001). Must be unique within the company.Optional free-text description.
Initial stock quantity. A non-zero value triggers an automatic
entrada movement.Minimum stock level before a low-stock alert is triggered.
201 Created.
Error cases
| Status | Cause |
|---|---|
400 | Missing required fields or invalid values (e.g. negative price). |
403 | Not an ADMIN, or user has no company assigned. |
409 | A product with the same codigo already exists in the company. |
500 | Unexpected 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.The product’s numeric ID.
categoria sub-object (id, nombre, prefijo).
Error cases
| Status | Cause |
|---|---|
401 | No active session. |
403 | User has no company assigned. |
404 | Product not found or belongs to a different company. |
500 | Unexpected 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
cantidadis greater than the current value, anentradamovement with the note"Ajuste por edición"is created automatically. - If
cantidadis less than the current value, the request is rejected with400. UsePOST /api/movimientosto reduce stock. - If
preciochanges, an entry is added toHistorialPrecioautomatically.
The product’s numeric ID.
Product name. Minimum 2 characters.
Category ID. Must exist within the company.
Unit sale price. Must be non-negative.
Product code. Must be unique within the company.
New stock quantity. Cannot be lower than the current value.
Minimum stock threshold.
Optional description.
| Status | Cause |
|---|---|
400 | Validation failure, or cantidad is lower than the current value. |
403 | Not an ADMIN, or user has no company assigned. |
404 | Product not found. |
409 | Another product already uses the given codigo. |
500 | Unexpected 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.
The product’s numeric ID.
| Status | Cause |
|---|---|
403 | Not an ADMIN. |
404 | Product not found. |
500 | Unexpected 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.
Array of product IDs to delete. Must contain at least one valid positive integer.
Number of products successfully deleted.
The IDs that were actually deleted.
| Status | Cause |
|---|---|
400 | Empty or invalid ids array. |
403 | Not an ADMIN. |
404 | None of the given IDs exist in the company. |
409 | One or more products have linked sales or quotes. The response body names the blocking products. |
500 | Unexpected 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. producto → nombre, valor → precio, stock → cantidad). 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.
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.| Column | Required | Notes |
|---|---|---|
nombre | ✅ | Also matched as producto, articulo |
precio | ✅ | Also matched as valor, pvp. Currency symbols and thousand separators are stripped. |
codigo | — | Auto-generated if absent |
descripcion | — | |
cantidad | — | Defaults to 0 |
stockMinimo | — | Defaults to 1 |
categoria | — | Creates a new category if not found |
Detected file format:
"csv" or "xlsx".Total rows processed.
Number of products successfully created.
Number of rows that failed.
Per-row result array. Each entry contains
linea (1-based row number), codigo, nombre, estado ("creado" | "error"), and an optional mensaje explaining the outcome.| Status | Cause |
|---|---|
400 | No file provided, empty file, unrecognised required columns, or row count exceeds 5,000. |
403 | Not an ADMIN. |
413 | File exceeds 10 MB. |
500 | Unexpected 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.text/csv file named plantilla_productos.csv with columns: codigo, nombre, descripcion, precio, cantidad, stockMinimo, categoria.
Error cases
| Status | Cause |
|---|---|
403 | Not 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.The numeric ID of the category for which to suggest a code.
The suggested next product code, e.g.
"BEB-005".| Status | Cause |
|---|---|
400 | Missing or invalid categoria query parameter. |
403 | Not an ADMIN. |
500 | Code 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 aPUT /api/productos/[id] request changes the precio field.
The product’s numeric ID.
Record identifier.
The associated product ID.
Price before the change.
Price after the change.
ISO 8601 timestamp of the change.
Embedded user object with
nombre and email, or null if the changing user no longer exists.| Status | Cause |
|---|---|
401 | No active session or user is not in ACTIVO state. |
403 | User has no company assigned. |
404 | Product not found or belongs to a different company. |
500 | Unexpected server error. |