Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/RoyGeova07/Credith/llms.txt

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

The Products API is the foundation of Credith’s point-of-sale catalog. Every item that can be sold at a store must exist as a product record. Products carry pricing data — both cost (buyPrice) and sale price (sellPrice) — along with an optional minimum gain percentage that can be used to enforce margin rules at checkout. When a product is created, it is immediately registered in a store’s inventory with a configurable initial stock count. Archiving a product via DELETE performs a soft-delete: the record is never physically removed from the database, and it can be fully restored at any time using the recover endpoint.

List Products

limit
integer
default:"10"
Maximum number of products to return per page.
offset
integer
default:"0"
Number of records to skip before starting to return results. Used for pagination.
storeId
string (UUID)
OWNER only. Filter products that belong to a specific store. ADMIN and EMPLOYEE users are automatically scoped to their assigned store and cannot override this.
category
string
Filter products by category name (case-sensitive match against the category’s name field).
archived
boolean
default:"false"
When true, returns archived (soft-deleted) products instead of active ones. Only OWNER users can view the global archived list without a storeId. For store-scoped views, archived reflects inventory isActive=false.
GET /api/products
Returns a paginated list of products, each with their linked categories and per-store inventory data. The shape of the response varies by role:
  • OWNER — sees all products across all stores unless storeId is provided.
  • ADMIN / EMPLOYEE — automatically scoped to their assigned store only.
Response
{
  "total": 42,
  "data": [
    {
      "productId": "b75438e5-9ae8-4597-b95e-9889028f4737",
      "name": "Coca Cola 3L",
      "description": "Refresco Coca Cola 3 litros",
      "sellPrice": "45.00000000",
      "buyPrice": "35.00000000",
      "minGainPercentage": 20,
      "imageUrl": "https://res.cloudinary.com/demo/image/upload/cocacola.jpg",
      "isActive": true,
      "categories": [
        { "categoryId": "7d4d0f83-f2d7-4d58-a48b-cf2d2f75d4d1", "name": "bebidas", "description": "Bebidas frías y calientes" }
      ],
      "inventories": [
        { "storeId": "c3d4e5f6-a7b8-490a-bcde-f01234567891", "inStock": 120, "store": { "storeId": "c3d4e5f6-a7b8-490a-bcde-f01234567891", "address": 1 } }
      ]
    }
  ]
}

Get Product by ID

GET /api/products/:id
Returns a single product identified by its UUID, including all associated categories. Returns 404 if the product does not exist or has been globally archived. Path parameter
id
string (UUID)
required
The UUID of the product to retrieve.
Response
{
  "productId": "b75438e5-9ae8-4597-b95e-9889028f4737",
  "name": "Coca Cola 3L",
  "description": "Refresco Coca Cola 3 litros",
  "buyPrice": "35.00000000",
  "sellPrice": "45.00000000",
  "minGainPercentage": 20,
  "imageUrl": "https://res.cloudinary.com/demo/image/upload/cocacola.jpg",
  "isActive": true,
  "categories": [
    {
      "categoryId": "7d4d0f83-f2d7-4d58-a48b-cf2d2f75d4d1",
      "name": "bebidas",
      "description": "Bebidas frías y calientes"
    }
  ]
}

Create Product

POST /api/products
Creates a new product and simultaneously registers it in a store’s inventory with the specified initial stock. Requires OWNER role. Both categoryId and storeId must reference existing records — the server validates both before creating anything.
name
string
required
Display name of the product. Must be unique across all products (enforced by a unique index on the name column).
sellPrice
number
required
The retail sale price of the product. Must be a non-negative number. Stored as DECIMAL(16,8).
categoryId
string (UUID)
required
UUID of the category to assign this product to. The category must already exist.
storeId
string (UUID)
required
UUID of the store where the product’s initial inventory entry will be created.
description
string
required
A short description of the product. Required by the database (allowNull: false on the description column). Cannot be omitted.
buyPrice
number
default:"0"
The cost price (purchase price) of the product. Defaults to 0 if omitted or negative.
minGainPercentage
integer
Minimum acceptable profit margin percentage. Used as a soft business rule reference at checkout. Stored as SMALLINT.
imageUrl
string
URL pointing to the product’s image. Typically a Cloudinary-hosted URL obtained from the frontend upload widget.
initialStock
integer
default:"1"
The opening stock count for the product in the specified store. Defaults to 1 if omitted or less than zero.
imageUrl can be populated automatically by using the Cloudinary upload preset configured in the Credith frontend. The upload widget returns a secure URL that you can pass directly to this field.
curl -X POST https://your-domain.com/api/products \
  -H "Content-Type: application/json" \
  -H "Cookie: token=<your-session-token>" \
  -d '{
    "name": "Coca Cola 3L",
    "description": "Refresco Coca Cola 3 litros",
    "buyPrice": 35,
    "sellPrice": 45,
    "minGainPercentage": 20,
    "imageUrl": "https://res.cloudinary.com/demo/image/upload/cocacola.jpg",
    "categoryId": "7d4d0f83-f2d7-4d58-a48b-cf2d2f75d4d1",
    "storeId": "c3d4e5f6-a7b8-490a-bcde-f01234567891",
    "initialStock": 100
  }'

Update Product

PUT /api/products/:id
Updates the fields of an existing product. The productId in the request body must match the :id path parameter — the server returns 400 if they differ. Requires OWNER or ADMIN role. You can optionally update the product’s store-level stock in the same request by supplying storeId and stock together.
id
string (UUID)
required
The UUID of the product to update. Must match productId in the body.
productId
string (UUID)
required
Must be identical to the :id path parameter.
name
string
required
Updated display name for the product. Cannot be empty.
sellPrice
number
required
Updated retail price. Must be >= 0.
description
string
Updated product description.
buyPrice
number
Updated cost price. Defaults to 0 if omitted.
minGainPercentage
integer
Updated minimum gain percentage.
imageUrl
string
Updated image URL.
categoryId
string (UUID)
If provided, replaces the product’s entire category assignment with this single category (uses setCategories). The category must exist.
storeId
string (UUID)
If provided alongside stock, the inventory record for this product in the given store will be updated. Must be provided together with stock.
stock
integer
New stock count for the product at storeId. Must be >= 0. Requires storeId to also be present.
Response
{
  "message": "Producto editado exitosamente"
}

Archive Product (Soft-Delete)

DELETE /api/products/:id
Soft-deletes a product. Behavior depends on the caller’s role and whether a storeId query parameter is provided.
id
string (UUID)
required
UUID of the product to archive.
storeId
string (UUID)
  • Optional for OWNER — archives the product only from the specified store (sets isActive=false on the stores_inventories row). The product remains visible in other stores.
  • Required for ADMIN — ADMIN users must always provide storeId; they cannot perform a global archive.
  • If omitted and the caller is OWNER, the product is globally archived via a Sequelize paranoid soft-delete (sets deletedAt).
Archived products are never physically removed from the database. The soft-delete sets a deleted_at timestamp (global archive) or sets isActive=false on the inventory row (store-level archive). All historical invoice data referencing the product remains intact. Use POST /api/products/:id/recover to restore them.
Response
{
  "message": "Producto archivado globalmente"
}

Recover Product

POST /api/products/:id/recover
Restores a previously archived product. Like the delete endpoint, behavior varies based on whether storeId is supplied.
id
string (UUID)
required
UUID of the product to restore.
storeId
string (UUID)
If provided, restores the product only within that store’s inventory (sets isActive=true). If omitted, performs a global restore via Sequelize’s restore(), clearing the deleted_at timestamp.
Response
{
  "message": "Producto restaurado globalmente"
}

Product Object

productId
string (UUID)
Unique identifier for the product. Auto-generated as UUIDv4.
name
string
Display name of the product. Unique across all products.
sellPrice
string (decimal)
The retail price of the product, returned as a decimal string with 8 decimal places (e.g. "45.00000000"). Stored as DECIMAL(16,8).
buyPrice
string (decimal)
The purchase/cost price. Defaults to 0.00000000. Stored as DECIMAL(16,8).
description
string
Short description of the product.
minGainPercentage
integer
Minimum profit margin percentage. May be null if not set.
imageUrl
string
URL to the product’s image. May be null if not set.
isActive
boolean
Whether the product is currently active. Managed through archive/recover operations.
categories
array
inventories
array

Error Responses

StatusMeaning
400Missing required field, invalid price, mismatched productId, or invalid stock value
401Request is not authenticated (missing or invalid session token)
403Role is not permitted to perform the action (e.g., ADMIN attempting a global archive)
404Product, category, store, or inventory record not found
500Unexpected server error

Build docs developers (and LLMs) love