Update Product Variant
Update an existing product variant in your 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 after purchase, relative-expiry mode (min 1). Set to null for unlimited. |
access_until | string | Fixed access-expiry date (ISO 8601), fixed-expiry mode. Setting it also ends the sale window (active_until is set to the same date). Set to null to clear. |
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 minor units 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 100 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,
"currency": "usd",
"checkout_url": "https://cart.easy.tools/checkout/premium-coffee?plan=price_123",
"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",
"access_until": null,
"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,
"currency": "usd",
"checkout_url": "https://cart.easy.tools/checkout/premium-coffee?plan=price_456",
"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,
"access_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 e1b6d3f8-7c2a-4f9e-b4d1-6a8c3e7b2f50 not found"
}
Validation Error (422 Unprocessable Entity)
{
"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
- Immutable fields:
amount,type,interval,interval_count, andtax_behaviorcannot be changed after creation and are not accepted in the request body. - Access expiry:
active_days(relative — N days after purchase) andaccess_until(fixed calendar date) are the two access-expiry modes. Settingaccess_untilalso ends the sale window —active_untilis set to the same date. If both are set,access_untiltakes precedence at fulfilment.