Skip to content

Update a product

The products.update operation: PATCH /api/v1/products/{id} in the REST API and the products_update tool in the MCP server.

PATCH/api/v1/products/{id}

Changes a product's name, description, tax category, kind, entitlements, lifetimeEntitlements, pricing-table hints, images or metadata. Send only the fields to change; null clears an optional value. entitlements, images and metadata replace the whole list or map. Customers' entitlements are recomputed after a change of entitlements or lifetimeEntitlements.

A new tax category applies to future sales; issued invoices keep theirs. active: false archives the product (as products.archive) and active: true reactivates it.

At a glance

  • REST: PATCH /api/v1/products/{id}
  • MCP tool: products_update
  • Operation ID: products.update
  • Scope: Brand
  • Permission: catalog:write
  • Risk tier: write
  • Dry run: Supported (send Ownrecord-Dry-Run: true)
  • Idempotency: Idempotency-Key optional
  • Modes: Test and live
  • Authentication: API key with the catalog:write scope
  • Since: M4

Request

Path parameters

FieldTypeDescription
idprod_… ID

Body

A JSON object (Content-Type: application/json):

FieldTypeRequiredDescription
namestringNo
descriptionstring or nullNo
taxCategoryIdone of 9 values, e.g. electronically_supplied_service, saas, ebook (all in the OpenAPI document)NoThe product's tax category (spec §7.2), e.g. saas or electronically_supplied_service.
kindone of standard, planNoplan products appear on the brand's pricing table; standard ones don't.
entitlementsarray of objectNoFeature values the product grants (spec §36.1), each feature once.
entitlements[].featureKeystringYesThe feature's key, e.g. seats.max.
entitlements[].valueboolean or number or stringYestrue/false for a boolean feature, a whole number for a limit, one of the values for an enum.
lifetimeEntitlementsbooleanNotrue: a one-time purchase grants the entitlements for good. Buyers' entitlements follow.
displayOrderinteger (0 to 10000) or nullNo
highlightedbooleanNo
imagesarray of stringNoImage URLs (https). On updates the whole list is replaced.
metadataobjectNoYour own key-value pairs (at most 50 keys). On updates the whole set is replaced.
activebooleanNofalse archives the product, true reactivates it.

Response

200 OK with a JSON object:

FieldTypeDescription
idprod_… ID
object"product"
brandIdbrd_… ID
livemodeboolean
namestring
descriptionstring or null
taxCategoryIdone of 9 values, e.g. electronically_supplied_service, saas, ebook (all in the OpenAPI document)
kindone of standard, plan
entitlementsarray of object
entitlements[].featureKeystring
entitlements[].valueboolean or number or string
lifetimeEntitlementsbooleanA one-time purchase of the product grants its entitlements for good (spec §36.1).
displayOrderinteger or null
highlightedboolean
activeboolean
imagesarray of string
metadataobject
createdAtdate-time
updatedAtdate-time

Examples

Raise the seat limit

HTTP
PATCH /api/v1/products/prod_01m4tx5nj8emwbyf7y9vcf47y0
Authorization: Bearer or_test_…
Content-Type: application/json

{
  "entitlements": [
    {
      "featureKey": "seats.max",
      "value": 25
    },
    {
      "featureKey": "feature.export",
      "value": true
    }
  ]
}

Response (200):

JSON
{
  "id": "prod_01m4tx5nj8emwbyf7y9vcf47y0",
  "object": "product",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "livemode": false,
  "name": "Pro",
  "description": "For growing teams.",
  "taxCategoryId": "saas",
  "kind": "plan",
  "entitlements": [
    {
      "featureKey": "seats.max",
      "value": 25
    },
    {
      "featureKey": "feature.export",
      "value": true
    }
  ],
  "lifetimeEntitlements": false,
  "displayOrder": 2,
  "highlighted": true,
  "active": true,
  "images": [],
  "metadata": {},
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-14T09:30:00.000Z"
}

Errors

CodeHTTP statusWhenWhat to do
validation_failed400No field to change was sent, or one is malformed.Fix the fields listed in details.issues and send the request again.
feature_not_found400An entitlement names a feature the brand doesn't have in this mode.Create the feature first (features.create), or fix the feature key.
entitlement_value_invalid400An entitlement value doesn't fit its feature's type.Use true or false for boolean features, a whole number of 0 or more for limits, and one of the listed values for enum features.
resource_not_found404No product with this ID is visible to the request.Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.
version_conflict409The product changed at the same time; retry.Fetch the object again and retry the change.
permission_denied403You can't change this brand's catalog.Ask an organization owner or admin for a role or scope that allows this action.

It can also return these common errors: api_version_unsupported, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, scope_required, idempotency_key_reused, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.