Spaces:
Runtime error
Taxonomy API
Endpoints
| Method | URL | Description |
|---|---|---|
POST |
/taxonomy/ |
Create or append taxonomy values |
PUT |
/taxonomy/ |
Replace (overwrite) taxonomy field values |
Both endpoints require a Bearer token (JWT). merchant_id is always extracted from the JWT — do not pass it in the request body.
POST /taxonomy/ — Create or Append
Overview
Handles both create and append of taxonomy data. The operation is determined automatically based on whether a taxonomy document already exists for the merchant.
How Create vs Append Works
| Scenario | Behaviour |
|---|---|
| No taxonomy document exists for the merchant | Creates a new document (operation: "created") |
| Document already exists | Appends new values using MongoDB $addToSet — no duplicates (operation: "updated") |
is_delete: true is passed |
Removes the specified values from the arrays |
The key behaviour for updates: values are appended, not replaced. If you send brands: ["Nike"] and the document already has ["Adidas"], the result will be ["Adidas", "Nike"]. To replace entirely, use PUT /taxonomy/.
PUT /taxonomy/ — Replace Field Values
Overview
Replaces the value of each provided field entirely. Only fields included in the request body are affected — omitted fields remain unchanged.
- Method:
PUT - URL:
/taxonomy/ - Auth: Bearer token (JWT) required
- Prerequisite: A taxonomy document must already exist for the merchant (use
POSTto create it first)
How Replace Works
| Scenario | Behaviour |
|---|---|
| Field is included in request body | Existing array is overwritten with the new values |
| Field is omitted from request body | Field is left unchanged |
| Document does not exist | Returns 422 — use POST /taxonomy/ to create first |
Example: if the document has brands: ["Adidas", "Nike"] and you PUT with brands: ["Puma"], the result will be brands: ["Puma"].
Response — 200 OK
{
"success": true,
"message": "Taxonomy fields replaced successfully",
"data": {
"taxonomy_id": "64f1a2b3c4d5e6f7a8b9c0d1",
"operation": "replaced",
"merchant_id": "af59ab73-4ef4-43a0-aac3-6909f3ba87e4",
"modified_count": 1
},
"timestamp": "2026-03-14T10:30:00.000Z"
}
Usage Example
curl -X PUT https://<host>/taxonomy/ \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"brands": ["Puma"],
"categories": ["Hair", "Skin"]
}'
Request Body
All fields are optional. Only send the fields you want to add/update.
{
"brands": ["L'Oréal Professional", "Schwarzkopf"],
"categories": ["Hair", "Skin", "Nails"],
"lines": ["Hair Care", "Hair Styling"],
"classes": ["Premium", "Luxury", "Basic"],
"subcategories": {
"Hair": ["Hair Cut", "Hair Color", "Hair Treatment"],
"Skin": ["Facial", "Cleanup"]
},
"job_role": ["Senior Stylist", "Director", "Massage Therapist"],
"specializations": ["Hairdresser", "Nail Technician", "Esthetician"],
"languages": ["English", "Hindi", "Tamil"],
"designation": ["CTO", "CEO", "RSM", "ASM"],
"regions": ["East", "West", "North", "South"],
"customer_group": ["VIP", "Regular", "Premium", "Gold"],
"pos_tender_modes": ["Cash", "Credit Card", "Debit Card", "Mobile Payment"],
"payment_types": ["Cash and Carry", "Credit"],
"payment_methods": ["Bank Transfer", "Cash", "Cheque"],
"pos_modes": ["Walk-in", "Appointment", "Online"],
"pricing_model": ["Weight_Based", "Fixed_Rate", "Zone_Based"],
"asset_location": ["Store Floor", "Warehouse", "Back Office"],
"asset_category": ["Electronics", "Furniture", "Equipment"],
"stock_bin_location": ["A1-01", "B2-15", "C3-07"],
"branch_types": ["Flagship", "Outlet", "Franchise"],
"store_types": ["Retail", "Wholesale", "Online"],
"expense_types": ["Travel", "Office Supplies"],
"region_codes": ["IN-KA-BLR", "IN-TN-CHN"],
"states": ["Maharashtra", "Karnataka", "Tamil Nadu"],
"relations": ["Parent", "Subsidiary", "Partner", "Vendor"],
"document_types": ["Invoice", "Receipt", "Purchase Order"],
"merchant_types": [
{ "code": "cnf", "label": "CNF", "order": 1 },
{ "code": "distributor", "label": "Distributor", "order": 2 },
{ "code": "retail", "label": "Retail", "order": 3 }
],
"is_delete": false
}
Field Reference
Simple String Arrays
All of these follow the same pattern — send an array of strings to add values:
| Field | Description | Example |
|---|---|---|
brands |
Product brands | ["L'Oréal", "Schwarzkopf"] |
categories |
Product categories | ["Hair", "Skin", "Nails"] |
lines |
Product lines | ["Hair Care", "Hair Styling"] |
classes |
Product classes | ["Premium", "Luxury"] |
job_role |
Employee job roles | ["Senior Stylist", "Director"] |
specializations |
Employee specializations | ["Hairdresser", "Esthetician"] |
languages |
Languages | ["English", "Hindi"] |
designation |
Employee designations | ["CTO", "RSM", "ASM"] |
regions |
Region groups | ["East", "West", "North"] |
customer_group |
Customer groups | ["VIP", "Regular", "Gold"] |
pos_tender_modes |
POS tender modes | ["Cash", "Credit Card"] |
payment_types |
Payment types | ["Cash and Carry", "Credit"] |
payment_methods |
Payment methods | ["Bank Transfer", "Cash"] |
pos_modes |
POS modes | ["Walk-in", "Appointment"] |
pricing_model |
Pricing models | ["Fixed_Rate", "Weight_Based"] |
asset_location |
Asset locations | ["Store Floor", "Warehouse"] |
asset_category |
Asset categories | ["Electronics", "Furniture"] |
stock_bin_location |
Stock bin locations | ["A1-01", "B2-15"] |
branch_types |
Branch types | ["Flagship", "Outlet"] |
store_types |
Store types | ["Retail", "Wholesale"] |
expense_types |
Expense types | ["Travel", "Office Supplies"] |
region_codes |
Region codes | ["IN-KA-BLR", "IN-TN-CHN"] |
states |
States | ["Maharashtra", "Karnataka"] |
relations |
Merchant relations | ["Parent", "Subsidiary"] |
document_types |
Document types | ["Invoice", "Receipt"] |
subcategories — Object (category → values)
Maps a parent category to its subcategory values.
{
"subcategories": {
"Hair": ["Hair Cut", "Hair Color", "Hair Treatment"],
"Skin": ["Facial", "Cleanup", "Peel"]
}
}
merchant_types — Structured Array
Each item must have all three fields:
| Field | Type | Required | Description |
|---|---|---|---|
code |
string | ✅ | Unique identifier (e.g., "cnf", "distributor") |
label |
string | ✅ | Display name (e.g., "CNF", "Distributor") |
order |
integer ≥ 1 | ✅ | Sort order — must be positive, no duplicates |
{
"merchant_types": [
{ "code": "cnf", "label": "CNF", "order": 1 },
{ "code": "distributor", "label": "Distributor", "order": 2 }
]
}
is_delete — Boolean (default: false)
When true, the values in the payload are removed from the existing arrays instead of being added.
{
"brands": ["OldBrand"],
"is_delete": true
}
Response
Success — 201 Created
{
"success": true,
"message": "Taxonomy operation completed successfully",
"data": {
"taxonomy_id": "64f1a2b3c4d5e6f7a8b9c0d1",
"operation": "created",
"merchant_id": "af59ab73-4ef4-43a0-aac3-6909f3ba87e4",
"modified_count": 1
},
"timestamp": "2026-03-14T10:30:00.000Z"
}
| Field | Description |
|---|---|
data.taxonomy_id |
MongoDB document ID of the taxonomy record |
data.operation |
"created" for new documents, "updated" for existing |
data.modified_count |
Number of documents modified (typically 1) |
Usage Examples
1. Initial Setup — Create taxonomy for a new merchant
Send all the values you want to seed:
curl -X POST https://<host>/taxonomy/ \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"brands": ["L'\''Oréal Professional", "Schwarzkopf"],
"categories": ["Hair", "Skin", "Nails"],
"job_role": ["Senior Stylist", "Junior Stylist"],
"customer_group": ["VIP", "Regular"]
}'
2. Add new values to existing taxonomy
Only send the new values — existing ones are preserved:
curl -X POST https://<host>/taxonomy/ \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"brands": ["Kerastase"],
"categories": ["Makeup"]
}'
Result: brands will now contain ["L'Oréal Professional", "Schwarzkopf", "Kerastase"]
3. Delete specific values
curl -X POST https://<host>/taxonomy/ \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"brands": ["OldBrand"],
"is_delete": true
}'
4. Add subcategories
curl -X POST https://<host>/taxonomy/ \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"subcategories": {
"Hair": ["Hair Cut", "Hair Color"],
"Skin": ["Facial", "Cleanup"]
}
}'
5. Set up merchant types
curl -X POST https://<host>/taxonomy/ \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"merchant_types": [
{ "code": "cnf", "label": "CNF", "order": 1 },
{ "code": "distributor", "label": "Distributor", "order": 2 },
{ "code": "retail", "label": "Retail", "order": 3 }
]
}'
Error Responses
| Status | Scenario |
|---|---|
401 Unauthorized |
Missing or invalid JWT token |
403 Forbidden |
User has no associated merchant |
422 Unprocessable Entity |
Validation failure (e.g., order <= 0, empty code) |
500 Internal Server Error |
Database operation failed |
Validation Error Example (422)
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Order must be a positive integer",
"details": {}
}
}
Important Notes
- merchant_id is never sent in the body — it is always extracted from the JWT token.
- Append-only by default — sending existing values again has no effect (idempotent for duplicates).
merchant_typesdeduplication — duplicatecodeorordervalues within the same request are silently skipped; the first occurrence wins.- String sanitization — all string values are trimmed of whitespace and empty strings are ignored automatically.
subcategoriesmerge — new keys are added, existing keys get new values appended. Existing subcategory values are not removed unlessis_delete: true.