メインコンテンツまでスキップ
バージョン: 🚧 Canary

📦 Product Service

Testing Status

The Product Service provides a complete REST API for managing product entities with comprehensive CRUD operations and powerful batch processing capabilities. It's built using the Nodeblocks functional composition approach and integrates seamlessly with MongoDB.


🚀 Quickstart

import express from 'express';
import { middlewares, services, drivers } from '@nodeblocks/backend-sdk';

const { nodeBlocksErrorMiddleware } = middlewares;
const { productService } = services;
const { withMongo, createFileStorageDriver } = drivers;

const connectToDatabase = withMongo('mongodb://localhost:27017', 'dev', 'user', 'password');

// Required for image upload URL endpoint:
// Ensure GOOGLE_APPLICATION_CREDENTIALS is set to your Google Cloud service account JSON.
const fileStorageDriver = createFileStorageDriver(
'your-gcp-project-id',
'your-bucket-name'
);

express()
.use(
productService(
{
...(await connectToDatabase('products')),
...(await connectToDatabase('identities')),
},
{
authSecrets: {
authEncSecret: 'your-encryption-secret',
authSignSecret: 'your-signing-secret',
},
identity: {
typeIds: {
admin: '100',
guest: '000',
regular: '001',
},
},
},
{ fileStorageDriver }
)
)
.use(nodeBlocksErrorMiddleware())
.listen(8089, () => console.log('Server running'));

📋 Endpoint Summary

Individual Product Operations

MethodPathDescriptionAuthorization
POST/productsCreate a new productBearer token required (admin only)
GET/products/:productIdRetrieve a product by IDNone required
GET/productsList/filter productsNone required
GET/products/organizations/:organizationIdList products by organizationBearer token required (org member+)
GET/products/:productId/likersList users who liked a productBearer token required (admin only)
PATCH/products/:productIdUpdate a productBearer token required (admin only)
DELETE/products/:productIdDelete a productBearer token required (admin only)
POST/products/:productId/copyCopy an existing productBearer token required (admin only)

File Upload Operations

MethodPathDescriptionAuthorization
GET/products/:productId/image-upload-urlGet signed URL to upload a product imageBearer token required (admin only)
POST/products/:productId/imagesCreate a product image entryBearer token required (admin only)
DELETE/products/:productId/images/:imageIdDelete a product imageBearer token required (admin only)

Batch Product Operations

MethodPathDescriptionAuthorization
POST/products/batchCreate multiple productsBearer token required (admin only)
PATCH/products/batchUpdate multiple productsBearer token required (admin only)
DELETE/products/batchDelete multiple productsBearer token required (admin only)
POST/products/batch/copyCopy multiple productsBearer token required (admin only)

Product Variant Operations

MethodPathDescriptionAuthorization
POST/products/:productId/variantsCreate a product variantBearer token required (admin only)
GET/products/:productId/variantsList variants for a productNone required
GET/products/:productId/variants/:productVariantIdGet a specific variantBearer token required
PATCH/products/:productId/variants/:productVariantIdUpdate a product variantBearer token required (admin only)
DELETE/products/:productId/variants/:productVariantIdDelete a product variantBearer token required (admin only)
POST/product/:productId/variants/bulkCreate multiple variantsBearer token required (admin only)
PATCH/product/:productId/variants/bulkUpdate multiple variantsBearer token required (admin only)
POST/product/:productId/variants/bulk-deleteDelete multiple variantsBearer token required (admin only)

🗄️ Entity Schema

The product entity combines base fields (auto-generated) with product-specific data including images:

{
"name": "string",
"description": "string",
"images": [
{
"objectId": "string (uuid)",
"type": "string",
"id": "string (uuid)",
"createdAt": "string (datetime)",
"updatedAt": "string (datetime)"
}
],
"createdAt": "string (datetime)",
"id": "string (uuid)",
"updatedAt": "string (datetime)"
}

Field Details

FieldTypeAuto-GeneratedRequiredDescription
namestringProduct name
descriptionstringProduct description
imagesarrayPartialArray of product images
images[].objectIdstring (uuid)Object identifier for the image file
images[].typestringImage MIME type (e.g., 'image/png')
images[].idstring (uuid)Unique identifier for the image entity
images[].createdAtdatetimeImage creation timestamp
images[].updatedAtdatetimeImage last modification timestamp
createdAtdatetimeProduct creation timestamp
idstring (uuid)Unique product identifier (UUID)
updatedAtdatetimeProduct last modification timestamp

📝 Note:

  • Auto-generated fields are set by the service and should not be included in create/update requests
  • Each image in the images array gets its own base entity fields (id, createdAt, updatedAt)
  • The objectId in each image references the actual image file in storage
  • Field order in responses matches the actual API output

🔐 Authentication Headers

For protected endpoints, include the following headers:

Authorization: Bearer <admin_access_token>
x-nb-fingerprint: <device_fingerprint>

⚠️ Important: The x-nb-fingerprint header is required for all authenticated requests if fingerprint was specified during authorization. Without it, requests will return 401 Unauthorized.


🔧 API Endpoints

1. Create Product

Creates a new product with the provided information.

Request:

  • Method: POST
  • Path: /products
  • Headers: Content-Type: application/json, Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

Request Body:

FieldTypeRequiredDescription
namestringProduct name
descriptionstringProduct description

Response Body:

FieldTypeDescription
idstringUnique product identifier
namestringProduct name
descriptionstringProduct description
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Enforced automatically (name, description required)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X POST {{host}}/products \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"name": "Premium Widget",
"description": "High-quality widget for enterprise use"
}'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"name": "Premium Widget",
"description": "High-quality widget for enterprise use",
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T09:41:22.552Z"
}

Error Responses:

When request body is missing required fields:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'name'",
"request body must have required property 'description'"
]
}
}

When database insert operation fails:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
"error": {
"message": "Failed to create product"
}
}

2. Get Product by ID

Retrieves a specific product by their unique ID.

Request:

  • Method: GET
  • Path: /products/:productId
  • Authorization: None required

URL Parameters:

ParameterTypeRequiredDescription
productIdstringUnique product identifier

Response Body:

FieldTypeDescription
idstringUnique product identifier
namestringProduct name
descriptionstringProduct description
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Path parameter validation (productId required)
  • Route Validators: None

Example Request:

curl {{host}}/products/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"name": "Premium Widget",
"description": "High-quality widget for enterprise use",
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T09:41:22.552Z"
}

Error Responses:

When no product exists with the provided ID:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Product not found"
}
}

3. List Products

Retrieves a list of products with optional filtering and pagination.

Request:

  • Method: GET
  • Path: /products
  • Authorization: None required

Query Parameters:

ParameterTypeRequiredDescription
namestringFilter by product name
descriptionstringFilter by product description
pagenumberPage number for pagination (1-1000)
limitnumberNumber of items per page (1-50)

Response Body:

FieldTypeDescription
idstringUnique product identifier
namestringProduct name
descriptionstringProduct description
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Query parameter validation (optional name, description, page, limit)
  • Route Validators: None

Example Requests:

List all products:

curl {{host}}/products

Filter by name:

curl "{{host}}/products?name=Premium%20Widget"

With pagination:

curl "{{host}}/products?page=1&limit=10"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

[
{
"name": "Premium Widget",
"description": "Updated high-quality widget for enterprise use",
"createdAt": "2025-06-24T06:39:17.101Z",
"id": "3d0e4b74-398c-43e2-a7b4-c9a180477322",
"updatedAt": "2025-06-24T06:39:17.101Z"
},
{
"name": "Product A",
"description": "Updated batch description",
"createdAt": "2025-06-24T06:39:45.378Z",
"id": "0e0dd6c7-c3d5-49e5-a1d8-20daa34d380a",
"updatedAt": "2025-06-24T06:39:55.720Z"
},
{
"name": "Product B",
"description": "Updated batch description",
"createdAt": "2025-06-24T06:39:45.378Z",
"id": "d5a60fdf-2a22-4fcc-8e40-a68cb89cce72",
"updatedAt": "2025-06-24T06:39:55.720Z"
}
]

4. List Products by Organization ID

Retrieves a list of products scoped to a specific organization with pagination and image normalization.

Request:

  • Method: GET
  • Path: /products/organizations/:organizationId
  • Authorization: Bearer token required (organization member, admin, or owner)

URL Parameters:

ParameterTypeRequiredDescription
organizationIdstringOrganization identifier to scope product retrieval

Query Parameters:

ParameterTypeRequiredDescription
pagenumberPage number for pagination (1-1000)
limitnumberNumber of items per page (1-50)

Response Body:

FieldTypeDescription
dataarrayArray of product objects
data[].idstringUnique product identifier
data[].organizationIdstringOrganization identifier
data[].namestringProduct name
data[].descriptionstringProduct description
data[].imagesarrayArray of product images with URLs
data[].createdAtstringCreation timestamp
data[].updatedAtstringLast update timestamp
metadataobjectPagination metadata
metadata.paginationobjectPagination information
metadata.pagination.pagenumberCurrent page number
metadata.pagination.limitnumberItems per page
metadata.pagination.totalnumberTotal number of products
metadata.pagination.totalPagesnumberTotal number of pages
metadata.pagination.hasNextbooleanWhether there are more pages
metadata.pagination.hasPrevbooleanWhether there are previous pages

Validation:

  • Schema Validation: Organization ID path parameter and pagination query parameters
  • Route Validators: Authentication required, organization membership validation
  • Authorization: User must be a member, admin, or owner of the organization

Example Requests:

List products for an organization:

curl -H "Authorization: Bearer eyJ..." "{{host}}/products/organizations/org-123"

With pagination:

curl -H "Authorization: Bearer eyJ..." "{{host}}/products/organizations/org-123?page=1&limit=5"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"data": [
{
"id": "prod-123",
"organizationId": "org-456",
"name": "Premium Widget",
"description": "High-quality widget for professionals",
"images": [
{
"id": "img-789",
"objectId": "abc123...",
"type": "image/jpeg",
"url": "https://storage.googleapis.com/bucket/abc123..."
}
],
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 10,
"total": 25,
"totalPages": 3,
"hasNext": true,
"hasPrev": false
}
}
}

Error Responses:

  • 401 Unauthorized: Authentication failed
  • 403 Forbidden: User doesn't have access to the organization
  • 500 Internal Server Error: Database operation failed or file storage error

Use Cases:

  • Organization-specific product catalogs in multi-tenant applications
  • Admin dashboards for managing products within an organization
  • API consumers retrieving products for a specific business entity

5. List Product Likers

Retrieves a list of users who have liked a specific product with pagination and avatar normalization.

Request:

  • Method: GET
  • Path: /products/:productId/likers
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringProduct identifier to retrieve likers for

Query Parameters:

ParameterTypeRequiredDescription
pagenumberPage number for pagination (1-1000)
limitnumberNumber of items per page (1-50)

Response Body:

FieldTypeDescription
dataarrayArray of user objects who liked the product
data[].idstringUser identifier
data[].namestringUser display name
data[].avatarobjectUser avatar with signed URL
data[].avatar.idstringAvatar file identifier
data[].avatar.objectIdstringCloud storage object identifier
data[].avatar.typestringMIME type of the avatar image
data[].avatar.urlstringSigned URL for avatar access
metadataobjectPagination metadata
metadata.paginationobjectPagination information
metadata.pagination.pagenumberCurrent page number
metadata.pagination.limitnumberItems per page
metadata.pagination.totalnumberTotal number of likers
metadata.pagination.totalPagesnumberTotal number of pages
metadata.pagination.hasNextbooleanWhether there are more pages
metadata.pagination.hasPrevbooleanWhether there are previous pages

Validation:

  • Schema Validation: Product ID path parameter and pagination query parameters
  • Route Validators: Authentication required, admin-only authorization
  • Authorization: User must have admin role

Example Requests:

List product likers:

curl -H "Authorization: Bearer eyJ..." "{{host}}/products/prod-123/likers"

With pagination:

curl -H "Authorization: Bearer eyJ..." "{{host}}/products/prod-123/likers?page=1&limit=5"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"data": [
{
"id": "user-123",
"name": "John Doe",
"avatar": {
"id": "avatar-456",
"objectId": "abc123...",
"type": "image/jpeg",
"url": "https://storage.googleapis.com/bucket/abc123..."
}
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 10,
"total": 25,
"totalPages": 3,
"hasNext": true,
"hasPrev": false
}
}
}

Error Responses:

  • 401 Unauthorized: Authentication failed
  • 403 Forbidden: Non-admin user attempting to view likers
  • 404 Not Found: Product not found
  • 500 Internal Server Error: Database operation failed or file storage error

Use Cases:

  • Admin dashboards showing product engagement metrics
  • Social features displaying who liked products
  • Analytics and reporting on product popularity
  • User relationship analysis for recommendation systems

6. Update Product

Updates an existing product with partial data.

Request:

  • Method: PATCH
  • Path: /products/:productId
  • Headers: Content-Type: application/json, Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringUnique product identifier

Request Body (all fields optional):

FieldTypeRequiredDescription
namestringProduct name
descriptionstringProduct description

Response Body:

FieldTypeDescription
idstringUnique product identifier
namestringUpdated product name
descriptionstringUpdated product description
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Enforced automatically (partial updates, all fields optional, no additional properties allowed)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X PATCH {{host}}/products/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{"description": "Updated high-quality widget for enterprise use"}'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"name": "Premium Widget",
"description": "Updated high-quality widget for enterprise use",
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T14:22:15.789Z"
}

Error Responses:

When no product exists with the provided ID:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Product not found"
}
}

7. Delete Product

Permanently deletes a product from the system.

Request:

  • Method: DELETE
  • Path: /products/:productId
  • Headers: Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringUnique product identifier

Response Body:

FieldTypeDescription
No response body-Delete endpoint returns no response body on success

Validation:

  • Schema Validation: Path parameter validation (productId required)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X DELETE {{host}}/products/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2 \
-H "Authorization: Bearer <access-token>"

Success Response:

HTTP/1.1 204 No Content

Error Responses:

When no product exists with the provided ID:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Product not found"
}
}

8. Copy Product

Creates a copy of an existing product with a new ID.

Request:

  • Method: POST
  • Path: /products/:productId/copy
  • Headers: Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringID of product to copy

Response Body:

FieldTypeDescription
idstringUnique identifier for the copied product
namestringProduct name (copied from original)
descriptionstringProduct description (copied from original)
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Path parameter validation (productId required)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X POST {{host}}/products/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/copy \
-H "Authorization: Bearer <access-token>"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"id": "9abc123f-1cd8-4def-b123-456789abcdef",
"name": "Premium Widget",
"description": "High-quality widget for enterprise use",
"createdAt": "2024-05-28T15:30:45.123Z",
"updatedAt": "2024-05-28T15:30:45.123Z"
}

Error Responses:

When no product exists with the provided ID:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Product not found"
}
}

🔄 Batch Product Operations

The Product Service provides powerful batch operations for managing multiple products efficiently.

9. Create Multiple Products

Creates multiple products in a single request.

Request:

  • Method: POST
  • Path: /products/batch
  • Headers: Content-Type: application/json, Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

Request Body: Array of product objects, each requiring name and description.

Response Body:

FieldTypeDescription
idstringUnique product identifier
namestringProduct name
descriptionstringProduct description
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Enforced automatically (array of product objects with required name and description)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X POST {{host}}/products/batch \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '[
{
"name": "Product A",
"description": "Description for Product A"
},
{
"name": "Product B",
"description": "Description for Product B"
}
]'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

[
{
"name": "Product A",
"description": "Description for Product A",
"createdAt": "2025-06-24T06:39:45.378Z",
"id": "0e0dd6c7-c3d5-49e5-a1d8-20daa34d380a",
"updatedAt": "2025-06-24T06:39:45.378Z"
},
{
"name": "Product B",
"description": "Description for Product B",
"createdAt": "2025-06-24T06:39:45.378Z",
"id": "d5a60fdf-2a22-4fcc-8e40-a68cb89cce72",
"updatedAt": "2025-06-24T06:39:45.378Z"
}
]

10. Update Multiple Products

Updates multiple products with the same data in a single request.

Request:

  • Method: PATCH
  • Path: /products/batch
  • Headers: Content-Type: application/json, Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

Request Body:

FieldTypeRequiredDescription
idsarray of stringsArray of product IDs to update
dataobjectUpdate data to apply to all products
data.namestringNew product name
data.descriptionstringNew product description

Response Body:

FieldTypeDescription
idstringUnique product identifier
namestringUpdated product name
descriptionstringUpdated product description
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Enforced automatically (ids array and data object required)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X PATCH {{host}}/products/batch \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"ids": [
"7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"8fec096b-1bc7-5bfe-c827-3600e8fe2790"
],
"data": {
"description": "Updated batch description"
}
}'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

[
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"name": "Product A",
"description": "Updated batch description",
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T15:45:12.789Z"
},
{
"id": "8fec096b-1bc7-5bfe-c827-3600e8fe2790",
"name": "Product B",
"description": "Updated batch description",
"createdAt": "2024-05-28T09:41:23.123Z",
"updatedAt": "2024-05-28T15:45:12.789Z"
}
]

11. Delete Multiple Products

Deletes multiple products in a single request.

Request:

  • Method: DELETE
  • Path: /products/batch
  • Headers: Content-Type: application/json, Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

Request Body: Array of product IDs to delete.

Response Body:

FieldTypeDescription
No response body-Delete endpoint returns no response body on success

Validation:

  • Schema Validation: Enforced automatically (array of strings)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X DELETE {{host}}/products/batch \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '[
"7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"8fec096b-1bc7-5bfe-c827-3600e8fe2790"
]'

Success Response:

HTTP/1.1 204 No Content

12. Copy Multiple Products

Creates copies of multiple products in a single request.

Request:

  • Method: POST
  • Path: /products/batch/copy
  • Headers: Content-Type: application/json, Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

Request Body: Array of product IDs to copy.

Response Body:

FieldTypeDescription
idstringUnique identifier for the copied product
namestringProduct name (copied from original)
descriptionstringProduct description (copied from original)
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Enforced automatically (array of strings)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X POST {{host}}/products/batch/copy \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '[
"7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"8fec096b-1bc7-5bfe-c827-3600e8fe2790"
]'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

[
{
"id": "9abc123f-1cd8-4def-b123-456789abcdef",
"name": "Product A",
"description": "Description for Product A",
"createdAt": "2024-05-28T16:00:00.000Z",
"updatedAt": "2024-05-28T16:00:00.000Z"
},
{
"id": "def456a1-2e3f-4567-8901-23456789bcde",
"name": "Product B",
"description": "Description for Product B",
"createdAt": "2024-05-28T16:00:00.100Z",
"updatedAt": "2024-05-28T16:00:00.100Z"
}
]

13. Get Product Image Upload URL

Generates a pre-signed URL for securely uploading a product image. Returns an object ID and a temporary signed URL.

Request:

  • Method: GET
  • Path: /products/:productId/image-upload-url
  • Headers: Authorization: Bearer <token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringTarget product ID

Query Parameters:

ParameterTypeRequiredDescription
contentTypestringImage MIME type (e.g., image/png)
contentLengthnumberFile size in bytes (max 10MB)

Response Body:

FieldTypeDescription
objectIdstringGenerated storage object ID for the product image
urlstringPre-signed URL for uploading the file

Validation:

  • Schema Validation: Uses image upload schema (content type and size constraints)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl "{{host}}/products/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/image-upload-url?contentType=image/webp&contentLength=2097152" \
-H "Authorization: Bearer <access-token>"

Success Response:

{
"objectId": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"url": "https://storage.googleapis.com/bucket/products/...&X-Goog-Expires=900&X-Goog-Signature=..."
}

14. Create Product Image

Creates a product image entry after uploading the file to cloud storage.

Request:

  • Method: POST
  • Path: /products/:productId/images
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringTarget product ID

Request Body:

FieldTypeRequiredDescription
objectIdstringStorage object ID from upload URL
typestringImage type/category

Example Request:

curl -X POST "{{host}}/products/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/images" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"objectId": "image-uuid-123",
"type": "product-image"
}'

15. Delete Product Image

Removes a product image and deletes the file from cloud storage.

Request:

  • Method: DELETE
  • Path: /products/:productId/images/:imageId
  • Headers: Authorization: Bearer <token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringTarget product ID
imageIdstringImage ID to delete

Example Request:

curl -X DELETE "{{host}}/products/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/images/image-uuid-123" \
-H "Authorization: Bearer <access-token>"

16. Create Product Variant

Creates a new variant for an existing product.

Request:

  • Method: POST
  • Path: /products/:productId/variants
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringParent product ID

Request Body:

FieldTypeRequiredDescription
titlestringProduct variant title
descriptionstringVariant description
skustringStock keeping unit identifier
imageIdsarray of stringsArray of image identifiers associated with the variant
priceobjectPricing details (see below)

Price Object:

FieldTypeRequiredDescription
amountnumberPrice amount
currencystringISO currency code
taxIncludedbooleanWhether tax is included in amount
taxablebooleanWhether the variant is taxable

Response Body:

FieldTypeDescription
idstringUnique variant identifier
productIdstringParent product ID
titlestringVariant title
descriptionstringVariant description
skustringStock keeping unit
imageIdsarrayArray of image IDs
priceobjectPricing information
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Request body requires title; all other fields optional
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X POST "{{host}}/products/product-123/variants" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"title": "Large Size",
"description": "Large variant of the product",
"sku": "PROD-LG-001",
"price": {
"amount": 29.99,
"currency": "USD",
"taxIncluded": false,
"taxable": true
}
}'

Success Response:

HTTP/1.1 201 Created
Content-Type: application/json

{
"id": "variant-456",
"productId": "product-123",
"title": "Large Size",
"description": "Large variant of the product",
"sku": "PROD-LG-001",
"price": {
"amount": 29.99,
"currency": "USD",
"taxIncluded": false,
"taxable": true
},
"createdAt": "2025-01-15T10:30:00.000Z",
"updatedAt": "2025-01-15T10:30:00.000Z"
}

17. List Product Variants

Retrieves all variants for a specific product with pagination.

Request:

  • Method: GET
  • Path: /products/:productId/variants
  • Authorization: None required

URL Parameters:

ParameterTypeRequiredDescription
productIdstringParent product ID

Query Parameters:

ParameterTypeRequiredDescription
pagenumberPage number for pagination (1-1000)
limitnumberNumber of results per page (1-50)

Response Body: Paginated response with variants array and metadata.

Response Structure:

{
"data": [
{
"id": "string",
"productId": "string",
"title": "string",
"description": "string",
"sku": "string",
"imageIds": ["string"],
"price": {
"amount": number,
"currency": "string",
"taxIncluded": boolean,
"taxable": boolean
},
"createdAt": "string",
"updatedAt": "string"
}
],
"metadata": {
"pagination": {
"page": number,
"limit": number,
"total": number,
"totalPages": number,
"hasNext": boolean,
"hasPrev": boolean
}
}
}

Validation:

  • Schema Validation: Path parameter validation and pagination query parameters
  • Route Validators: None

Example Request:

curl "{{host}}/products/product-123/variants?page=1&limit=20"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"data": [
{
"id": "variant-456",
"productId": "product-123",
"title": "Large Size",
"description": "Large variant",
"sku": "PROD-LG-001",
"imageIds": [],
"price": {
"amount": 29.99,
"currency": "USD",
"taxIncluded": false,
"taxable": true
},
"createdAt": "2025-01-15T10:30:00.000Z",
"updatedAt": "2025-01-15T10:30:00.000Z"
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 20,
"total": 5,
"totalPages": 1,
"hasNext": false,
"hasPrev": false
}
}
}

18. Get Product Variant

Retrieves a specific product variant by ID.

Request:

  • Method: GET
  • Path: /products/:productId/variants/:productVariantId
  • Headers: Authorization: Bearer <token>
  • Authorization: Bearer token required

URL Parameters:

ParameterTypeRequiredDescription
productIdstringParent product ID
productVariantIdstringVariant ID

Response Body:

FieldTypeDescription
idstringUnique variant identifier
productIdstringParent product ID
titlestringVariant title
descriptionstringVariant description
skustringStock keeping unit
imageIdsarrayArray of image IDs
priceobjectPricing information
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Path parameter validation (productId and productVariantId required)
  • Route Validators:
    • Require authenticated request (bearer token)

Example Request:

curl "{{host}}/products/product-123/variants/variant-456" \
-H "Authorization: Bearer <access-token>"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"id": "variant-456",
"productId": "product-123",
"title": "Large Size",
"description": "Large variant of the product",
"sku": "PROD-LG-001",
"imageIds": [],
"price": {
"amount": 29.99,
"currency": "USD",
"taxIncluded": false,
"taxable": true
},
"createdAt": "2025-01-15T10:30:00.000Z",
"updatedAt": "2025-01-15T10:30:00.000Z"
}

Error Responses:

  • 401 Unauthorized: Authentication failed
  • 404 Not Found: Product variant not found
  • 500 Internal Server Error: Database operation failed

19. Update Product Variant

Updates an existing product variant with partial data.

Request:

  • Method: PATCH
  • Path: /products/:productId/variants/:productVariantId
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringParent product ID
productVariantIdstringVariant ID to update

Request Body (all fields optional):

FieldTypeRequiredDescription
titlestringProduct variant title
descriptionstringVariant description
skustringStock keeping unit identifier
imageIdsarray of stringsArray of image identifiers associated with the variant
priceobjectPricing details (see below)

Price Object (all fields optional):

FieldTypeRequiredDescription
amountnumberPrice amount
currencystringISO currency code
taxIncludedbooleanWhether tax is included in amount
taxablebooleanWhether the variant is taxable

Response Body:

FieldTypeDescription
idstringUnique variant identifier
productIdstringParent product ID
titlestringUpdated variant title
descriptionstringUpdated variant description
skustringUpdated stock keeping unit
imageIdsarrayUpdated array of image IDs
priceobjectUpdated pricing information
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: All fields optional; no additional properties allowed
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X PATCH "{{host}}/products/product-123/variants/variant-456" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"price": {
"amount": 34.99,
"currency": "USD"
}
}'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"id": "variant-456",
"productId": "product-123",
"title": "Large Size",
"description": "Large variant of the product",
"sku": "PROD-LG-001",
"imageIds": [],
"price": {
"amount": 34.99,
"currency": "USD",
"taxIncluded": false,
"taxable": true
},
"createdAt": "2025-01-15T10:30:00.000Z",
"updatedAt": "2025-01-15T14:22:15.789Z"
}

Error Responses:

  • 401 Unauthorized: Authentication failed
  • 403 Forbidden: Non-admin user attempting to update variant
  • 404 Not Found: Product variant not found
  • 500 Internal Server Error: Database operation failed

20. Delete Product Variant

Removes a product variant.

Request:

  • Method: DELETE
  • Path: /products/:productId/variants/:productVariantId
  • Headers: Authorization: Bearer <token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringParent product ID
productVariantIdstringVariant ID to delete

Response Body: No response body (204 No Content)

Validation:

  • Schema Validation: Path parameter validation (productId and productVariantId required)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X DELETE "{{host}}/products/product-123/variants/variant-456" \
-H "Authorization: Bearer <access-token>"

Success Response:

HTTP/1.1 204 No Content

Error Responses:

  • 401 Unauthorized: Authentication failed
  • 403 Forbidden: Non-admin user attempting to delete variant
  • 500 Internal Server Error: Database operation failed

21. Create Product Variants in Bulk

Creates multiple product variants at once (1-100 variants per request).

Request:

  • Method: POST
  • Path: /product/:productId/variants/bulk
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringParent product ID

Request Body: Array of variant objects (1-100 items), each requiring title.

FieldTypeRequiredDescription
titlestringProduct variant title
descriptionstringVariant description
skustringStock keeping unit identifier
imageIdsarray of stringsArray of image identifiers
priceobjectPricing details

Response Body: Array of created variant objects.

Validation:

  • Schema Validation: Array of variant objects (1-100 items), each requires title
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X POST "{{host}}/product/product-123/variants/bulk" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '[
{
"title": "Small Size",
"sku": "PROD-SM-001",
"price": {
"amount": 19.99,
"currency": "USD"
}
},
{
"title": "Medium Size",
"sku": "PROD-MD-001",
"price": {
"amount": 24.99,
"currency": "USD"
}
}
]'

Success Response:

HTTP/1.1 201 Created
Content-Type: application/json

[
{
"id": "variant-789",
"productId": "product-123",
"title": "Small Size",
"sku": "PROD-SM-001",
"createdAt": "2025-01-15T10:30:00.000Z",
"updatedAt": "2025-01-15T10:30:00.000Z"
},
{
"id": "variant-790",
"productId": "product-123",
"title": "Medium Size",
"sku": "PROD-MD-001",
"createdAt": "2025-01-15T10:30:00.100Z",
"updatedAt": "2025-01-15T10:30:00.100Z"
}
]

22. Update Product Variants in Bulk

Updates multiple product variants at once with the same data (1-100 variants per request).

Request:

  • Method: PATCH
  • Path: /product/:productId/variants/bulk
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringParent product ID

Request Body:

FieldTypeRequiredDescription
idsarray of stringsArray of variant IDs to update (1-100 items)
dataobjectUpdate data to apply to all variants (see below)

Data Object (all fields optional):

FieldTypeRequiredDescription
titlestringProduct variant title
descriptionstringVariant description
skustringStock keeping unit identifier
imageIdsarray of stringsArray of image identifiers
priceobjectPricing details

Response Body: Array of updated variant objects.

Validation:

  • Schema Validation: ids array (1-100 items) and data object required
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X PATCH "{{host}}/product/product-123/variants/bulk" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"ids": ["variant-456", "variant-789"],
"data": {
"price": {
"amount": 29.99,
"currency": "USD"
}
}
}'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

[
{
"id": "variant-456",
"productId": "product-123",
"title": "Large Size",
"price": {
"amount": 29.99,
"currency": "USD"
},
"updatedAt": "2025-01-15T14:22:15.789Z"
},
{
"id": "variant-789",
"productId": "product-123",
"title": "Small Size",
"price": {
"amount": 29.99,
"currency": "USD"
},
"updatedAt": "2025-01-15T14:22:15.789Z"
}
]

Error Responses:

  • 401 Unauthorized: Authentication failed
  • 403 Forbidden: Non-admin user attempting to update variants
  • 404 Not Found: One or more product variants not found
  • 500 Internal Server Error: Database operation failed

23. Delete Product Variants in Bulk

Deletes multiple product variants at once (1-100 variants per request).

Request:

  • Method: POST
  • Path: /product/:productId/variants/bulk-delete
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringParent product ID

Request Body: Array of variant IDs to delete (1-100 items).

Response Body: No response body (204 No Content)

Validation:

  • Schema Validation: Array of variant ID strings (1-100 items)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X POST "{{host}}/product/product-123/variants/bulk-delete" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '["variant-456", "variant-789"]'

Success Response:

HTTP/1.1 204 No Content

Error Responses:

  • 401 Unauthorized: Authentication failed
  • 403 Forbidden: Non-admin user attempting to delete variants
  • 500 Internal Server Error: Database operation failed

⚙️ Configuration Options

Service Configuration

interface ProductServiceConfiguration {
authSecrets: {
authEncSecret: string; // JWT encryption secret
authSignSecret: string; // JWT signing secret
};
identity?: {
typeIds?: {
admin: string; // Admin user type identifier
guest: string; // Guest user type identifier
regular: string; // Regular user type identifier
};
};
}

Configuration Details

The product service configuration is organized into logical groups for security and user type management.

🔐 Security Settings

authSecrets - JWT token security secrets

  • Type: { authEncSecret: string; authSignSecret: string }
  • Description: Secret keys for JWT encryption and signing (used for token validation)
  • Required: Yes (for production)
  • Child Properties:
    • authEncSecret: Secret key for JWT payload encryption
    • authSignSecret: Secret key for JWT signature verification

👥 User Type Settings

identity.typeIds - User type identifier configuration

  • Type: { admin?: string; guest?: string; regular?: string }
  • Description: Custom user type identifiers for role-based access control
  • Default: undefined (uses default type validation)
  • Child Properties:
    • admin: Admin user type identifier
      • Type: string
      • Description: Custom identifier for admin users
      • Use Case: Role-based access control for administrative operations
      • Example: "admin", "administrator", "superuser"
    • guest: Guest user type identifier
      • Type: string
      • Description: Custom identifier for guest users
      • Use Case: Limited access for unauthenticated or temporary users
      • Example: "guest", "visitor", "anonymous"
    • regular: Regular user type identifier
      • Type: string
      • Description: Custom identifier for regular users
      • Use Case: Standard user access permissions
      • Example: "user", "member", "customer"

Example Configuration

const productConfig = {
authSecrets: {
authEncSecret: process.env.AUTH_ENC_SECRET || 'your-enc-secret',
authSignSecret: process.env.AUTH_SIGN_SECRET || 'your-sign-secret'
},
identity: {
typeIds: {
admin: '100',
guest: '000',
regular: '001'
}
}
};

🚨 Error Handling

All product service errors return JSON format with appropriate HTTP status codes:

Common Error Codes

StatusError MessageDescription
400Validation ErrorInvalid request body format or missing required fields
400Failed to create productDatabase insert operation failed to return an inserted ID
400Failed to update productUpdate operation doesn't modify any data (no changes detected)
400Failed to create productsBatch creation operation failed
400Failed to update productsBatch update operation failed
400Failed to delete productsBatch deletion operation failed
400Failed to copy productProduct copy operation failed
400Failed to copy productsBatch copy operation failed
401token could not be verifiedMissing or invalid authorization token
403User is not authorized to access this resourceUser lacks required permissions (admin access)
404Product not foundProduct doesn't exist for the requested operation
500Failed to create productDatabase connection issues or unexpected failures during creation
500Failed to get productDatabase connection issues or unexpected failures during retrieval
500Failed to find productsDatabase connection issues, invalid filter syntax, or unexpected failures during listing
500Failed to update productDatabase connection issues or unexpected failures during update
500Failed to delete productDatabase connection issues or unexpected failures during deletion
500Failed to copy productDatabase connection issues or unexpected failures during copying

Error Response Format

{
"error": {
"message": "Error message description",
"data": ["Additional error details"]
}
}

Validation Errors include additional details:

{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'name'",
"request body must have required property 'description'"
]
}
}