Edit Product
curl --request PUT \
--url https://api.example.com/api/products/{product_id}/edit \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <x-api-key>' \
--data '
{
"name": "<string>",
"price": 123,
"current_price": 123,
"description": "<string>",
"short_description": "<string>",
"stock": 123,
"shipping_cost": 123,
"primary_image": "<string>",
"images": [
{}
],
"variations": [
{}
],
"size": [
{}
],
"colors": [
{}
],
"categories": [
{}
],
"is_sale": true,
"is_active": true,
"custom_questions": [
{}
],
"internal_note": "<string>",
"metadata": {}
}
'import requests
url = "https://api.example.com/api/products/{product_id}/edit"
payload = {
"name": "<string>",
"price": 123,
"current_price": 123,
"description": "<string>",
"short_description": "<string>",
"stock": 123,
"shipping_cost": 123,
"primary_image": "<string>",
"images": [{}],
"variations": [{}],
"size": [{}],
"colors": [{}],
"categories": [{}],
"is_sale": True,
"is_active": True,
"custom_questions": [{}],
"internal_note": "<string>",
"metadata": {}
}
headers = {
"X-API-Key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {'X-API-Key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
price: 123,
current_price: 123,
description: '<string>',
short_description: '<string>',
stock: 123,
shipping_cost: 123,
primary_image: '<string>',
images: [{}],
variations: [{}],
size: [{}],
colors: [{}],
categories: [{}],
is_sale: true,
is_active: true,
custom_questions: [{}],
internal_note: '<string>',
metadata: {}
})
};
fetch('https://api.example.com/api/products/{product_id}/edit', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/products/{product_id}/edit",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'price' => 123,
'current_price' => 123,
'description' => '<string>',
'short_description' => '<string>',
'stock' => 123,
'shipping_cost' => 123,
'primary_image' => '<string>',
'images' => [
[
]
],
'variations' => [
[
]
],
'size' => [
[
]
],
'colors' => [
[
]
],
'categories' => [
[
]
],
'is_sale' => true,
'is_active' => true,
'custom_questions' => [
[
]
],
'internal_note' => '<string>',
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/products/{product_id}/edit"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"price\": 123,\n \"current_price\": 123,\n \"description\": \"<string>\",\n \"short_description\": \"<string>\",\n \"stock\": 123,\n \"shipping_cost\": 123,\n \"primary_image\": \"<string>\",\n \"images\": [\n {}\n ],\n \"variations\": [\n {}\n ],\n \"size\": [\n {}\n ],\n \"colors\": [\n {}\n ],\n \"categories\": [\n {}\n ],\n \"is_sale\": true,\n \"is_active\": true,\n \"custom_questions\": [\n {}\n ],\n \"internal_note\": \"<string>\",\n \"metadata\": {}\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("X-API-Key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.example.com/api/products/{product_id}/edit")
.header("X-API-Key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"price\": 123,\n \"current_price\": 123,\n \"description\": \"<string>\",\n \"short_description\": \"<string>\",\n \"stock\": 123,\n \"shipping_cost\": 123,\n \"primary_image\": \"<string>\",\n \"images\": [\n {}\n ],\n \"variations\": [\n {}\n ],\n \"size\": [\n {}\n ],\n \"colors\": [\n {}\n ],\n \"categories\": [\n {}\n ],\n \"is_sale\": true,\n \"is_active\": true,\n \"custom_questions\": [\n {}\n ],\n \"internal_note\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/products/{product_id}/edit")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["X-API-Key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"price\": 123,\n \"current_price\": 123,\n \"description\": \"<string>\",\n \"short_description\": \"<string>\",\n \"stock\": 123,\n \"shipping_cost\": 123,\n \"primary_image\": \"<string>\",\n \"images\": [\n {}\n ],\n \"variations\": [\n {}\n ],\n \"size\": [\n {}\n ],\n \"colors\": [\n {}\n ],\n \"categories\": [\n {}\n ],\n \"is_sale\": true,\n \"is_active\": true,\n \"custom_questions\": [\n {}\n ],\n \"internal_note\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"message": "<string>"
}Product APIs
Edit Product
Update an existing product’s details
PUT
/
api
/
products
/
{product_id}
/
edit
Edit Product
curl --request PUT \
--url https://api.example.com/api/products/{product_id}/edit \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <x-api-key>' \
--data '
{
"name": "<string>",
"price": 123,
"current_price": 123,
"description": "<string>",
"short_description": "<string>",
"stock": 123,
"shipping_cost": 123,
"primary_image": "<string>",
"images": [
{}
],
"variations": [
{}
],
"size": [
{}
],
"colors": [
{}
],
"categories": [
{}
],
"is_sale": true,
"is_active": true,
"custom_questions": [
{}
],
"internal_note": "<string>",
"metadata": {}
}
'import requests
url = "https://api.example.com/api/products/{product_id}/edit"
payload = {
"name": "<string>",
"price": 123,
"current_price": 123,
"description": "<string>",
"short_description": "<string>",
"stock": 123,
"shipping_cost": 123,
"primary_image": "<string>",
"images": [{}],
"variations": [{}],
"size": [{}],
"colors": [{}],
"categories": [{}],
"is_sale": True,
"is_active": True,
"custom_questions": [{}],
"internal_note": "<string>",
"metadata": {}
}
headers = {
"X-API-Key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {'X-API-Key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
price: 123,
current_price: 123,
description: '<string>',
short_description: '<string>',
stock: 123,
shipping_cost: 123,
primary_image: '<string>',
images: [{}],
variations: [{}],
size: [{}],
colors: [{}],
categories: [{}],
is_sale: true,
is_active: true,
custom_questions: [{}],
internal_note: '<string>',
metadata: {}
})
};
fetch('https://api.example.com/api/products/{product_id}/edit', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/products/{product_id}/edit",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'price' => 123,
'current_price' => 123,
'description' => '<string>',
'short_description' => '<string>',
'stock' => 123,
'shipping_cost' => 123,
'primary_image' => '<string>',
'images' => [
[
]
],
'variations' => [
[
]
],
'size' => [
[
]
],
'colors' => [
[
]
],
'categories' => [
[
]
],
'is_sale' => true,
'is_active' => true,
'custom_questions' => [
[
]
],
'internal_note' => '<string>',
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/products/{product_id}/edit"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"price\": 123,\n \"current_price\": 123,\n \"description\": \"<string>\",\n \"short_description\": \"<string>\",\n \"stock\": 123,\n \"shipping_cost\": 123,\n \"primary_image\": \"<string>\",\n \"images\": [\n {}\n ],\n \"variations\": [\n {}\n ],\n \"size\": [\n {}\n ],\n \"colors\": [\n {}\n ],\n \"categories\": [\n {}\n ],\n \"is_sale\": true,\n \"is_active\": true,\n \"custom_questions\": [\n {}\n ],\n \"internal_note\": \"<string>\",\n \"metadata\": {}\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("X-API-Key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.example.com/api/products/{product_id}/edit")
.header("X-API-Key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"price\": 123,\n \"current_price\": 123,\n \"description\": \"<string>\",\n \"short_description\": \"<string>\",\n \"stock\": 123,\n \"shipping_cost\": 123,\n \"primary_image\": \"<string>\",\n \"images\": [\n {}\n ],\n \"variations\": [\n {}\n ],\n \"size\": [\n {}\n ],\n \"colors\": [\n {}\n ],\n \"categories\": [\n {}\n ],\n \"is_sale\": true,\n \"is_active\": true,\n \"custom_questions\": [\n {}\n ],\n \"internal_note\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/products/{product_id}/edit")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["X-API-Key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"price\": 123,\n \"current_price\": 123,\n \"description\": \"<string>\",\n \"short_description\": \"<string>\",\n \"stock\": 123,\n \"shipping_cost\": 123,\n \"primary_image\": \"<string>\",\n \"images\": [\n {}\n ],\n \"variations\": [\n {}\n ],\n \"size\": [\n {}\n ],\n \"colors\": [\n {}\n ],\n \"categories\": [\n {}\n ],\n \"is_sale\": true,\n \"is_active\": true,\n \"custom_questions\": [\n {}\n ],\n \"internal_note\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"message": "<string>"
}Overview
Update an existing product’s details. All fields are optional - only include fields you want to change. The same validation rules from Create Product apply.Rate Limit: 20 requests per minute
Endpoint
PUT https://api.tribemade.in/api/products/{product_id}/edit
Path Parameters
string
required
UUID of the product to edit
Authentication
string
required
Your TribeMade API key (format:
tb-xxxx-xxx-xxxx)Request Body
All fields from Create Product can be updated. Include only the fields you want to change.string
Product name (3-30 characters)
number
Original/MRP price in INR (must be > 0)
number
Sale price in INR (must be >= 0)
string
Detailed product description (0-500 characters)
string
Short description (0-50 characters)
integer
Available quantity (must be >= 0)
number
Shipping cost in INR (must be >= 0)
string
Primary product image URL or base64 (max 5MB)
array
Additional images (max 10, each max 5MB)
array
Product variations (max 20 items)
array
Available sizes (max 20 items)
array
Available colors (max 20 items)
array
Product categories (max 20, must exist in store)
boolean
Mark product as on sale
boolean
Product visibility to customers
array
Custom questions (max 5)
string
Private seller notes (0-500 characters)
object
Custom key-value pairs
Response
string
Success message: “Product updated successfully”
Examples
Update Price and Stock
curl -X PUT https://api.tribemade.in/api/products/660e8400-e29b-41d4-a716-446655440123/edit \
-H "X-API-Key: tb-a1b2-c3d-e4f5" \
-H "Content-Type: application/json" \
-d '{
"current_price": 799,
"stock": 200,
"is_sale": true
}'
import requests
product_id = "660e8400-e29b-41d4-a716-446655440123"
url = f"https://api.tribemade.in/api/products/{product_id}/edit"
headers = {
"X-API-Key": "tb-a1b2-c3d-e4f5",
"Content-Type": "application/json"
}
data = {
"current_price": 799,
"stock": 200,
"is_sale": True
}
response = requests.put(url, headers=headers, json=data)
print(response.json())
# Output: {"message": "Product updated successfully"}
const fetch = require('node-fetch');
const productId = '660e8400-e29b-41d4-a716-446655440123';
const url = `https://api.tribemade.in/api/products/${productId}/edit`;
const headers = {
'X-API-Key': 'tb-a1b2-c3d-e4f5',
'Content-Type': 'application/json'
};
const data = {
current_price: 799,
stock: 200,
is_sale: true
};
fetch(url, {
method: 'PUT',
headers: headers,
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => console.log(data));
// Output: {"message": "Product updated successfully"}
<?php
$product_id = '660e8400-e29b-41d4-a716-446655440123';
$url = "https://api.tribemade.in/api/products/{$product_id}/edit";
$headers = array(
'X-API-Key: tb-a1b2-c3d-e4f5',
'Content-Type: application/json'
);
$data = array(
'current_price' => 799,
'stock' => 200,
'is_sale' => true
);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
// Output: {"message": "Product updated successfully"}
?>
Success Response
{
"message": "Product updated successfully"
}
Update Multiple Fields
Update description, add internal notes, and update stock:{
"description": "Updated high-quality 100% cotton t-shirt with improved fabric",
"stock": 150,
"internal_note": "Supplier: ABC Corp, Cost: ₹550 (increased), Reorder at 20 units",
"metadata": {
"material": "100% Organic Cotton",
"care": "Machine wash cold, tumble dry low"
}
}
import requests
product_id = "660e8400-e29b-41d4-a716-446655440123"
url = f"https://api.tribemade.in/api/products/{product_id}/edit"
headers = {
"X-API-Key": "tb-a1b2-c3d-e4f5",
"Content-Type": "application/json"
}
data = {
"description": "Updated high-quality 100% cotton t-shirt",
"stock": 150,
"internal_note": "Supplier: ABC Corp, Cost: ₹550, Reorder at 20",
"metadata": {
"material": "100% Organic Cotton",
"care": "Machine wash cold"
}
}
response = requests.put(url, headers=headers, json=data)
print(response.json())
Disable Product
Temporarily hide a product from customers:curl -X PUT https://api.tribemade.in/api/products/660e8400-e29b-41d4-a716-446655440123/edit \
-H "X-API-Key: tb-a1b2-c3d-e4f5" \
-H "Content-Type: application/json" \
-d '{
"is_active": false,
"internal_note": "Out of stock from supplier. Expected restock: Dec 15"
}'
data = {
"is_active": False,
"internal_note": "Out of stock from supplier. Expected restock: Dec 15"
}
response = requests.put(url, headers=headers, json=data)
Update Images and Categories
{
"primary_image": "https://cdn.example.com/new-primary-image.jpg",
"images": [
"https://cdn.example.com/image-1.jpg",
"https://cdn.example.com/image-2.jpg",
"https://cdn.example.com/image-3.jpg"
],
"categories": ["Fashion", "Men's Wear", "New Arrivals"]
}
Categories must be created in your store first. Use exact category names (case-sensitive).
Error Responses
400 Bad Request - No Fields to Update
{
"error": "No valid fields to update"
}
400 Bad Request - Validation Errors
All validation errors from Create Product apply:- Invalid name length
- Invalid price (must be > 0)
- Invalid description length
- Invalid stock (must be >= 0)
- Too many images/variations/sizes/colors/categories
- Invalid categories
- Image too large
- Invalid custom question types
404 Not Found
{
"error": "Product not found or does not belong to this store"
}
- Product ID doesn’t exist
- Product belongs to a different store
- Product was deleted
401 Unauthorized
{
"error": "Invalid API key"
}
{
"error": "Missing API key"
}
429 Too Many Requests
{
"error": "Rate limit exceeded",
"retry_after": 60
}
Common Use Cases
Inventory Sync
Keep stock levels synchronized with your warehouse system:import requests
def sync_inventory(products_to_update):
"""
Sync inventory from warehouse system to TribeMade
products_to_update: [{"id": "product_id", "stock": 50}, ...]
"""
url_base = "https://api.tribemade.in/api/products"
headers = {
"X-API-Key": "tb-a1b2-c3d-e4f5",
"Content-Type": "application/json"
}
for product in products_to_update:
url = f"{url_base}/{product['id']}/edit"
data = {"stock": product['stock']}
try:
response = requests.put(url, headers=headers, json=data)
if response.status_code == 200:
print(f"✓ Updated {product['id']}: stock = {product['stock']}")
else:
print(f"✗ Failed {product['id']}: {response.json()['error']}")
except Exception as e:
print(f"✗ Error {product['id']}: {str(e)}")
# Example usage
products_to_update = [
{"id": "660e8400-e29b-41d4-a716-446655440123", "stock": 45},
{"id": "770e8400-e29b-41d4-a716-446655440124", "stock": 32},
{"id": "880e8400-e29b-41d4-a716-446655440125", "stock": 78}
]
sync_inventory(products_to_update)
Flash Sale
Run a flash sale by updating prices:import requests
import time
def start_flash_sale(product_ids, discount_percent):
"""
Apply discount to multiple products for a flash sale
"""
url_base = "https://api.tribemade.in/api/products"
headers = {
"X-API-Key": "tb-a1b2-c3d-e4f5",
"Content-Type": "application/json"
}
for product_id in product_ids:
url = f"{url_base}/{product_id}/edit"
# First, get current price (assume you have it stored)
# For demo, we'll use a fixed price
original_price = 1000
sale_price = original_price * (1 - discount_percent / 100)
data = {
"current_price": sale_price,
"is_sale": True,
"internal_note": f"Flash sale: {discount_percent}% off until end of day"
}
response = requests.put(url, headers=headers, json=data)
print(f"Applied {discount_percent}% discount to {product_id}")
# Respect rate limits
time.sleep(3) # ~20 requests per minute
# Start 30% off flash sale
product_ids = ["660e8400-...", "770e8400-...", "880e8400-..."]
start_flash_sale(product_ids, discount_percent=30)
Bulk Status Update
Activate or deactivate multiple products:import requests
import time
def bulk_update_status(product_ids, is_active):
"""
Activate or deactivate multiple products
"""
url_base = "https://api.tribemade.in/api/products"
headers = {
"X-API-Key": "tb-a1b2-c3d-e4f5",
"Content-Type": "application/json"
}
status_text = "activated" if is_active else "deactivated"
for product_id in product_ids:
url = f"{url_base}/{product_id}/edit"
data = {"is_active": is_active}
try:
response = requests.put(url, headers=headers, json=data)
if response.status_code == 200:
print(f"✓ Product {product_id} {status_text}")
else:
print(f"✗ Failed to update {product_id}")
except Exception as e:
print(f"✗ Error: {str(e)}")
time.sleep(3)
# Deactivate out-of-season products
winter_products = ["660e8400-...", "770e8400-..."]
bulk_update_status(winter_products, is_active=False)
Best Practices
Update only what changed
Update only what changed
Only include fields that need to be updated. Don’t send the entire product object:✅ Good:❌ Bad:
{
"stock": 200,
"current_price": 799
}
{
"name": "Same Name",
"price": 1299,
"description": "Same description...",
"stock": 200,
"current_price": 799,
// ... all other unchanged fields
}
Sync inventory regularly
Sync inventory regularly
Set up automated inventory sync to keep stock levels accurate:
- Run sync every 15-30 minutes for high-traffic stores
- Use webhooks to get notified of orders and update stock accordingly
- Log sync operations for debugging
Schedule price updates
Schedule price updates
For sales and promotions:
- Update prices at specific times (e.g., midnight for daily deals)
- Store original prices before sales to restore later
- Use
internal_noteto track sale end dates
Batch updates efficiently
Batch updates efficiently
For bulk updates:
- Process in batches of 15-18 products per minute
- Add 3-4 second delays between requests
- Implement retry logic for failed updates
- Log all operations for tracking
Use is_active for temporary removal
Use is_active for temporary removal
Instead of deleting products, use
is_active: false to temporarily hide them:- Preserves product data and history
- Can be reactivated anytime
- Maintains order references
- Useful for seasonal products
Next Steps
Create Product
Learn how to create new products
Delete Product
Remove products from your store
Order APIs
Manage orders programmatically
Rate Limits
Understand API rate limits

