Update Product Variant
Update an existing product variant in your easycart store. This endpoint uses PATCH semantics, meaning only the fields you include in the request body will be updated.
Request
PATCH /product-variants/{id}
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Product variant UUID |
Request Body
All fields are optional. Only include the fields you want to update.
| Parameter | Type | Description |
|---|---|---|
name | string | Variant display name (max 255 characters). Set to null to clear. |
custom_id | string | External identifier for integration with other systems (max 255 characters). Set to null to clear. |
is_hidden | boolean | Hide variant from checkout page |
trial_period_days | integer | Trial period in days before first charge (recurring variants only, min 0). Set to null to disable. |
active_cycles | integer | Number of billing cycles for payment plans (min 1). Set to null for unlimited. |
cancel_early | boolean | Allow customers to cancel subscription before active_cycles complete |
keep_access_after_expiring | boolean | Keep access to content after subscription ends |
allow_multiple_subscriptions | boolean | Allow customers to have multiple concurrent subscriptions |
active_days | integer | Access duration in days for time-limited access (min 1). Set to null for unlimited. |
quantity | integer | Available inventory limit (min 0). Set to null for unlimited. |
has_quantity | boolean | Enable quantity selector on checkout page |
old_price | integer | Strike-through price in cents to show original price (min 0). Set to null to hide. |
active_from | string | Start selling date (ISO 8601 format). Set to null to clear. |
active_until | string | Stop selling date (ISO 8601 format). Set to null to clear. |
show_active_until_counter | boolean | Show countdown timer on checkout page |
refund_days | integer | Refund period in days, overrides product setting (min 0). Set to null to use product default. |
redirect_url | string | Post-purchase redirect URL, overrides product setting (max 1000 characters). Set to null to use product default. |
redirect_time | integer | Redirect delay in seconds (min 0). Set to null to use product default. |
file | object | Single variant-specific downloadable file, overrides product files. Legacy shortcut equivalent to files: [file]. Set to null to remove. See File Object. |
files | array | Up to 5 variant-specific downloadable files, overriding the product's files. Each entry is a File Object. When provided, this supersedes file and replaces the variant's entire file set. Send [] to remove all variant files (falls back to the product's files). |
invoice_remarks | string | Additional notes to include on invoices (max 250 characters). Set to null to clear. |
File Object
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name shown in the customer portal (max 255 characters) |
url | string | Yes | External URL to download the file (max 2048 characters) |
A variant can have up to 5 downloadable files. Variant files override the product's files: when a variant has any files, customers see only the variant's files; when it has none, they fall back to the product's files. Updating files (or the legacy file) replaces the variant's entire set.
Example Requests
Update variant name and custom ID:
curl -X PATCH "https://cart.easy.tools/api/v1/product-variants/550e8400-e29b-41d4-a716-446655440002" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Premium Package",
"custom_id": "SKU-PREMIUM-001"
}'
Update availability settings with sale pricing:
curl -X PATCH "https://cart.easy.tools/api/v1/product-variants/550e8400-e29b-41d4-a716-446655440002" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"active_from": "2026-02-01T00:00:00Z",
"active_until": "2026-03-01T00:00:00Z",
"show_active_until_counter": true,
"old_price": 2999
}'
Update subscription settings:
curl -X PATCH "https://cart.easy.tools/api/v1/product-variants/550e8400-e29b-41d4-a716-446655440003" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"trial_period_days": 14,
"active_cycles": 12,
"cancel_early": true,
"keep_access_after_expiring": false
}'
Update file attachment:
curl -X PATCH "https://cart.easy.tools/api/v1/product-variants/550e8400-e29b-41d4-a716-446655440002" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"file": {
"name": "Premium Ebook.pdf",
"url": "https://mysite.com/files/premium-ebook.pdf"
}
}'
Attach multiple variant-specific files:
curl -X PATCH "https://cart.easy.tools/api/v1/product-variants/550e8400-e29b-41d4-a716-446655440002" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"files": [
{ "name": "Premium Ebook.pdf", "url": "https://mysite.com/files/premium-ebook.pdf" },
{ "name": "Workbook.pdf", "url": "https://mysite.com/files/workbook.pdf" }
]
}'
Response
Success Response (200)
Returns the updated product variant with all fields.
{
"id": "550e8400-e29b-41d4-a716-446655440002",
"type": "one_time",
"recurring_options": null,
"name": "Premium Package",
"amount": 1999,
"custom_id": "SKU-PREMIUM-001",
"is_hidden": false,
"trial_period_days": null,
"active_cycles": null,
"cancel_early": false,
"keep_access_after_expiring": false,
"allow_multiple_subscriptions": false,
"active_days": null,
"quantity": null,
"has_quantity": false,
"old_price": 2999,
"active_from": "2026-02-01T00:00:00+00:00",
"active_until": "2026-03-01T00:00:00+00:00",
"show_active_until_counter": true,
"tax_behavior": "exclusive",
"refund_days": null,
"redirect_url": null,
"redirect_time": null,
"file": {
"name": "Premium Ebook.pdf",
"url": "https://mysite.com/files/premium-ebook.pdf"
},
"files": [
{
"name": "Premium Ebook.pdf",
"url": "https://mysite.com/files/premium-ebook.pdf"
},
{
"name": "Workbook.pdf",
"url": "https://mysite.com/files/workbook.pdf"
}
],
"invoice_remarks": null
}
{
"id": "550e8400-e29b-41d4-a716-446655440003",
"type": "recurring",
"recurring_options": {
"interval": "month",
"interval_count": 1
},
"name": "Monthly Subscription - 250g",
"amount": 1799,
"custom_id": null,
"is_hidden": false,
"trial_period_days": 14,
"active_cycles": 12,
"cancel_early": true,
"keep_access_after_expiring": false,
"allow_multiple_subscriptions": false,
"active_days": null,
"quantity": null,
"has_quantity": false,
"old_price": null,
"active_from": null,
"active_until": null,
"show_active_until_counter": null,
"tax_behavior": "exclusive",
"refund_days": null,
"redirect_url": null,
"redirect_time": null,
"file": null,
"files": [],
"invoice_remarks": null
}
Response Fields
See Get Product Variant for a complete list of response fields.
Error Responses
Bad Request (400)
{
"message": "Invalid product variant ID"
}
Product Variant Not Found (404)
{
"message": "Product variant with ID <UUID> not found"
}
Validation Error (422)
{
"message": "The given data was invalid.",
"errors": {
"active_until": [
"The active until field must be a date after or equal to active from."
]
}
}
{
"message": "The given data was invalid.",
"errors": {
"redirect_url": [
"The redirect url field must be a valid URL."
],
"file.url": [
"The file.url field must be a valid URL."
]
}
}
Notes
- PATCH semantics: Only fields included in the request body are updated. Omitted fields remain unchanged.
- Null values: Setting a field to
nullwill clear its value (where applicable). - Immutable fields: The following fields cannot be changed after creation and are not accepted in the request body:
amount- Price in centstype- Variant type (one_time or recurring)interval- Recurring intervalinterval_count- Number of intervals between chargestax_behavior- Tax behavior (inclusive or exclusive)
- Trial period: The
trial_period_daysfield only applies to recurring variants. - Subscription settings: Fields like
active_cycles,cancel_early,keep_access_after_expiring, andallow_multiple_subscriptionsare primarily relevant for recurring variants.