Products API
The Products API is designed to manage product data efficiently within an e-commerce environment. It supports product creation, modification, and deletion while handling pricing details, stock information, recurrence settings, taxes, and image management.
The API ensures clear and consistent responses, including detailed error handling and support for multiple currencies with proper precision validation.
Create a product¶
Endpoint
POST /v1/products/
This endpoint allows creating a new product in the system by sending a POST request with the product details — such as name, description, price, currency, stock, taxes, images, and recurrence settings.
Query Parameters:
| Parameter | Description | Type | Required |
|---|---|---|---|
| test | Indicates if the product is in test mode | boolean | false |
Request Body Fields:
| Parameter | Description | Type | Required |
|---|---|---|---|
| name | Product name (max 50 characters) | string | true |
| short_description | Brief product description (max 100 characters) | string | false |
| description | Detailed product description (max 300 characters) | string | false |
| price | Product price (validated by currency) | decimal | true |
| currency | Currency code (USD, EUR, CRC, etc.) | string | false |
| stock | Number of items in stock | integer | false |
| is_physical | Whether product is physical (true/false) | boolean | false |
| bar_code | Product barcode | string | false |
| sku | Stock keeping unit | string | false |
| taxes | Comma-separated tax IDs | string | false |
| recurrence | Recurrence settings (JSON object) | object | false |
Recurrence Object Format:
{
"recurrence": "period", // or "specific_billing_day"
"duration_period": 1 // Valid: 1, 2, 3, 4, 6, 12 (months)
}
Or:
File Upload Parameters:
| Parameter | Description | Type | Required |
|---|---|---|---|
| image_default | Default product image (file) | file | false |
| images | Additional product images (max 4) | file | false |
Request:
curl -X POST 'http://127.0.0.1:8000/v1/products/?test=false' \
-u 'sk_test_51O62xYzAbcDef123:' \
-F 'name=Premium Widget' \
-F 'description=This is a premium widget product' \
-F 'price=99.99' \
-F 'currency=USD' \
-F 'stock=50' \
-F 'is_physical=true' \
-F 'taxes=1,3' \
-F 'sku=PREMIUM-WIDGET-001' \
-F 'image_default=@/path/to/image.jpg' \
-F 'recurrence={"recurrence":"period","duration_period":3}'
Response (201 Created):
{
"code": 201,
"title": "Complete registration",
"content": "The registration was successfully completed.",
"type": "success",
"data": {
"id": "d36a4a5c-9fa9-4d55-b47f-4f1d50f2a180"
}
}
Get all products¶
Endpoint
GET /v1/products/
This endpoint retrieves a paginated list of all products with advanced filtering support. Supports pagination, search, filtering by type, price range, and stock levels.
Query Parameters:
| Parameter | Description | Type | Required |
|---|---|---|---|
| page | The page number to retrieve (default: 1) | integer | false |
| page_size | Products per page (default: 10, max: 100) | integer | false |
| test | Filter by test mode (true/false) | boolean | false |
| search | Search by name or SKU | string | false |
| type | Filter by type (physical/digital) | string | false |
| stock_min | Minimum stock level | integer | false |
| stock_max | Maximum stock level | integer | false |
| price_min | Minimum price (in product currency) | decimal | false |
| price_max | Maximum price (in product currency) | decimal | false |
Request:
curl -X GET 'http://127.0.0.1:8000/v1/products/?page=1&page_size=10&test=false' \
-u 'sk_test_51O62xYzAbcDef123:'
Request (With Filters):
curl -X GET 'http://127.0.0.1:8000/v1/products/?page=1&search=widget&type=physical&price_min=10&price_max=100&stock_min=5' \
-u 'sk_test_51O62xYzAbcDef123:'
Response (200 OK):
{
"count": 25,
"current_page": 1,
"total_pages": 3,
"results": [
{
"id": "a232cccc-956a-44ca-a2e8-d763afddc89f",
"name": "Premium Widget",
"short_description": "High-quality widget",
"description": "This is a premium widget product with advanced features",
"stock": 50,
"price": "99.99",
"currency": "USD",
"total_price": "109.99",
"is_physical": true,
"bar_code": "123456789012",
"sku": "PREMIUM-WIDGET-001",
"recurrence": {
"recurrence": "period",
"duration_period": 3
},
"images": {
"default": "https://storage.googleapis.com/bucket/image-default.jpg",
"additional_images": [
{"image": "https://storage.googleapis.com/bucket/image-1.jpg"},
{"image": "https://storage.googleapis.com/bucket/image-2.jpg"}
]
},
"payment_link": false,
"created_on": "2025-12-04T10:30:00Z",
"test": false,
"taxes": [
{"id": 1, "name": "VAT", "value": 10.0}
]
}
]
}
Get a specific product¶
Endpoint
GET /v1/products/{id}/
This endpoint retrieves complete details of a specific product by its unique ID.
Path Parameters:
| Parameter | Description | Type | Required |
|---|---|---|---|
| id | The unique identifier of a product (UUID) | string | true |
Query Parameters:
| Parameter | Description | Type | Required |
|---|---|---|---|
| test | Filter by test mode (true/false) | boolean | false |
Request:
curl -X GET 'http://127.0.0.1:8000/v1/products/f9b77185-a62e-4da9-a056-3c7b812ca334/?test=false' \
-u 'sk_test_51O62xYzAbcDef123:'
Response (200 OK):
{
"id": "f9b77185-a62e-4da9-a056-3c7b812ca334",
"name": "Premium Widget",
"short_description": "High-quality widget",
"description": "This is a premium widget product with advanced features",
"stock": 50,
"price": "99.99",
"currency": "USD",
"total_price": "109.99",
"is_physical": true,
"bar_code": "123456789012",
"sku": "PREMIUM-WIDGET-001",
"recurrence": {
"recurrence": "period",
"duration_period": 3
},
"images": {
"default": "https://storage.googleapis.com/bucket/image-default.jpg",
"additional_images": [
{"image": "https://storage.googleapis.com/bucket/image-1.jpg"},
{"image": "https://storage.googleapis.com/bucket/image-2.jpg"}
]
},
"payment_link": false,
"created_on": "2025-12-04T10:30:00Z",
"test": false,
"taxes": [
{"id": 1, "name": "VAT", "value": 10.0}
]
}
Update a product¶
Endpoint
PUT /v1/products/{id}/
Updates an existing product with new details. You can update individual fields without affecting others.
Path Parameters:
| Parameter | Description | Type | Required |
|---|---|---|---|
| id | The unique identifier of a product (UUID) | string | true |
Query Parameters:
| Parameter | Description | Type | Required |
|---|---|---|---|
| test | Filter by test mode (true/false) | boolean | false |
Request Body Fields (all optional):
| Parameter | Description | Type |
|---|---|---|
| name | Product name (max 50 characters) | string |
| short_description | Brief product description (max 100 characters) | string |
| description | Detailed product description (max 300 characters) | string |
| price | Product price (validated by currency) | decimal |
| currency | Currency code (USD, EUR, CRC, etc.) | string |
| stock | Number of items in stock | integer |
| is_physical | Whether product is physical (true/false) | boolean |
| bar_code | Product barcode | string |
| sku | Stock keeping unit | string |
| taxes | Comma-separated tax IDs | string |
| payment_link | Enable as payment link | boolean |
Image Management Flags:
| Parameter | Value | Action |
|---|---|---|
| default | -1 | Keep existing default image |
| default | -remove- | Remove default image |
| default | <file> | Replace with new image |
| additional_images | -1 | Keep existing additional images |
| additional_images | -remove- | Remove all additional images |
| additional_images | <files> | Replace with new images (max 4) |
Request:
curl -X PUT 'http://127.0.0.1:8000/v1/products/f9b77185-a62e-4da9-a056-3c7b812ca334/?test=false' \
-u 'sk_test_51O62xYzAbcDef123:' \
-F 'name=Updated Widget Name' \
-F 'description=Updated description' \
-F 'price=79.99' \
-F 'stock=100' \
-F 'default=-1'
Response (200 OK):
{
"code": 200,
"title": "Updated product",
"content": "The product was successfully updated.",
"type": "success",
"data": {
"id": "f9b77185-a62e-4da9-a056-3c7b812ca334",
"name": "Updated Widget Name",
"description": "Updated description",
"price": "79.99",
"stock": 100,
"total_price": "87.99"
}
}
Delete a product¶
Endpoint
DELETE /v1/products/{id}/
Permanently deletes a product and deactivates it in Stripe.
Path Parameters:
| Parameter | Description | Type | Required |
|---|---|---|---|
| id | The unique identifier of a product (UUID) | string | true |
Query Parameters:
| Parameter | Description | Type | Required |
|---|---|---|---|
| test | Filter by test mode (true/false) | boolean | false |
Request:
curl -X DELETE 'http://127.0.0.1:8000/v1/products/f9b77185-a62e-4da9-a056-3c7b812ca334/?test=false' \
-u 'sk_test_51O62xYzAbcDef123:'
Response (200 OK):
{
"code": 200,
"title": "Product deleted",
"content": "The product was successfully deleted.",
"type": "success"
}
Error Handling¶
The API returns standard HTTP status codes to indicate the success or failure of a request. Below are common errors specific to products:
400 Bad Request¶
Occurs when the request is malformed or has invalid data.
Scenarios:
| Scenario | Error Message | Solution |
|---|---|---|
| Invalid price format | "Price validation error: {message}" | Verify price precision for currency (e.g., JPY uses 0 decimals) |
| Invalid recurrence JSON | "Please check the format of recurrence, remember that it is a JSON object." | Ensure recurrence is valid JSON format |
| Invalid duration period | "The duration_period can contain only the following values 1, 2, 3, 4, 6, 12" | Use valid month durations: 1, 2, 3, 4, 6, or 12 |
| Invalid payday | "The payday has to be greater than 0 and less than or equal to 28." | Use day between 1-28 |
Example Error Response:
{
"code": 400,
"title": "Invalid price format",
"content": "Price validation error: JPY requires 0 decimal places. Please adjust the price according to the currency requirements.",
"type": "danger"
}
401 Unauthorized¶
Authentication failed. API Key is invalid, missing, or malformed.
Example:
Solution: - Verify you included the -u 'sk_test_...: parameter or Authorization: Basic header - Ensure your API Key is correct and active - Test with Postman using Basic Auth
404 Not Found¶
The requested product does not exist.
Example:
{
"code": 404,
"title": "Product does not exist",
"content": "The id 'f9b77185-a62e-4da9-a056-3c7b812ca334' does not correspond to any product",
"type": "danger"
}
Solution: - Verify the product ID exists - Use the list endpoint to find the correct product ID - Ensure the product belongs to your developer account
406 Not Acceptable¶
The request violates business rules or validation constraints.
Example:
{
"code": 406,
"title": "Product registration failure",
"content": "Failed to register the product, please check: Invalid field values",
"type": "danger"
}
Important Notes¶
Price Validation
- Prices are validated based on currency decimal places
- JPY, CLP, and similar currencies use 0 decimal places
- USD, EUR, GBP use 2 decimal places
- KWD and similar currencies use 3 decimal places
Image Management
- Default image: Displayed as primary product image
- Additional images: Up to 4 supplementary images supported
- Supported formats: JPEG, PNG
- Maximum file size: 10MB per image
- Use special flags (
-1,-remove-) to manage existing images
Taxes
- Products can have multiple taxes applied
- Total price includes tax calculations
- Taxes are linked by their IDs
- Send comma-separated tax IDs:
"taxes": "1,3,5"
Recurrence Settings
period: Fixed monthly recurrence (1, 2, 3, 4, 6, or 12 months)specific_billing_day: Monthly on a specific day (1-28)- These settings apply when product is used in subscriptions
Test vs Production
- Use your Test Key (
sk_test_...) for development and testing - Use your Live Key (
sk_live_...) for real transactions - Query parameter
?test=trueor?test=falsecontrols the mode - The system automatically detects the mode based on the API Key used
Best Practices¶
- Validate prices carefully - Ensure prices match currency decimal place requirements
- Use descriptive names - Help customers understand products clearly
- Set accurate stock - Keep inventory counts updated
- Add images - Product images increase conversion rates
- Use SKUs - Unique SKUs help with inventory management
- Apply taxes correctly - Include all applicable tax IDs
- Test before production - Use test mode with test API keys for validation
- Use recurrence wisely - Only set recurrence for subscription-eligible products
Troubleshooting¶
Problem: “Price validation error: JPY requires 0 decimal places”¶
Cause: Using decimal places not supported by currency
Solution: - JPY: Use whole numbers (no decimals) - USD/EUR: Use 2 decimal places (99.99) - KWD: Use 3 decimal places (99.999)
Problem: “The duration_period can contain only the following values 1, 2, 3, 4, 6, 12”¶
Cause: Invalid recurrence period provided
Solution: - Use only: 1 (monthly), 2 (bimonthly), 3 (quarterly), 4 (4-monthly), 6 (semi-annual), or 12 (annual)
Problem: “The payday has to be greater than 0 and less than or equal to 28”¶
Cause: Invalid billing day provided
Solution: - Payday must be between 1 and 28 - Days 29-31 not supported to ensure monthly consistency
Problem: “Product does not exist”¶
Cause: Product ID doesn’t exist or belongs to different developer account
Solution: - Verify the product ID using the list endpoint - Ensure you’re using the correct API Key - Check the product hasn’t been deleted
Problem: “The specified state is invalid”¶
Cause: Invalid product type or filter value
Solution: - Use valid type values: “physical” or “digital” - Ensure filter parameters are properly formatted
FAQ¶
Q: Can I update only specific fields without affecting others?
A: Yes, send only the fields you want to update. Omitted fields retain their current values.
Q: How many images can I add to a product?
A: You can have 1 default image and up to 4 additional images (5 total).
Q: What currencies are supported?
A: Any currency supported by Stripe (USD, EUR, GBP, CRC, JPY, KWD, etc.). Verify decimal place requirements per currency.
Q: Can I apply multiple taxes to a product?
A: Yes, provide comma-separated tax IDs to apply multiple taxes.
Q: What happens when I delete a product?
A: The product is soft-deleted in our system and deactivated in Stripe. Historical payment links referencing it remain available.
Q: How do I use products with payment links?
A: Create the product first, then reference its ID when creating payment links. The product price and details are used for the transaction.
Q: Can I change a product’s currency after creation?
A: Yes, you can update the currency. Prices will be validated against the new currency’s decimal place requirements.
Q: What are recurrence settings used for?
A: Recurrence settings define how products are billed if used in subscriptions. They’re not required for one-time purchases.