Linkit

Products

Managing your product catalog — create, update, and sync products across branches

Products

Products are the foundation of your catalog. Each product has bilingual names, pricing, VAT configuration, and optional brand/category associations. When you create a product, Linkit generates a SKU for that product at every existing branch.


The Product Object

{
  "id": "r1234567890abcdef",
  "iv_id": "PROD-001",
  "organization_id": "org_abc123",
  "name_en": "Panadol Extra",
  "name_ar": "بنادول إكسترا",
  "average_price": 15.50,
  "vat_value": 15,
  "barcode": "6281001210016",
  "brand_id": "brand_gsk",
  "category_id": "cat_pharma",
  "generic_id": "gen_paracetamol",
  "is_enabled": true,
  "is_deleted": false,
  "created": "2024-01-15T10:30:00Z",
  "updated": "2024-01-16T14:22:00Z"
}

Fields

FieldTypeDescription
idstringInternal Linkit ID (auto-generated)
iv_idstringYour external identifier for this product
name_enstringProduct name in English
name_arstringProduct name in Arabic
average_pricenumberDefault price
vat_valuenumberVAT percentage (e.g., 15)
barcodestringProduct barcode / EAN
brand_idstringAssociated brand ID
category_idstringAssociated category ID
generic_idstringAssociated generic medicine ID
is_enabledbooleanWhether the product is active
is_deletedbooleanSoft-delete flag

List Products

GET /api/v1/products

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger20Items per page (max 100)
searchstring-Search in product names
brand_idstring-Filter by brand
category_idstring-Filter by category
is_enabledboolean-Filter by active status
sortstring-createdSort field (prefix - for descending)

Example Request

curl -X GET "https://linkit.works/api/v1/products?search=panadol&limit=25" \
  -H "Authorization: Bearer your_token_here"
const response = await fetch(
  'https://linkit.works/api/v1/products?search=panadol&limit=25',
  {
    headers: {
      'Authorization': 'Bearer your_token_here'
    }
  }
);
const products = await response.json();
import requests

response = requests.get(
    'https://linkit.works/api/v1/products',
    params={'search': 'panadol', 'limit': 25},
    headers={'Authorization': 'Bearer your_token_here'}
)
products = response.json()

Response

{
  "data": [
    {
      "id": "r1234567890abcdef",
      "iv_id": "PROD-001",
      "name_en": "Panadol Extra",
      "name_ar": "بنادول إكسترا",
      "average_price": 15.50,
      "is_enabled": true,
      "created": "2024-01-15T10:30:00Z"
    }
  ],
  "count": 25,
  "total_count": 1234,
  "page": 1,
  "limit": 25,
  "has_next": true,
  "meta": {}
}

Get Single Product

GET /api/v1/products/code/{ivId}

Path Parameters

ParameterTypeDescription
ivIdstringProduct's external ID (iv_id)

Example

curl -X GET "https://linkit.works/api/v1/products/code/PROD-001" \
  -H "Authorization: Bearer your_token_here"

Returns the full product object.


Create Product

POST /api/v1/products

Request Body

{
  "iv_id": "PROD-NEW",
  "name_en": "New Product",
  "name_ar": "منتج جديد",
  "average_price": 29.99,
  "vat_value": 15,
  "barcode": "1234567890123",
  "brand_id": "brand_123",
  "category_id": "cat_456",
  "is_enabled": true
}

Required Fields

FieldTypeConstraints
iv_idstringMax 50 chars, unique per organization

Optional Fields

FieldTypeConstraints
name_enstringMax 255 chars
name_arstringMax 255 chars
average_pricenumber>= 0
vat_valuenumber0–100
barcodestringMax 50 chars
brand_idstringMust reference existing brand
category_idstringMust reference existing category
is_enabledbooleanDefault: true

When a product is created, Linkit automatically generates one SKU for each existing branch. The SKU's iv_id follows the pattern {product_iv_id}_{branch_iv_id}.

Response (201 Created)

{
  "success": true,
  "message": "Product created successfully",
  "data": {
    "id": "r1234567890abcdef",
    "iv_id": "PROD-NEW"
  },
  "timestamp": "2024-01-15T10:30:00Z"
}

Update Product

PUT /api/v1/products/code/{ivId}

Full replacement — include all fields you want to keep.

Example

curl -X PUT "https://linkit.works/api/v1/products/code/PROD-001" \
  -H "Authorization: Bearer your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "iv_id": "PROD-001",
    "name_en": "Panadol Extra (Updated)",
    "name_ar": "بنادول إكسترا",
    "average_price": 16.50,
    "vat_value": 15,
    "is_enabled": true
  }'

Delete Product

DELETE /api/v1/products/code/{ivId}

Query Parameters

ParameterTypeDefaultDescription
forcebooleanfalseDelete even if the product has associated SKUs

Deletion behavior

By default, products with existing SKUs cannot be deleted. Use force=true to override — this removes the product and its associated SKUs.

Response (204 No Content)

Success returns no body.


Bulk Operations

Process up to 1,000 products in a single request.

POST /api/v1/products/bulk

Request Body

{
  "mode": "upsert",
  "products": [
    {
      "iv_id": "PROD-001",
      "name_en": "Product One",
      "average_price": 49.99,
      "is_enabled": true
    },
    {
      "iv_id": "PROD-002",
      "name_en": "Product Two",
      "average_price": 79.99,
      "is_enabled": true
    }
  ]
}

Modes

ModeBehavior
createInsert only — fails if product exists
updateUpdate only — fails if product not found
upsertCreate or update as appropriate

Response

{
  "success": true,
  "message": "Processed 100 products successfully",
  "data": {
    "succeeded": 98,
    "failed": 2,
    "errors": {
      "PROD-050": "Invalid brand_id: brand_xyz does not exist",
      "PROD-075": "Duplicate barcode: 1234567890123"
    }
  },
  "timestamp": "2024-01-15T10:30:00Z"
}

Error Responses

404 Not Found

{
  "code": 404,
  "error": "Product not found",
  "details": { "iv_id": "NONEXISTENT" }
}

409 Conflict

{
  "code": 409,
  "error": "Product with this iv_id already exists",
  "details": { "iv_id": "PROD-001", "existing_id": "r1234567890" }
}

422 Validation Error

{
  "code": 422,
  "error": "Validation failed",
  "details": { "iv_id": "Required field" }
}