Skip to main content

Overview

Update an existing product in the Juadah bakery catalog. This endpoint supports updating product details and managing images (adding new images and removing existing ones).

Endpoint

PUT /api/products/:id

Authentication & Authorization

This endpoint requires Admin access. Regular users will receive a 403 Forbidden error.
Requires authentication via cookie-based session with admin role.

Path Parameters

id
number
required
The unique identifier of the product to update.

Request Body

This endpoint accepts multipart/form-data for file uploads.
name
string
required
Product name. Cannot be empty.
description
string
required
Product description. Cannot be empty.
price
number
required
Product price in rupiah. Must be a valid number.
images.removed
string[]
required
Array of image identifiers to remove from the product. Pass an empty array [] if no images should be removed.
images
file[]
Array of new image files to upload. Supports up to 5 images total (including existing images). Accepted formats: .png, .jpg, .jpeg.

Response

status
string
required
Response status. Returns "success" for successful requests.
data
object
required
Response data containing the updated product.
products
object
The updated product object.
id
number
Unique product identifier.
name
string
Updated product name.
description
string
Updated product description.
price
number
Updated product price in rupiah.
images
string[]
Array of image URLs (new and remaining images after removal).

Example Request

Update Product Details Only

curl -X PUT "https://juadah-backend.vercel.app/api/products/1" \
  -H "Cookie: accessToken=your-admin-access-token" \
  -F "name=Updated Kue Bolu" \
  -F "description=Updated kue bolu description" \
  -F "price=15000" \
  -F "images.removed[]=" 

Update Product and Add New Images

curl -X PUT "https://juadah-backend.vercel.app/api/products/1" \
  -H "Cookie: accessToken=your-admin-access-token" \
  -F "name=Updated Kue Bolu" \
  -F "description=Updated kue bolu description" \
  -F "price=15000" \
  -F "images.removed[]=" \
  -F "images=@/path/to/new-image1.png" \
  -F "images=@/path/to/new-image2.jpg"

Update Product and Remove Images

curl -X PUT "https://juadah-backend.vercel.app/api/products/1" \
  -H "Cookie: accessToken=your-admin-access-token" \
  -F "name=Updated Kue Bolu" \
  -F "description=Updated kue bolu description" \
  -F "price=15000" \
  -F "images.removed[]=image-id-1" \
  -F "images.removed[]=image-id-2"

Update with Image Replacement (Remove Old, Add New)

curl -X PUT "https://juadah-backend.vercel.app/api/products/1" \
  -H "Cookie: accessToken=your-admin-access-token" \
  -F "name=Updated Kue Bolu" \
  -F "description=Updated kue bolu description" \
  -F "price=15000" \
  -F "images.removed[]=old-image-id" \
  -F "images=@/path/to/new-image.png"

Using JavaScript (Fetch API)

const formData = new FormData();
formData.append('name', 'Updated Kue Bolu');
formData.append('description', 'Updated kue bolu description');
formData.append('price', '15000');

// Remove specific images
formData.append('images.removed[]', 'image-id-to-remove');

// Add new images
formData.append('images', newImageFile1);
formData.append('images', newImageFile2);

const response = await fetch('https://juadah-backend.vercel.app/api/products/1', {
  method: 'PUT',
  credentials: 'include',
  body: formData
});

const result = await response.json();

Using Python (requests)

import requests

url = "https://juadah-backend.vercel.app/api/products/1"

files = [
    ('images', open('new-image.png', 'rb'))
]

data = {
    'name': 'Updated Kue Bolu',
    'description': 'Updated kue bolu description',
    'price': '15000',
    'images.removed[]': 'image-id-to-remove'
}

cookies = {
    'accessToken': 'your-admin-access-token'
}

response = requests.put(url, files=files, data=data, cookies=cookies)
print(response.json())

Example Response

Success Response (200)

{
  "status": "success",
  "data": {
    "products": {
      "id": 1,
      "name": "Updated Kue Bolu",
      "description": "Updated kue bolu description",
      "price": 15000,
      "images": [
        "https://res.cloudinary.com/demo/image/upload/new/image/path.png"
      ]
    }
  }
}

Validation Error (400)

{
  "status": "fail",
  "errors": {
    "code": 400,
    "message": "validation errors",
    "details": {
      "price": "price should be a number",
      "name": "name is required"
    }
  }
}

Image Limit Error (400)

Returned when total images (existing + new - removed) exceed 5.
{
  "status": "fail",
  "errors": {
    "code": 400,
    "message": "each product can only have 5 images at max"
  }
}

Image Format Error (400)

{
  "status": "fail",
  "errors": {
    "code": 400,
    "message": "validation errors",
    "details": {
      "images": "invalid file format, please only upload file with .png or .jpg extension"
    }
  }
}

Forbidden Error (403)

Returned when a non-admin user attempts to update a product.
{
  "status": "fail",
  "errors": {
    "code": 403,
    "message": "this action is only for user with admin access"
  }
}

Not Found Error (404)

Returned when the product with the specified ID doesn’t exist.
{
  "status": "fail",
  "errors": {
    "code": 404,
    "message": "resource you're looking for is not found"
  }
}

Validation Rules

  • name: Required, must not be empty
  • description: Required, must not be empty
  • price: Required, must be a valid number
  • images.removed: Required field (can be empty array)
  • images: Optional, maximum 5 total images per product
  • Supported image formats: .png, .jpg, .jpeg

Image Management Details

  • Maximum images: Each product can have up to 5 images
  • Adding images: Upload new images using the images field
  • Removing images: Specify image IDs in the images.removed array
  • Image validation: Only .png, .jpg, and .jpeg formats are accepted
  • Cloudinary integration: Images are stored on Cloudinary
  • Total count validation: The system validates that (existing images - removed images + new images) ≤ 5

Implementation Notes

  • The endpoint uses multer middleware to handle multipart/form-data
  • Images are uploaded to Cloudinary
  • Old images specified in images.removed are deleted from Cloudinary
  • Update operations are transactional
  • All fields (name, description, price) must be provided even if only some are being changed