---
title: "Save a product with the given ID"
method: PUT
path: "/v3/products/{id}"
tags: ["Products"]
---

# Save a product with the given ID

`PUT /v3/products/{id}`

This endpoint both saves and updates a product. The product is identified by the `id` path parameter. If the product ID does not exist, then a new product with the corresponding ID will be created. Otherwise, the existing product will be modified.

## Path parameters

- `id` string, required

## Request body

- ProductRequest
  - `label` string, required — The product label. This is the human-readable name of the product.
  - `description` string — The product description. This is a human-readable description of the product.
  - `entitlement` ProductEntitlement, required
    - `id` string — Entitlement ID/slug.
    - `type` string — Entitlement type (always "bundle").
    - `entitlementTenant` string — Entitlement tenant ID.
  - `mapping` ProductMapping, required
    - `braintree_recurring` object
      - `plan_id` string — The Braintree plan ID. This is the unique identifier for the plan within the Braintree account.
      - `archived` boolean — Whether the product is archived. If true, the product will not be available for purchase.
    - `braintree_one_off` object
      - `price_points` ProductMappingPricePoint[]
        - `id` string, required — The unique identifier for the price point within the product.
        - `label` string, required — The human-readable name of the price point.
        - `price` number, required — The price of the product in the currency of the payment provider account.
        - `archived` boolean — Whether the price point is archived. If true, the price point will not be available for purchase.
    - `stripe_recurring` object
      - `stripe_plan_id` string — The Stripe plan ID. This is the unique identifier for the plan within the Stripe account.
    - `stripe_one_off` object
      - `price_points` ProductMappingPricePoint[]
        - `id` string, required — The unique identifier for the price point within the product.
        - `label` string, required — The human-readable name of the price point.
        - `price` number, required — The price of the product in the currency of the payment provider account.
        - `archived` boolean — Whether the price point is archived. If true, the price point will not be available for purchase.
    - `rate_plans` ProductMappingRatePlan[]
      - `payment_provider` string, required — The payment provider for which the rate plan is configured.
      - `rate_plan_id` string, required — The unique identifier for the rate plan within the payment provider account.
      - `archived` boolean — Whether the rate plan is archived. If true, the rate plan will not be available for purchase.
      - `archive_label` string — The human-readable name of the rate plan.
      - `environment` string, required — The environment for which the rate plan is configured.
    - `jwt` ProductMappingJwt
      - `privateClaimValue` string
  - `sharingLimit` number — The number of other users that the purchaser of this product can share the product with.

## Response `200`

OK. The product was updated.

- object
  - `message` string
  - `uri` string

## Other responses

- `201` — Created. The product was created.
- `400` — Bad Request. Returned if the request body is invalid.
- `401` — Unauthorized. Returned if no valid authentication was provided.
- `409` — Conflict. Returned when missing a reference to the entitlement.

---

[API](https://skmtc.dev/zuora/apis/admin-api-reference.md) · [All operations](https://skmtc.dev/zuora/apis/admin-api-reference/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/zuora/admin-api-reference/revisions/789812d35ac8/schema)
