> For the complete documentation index, see [llms.txt](https://tip4serv.gitbook.io/tip4serv-api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tip4serv.gitbook.io/tip4serv-api/products.md).

# Products

Operations related to products

## Get store products

> Retrieves information about all products in your store.\
> Use the \`page\` parameter to paginate results.\
> Set \`details\` to \`true\` to include detailed product information.\
> Set \`only\_enabled\` to \`true\` to retrieve only enabled products.\
> \
> \*\*Authorization:\*\*\
> \- Requires a valid JWT Bearer token.\
> \- The token must include the permission: \`read-products\`.<br>

```json
{"openapi":"3.0.4","info":{"title":"Tip4Serv API","version":"1.0.12"},"tags":[{"name":"Products","description":"Operations related to products"}],"servers":[{"url":"https://api.tip4serv.com/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT or Partner API key","description":"Use a Tip4Serv JWT for standard store access, or a Partner API key as a Bearer token for Partner Connect. Partner Connect operations also require the `store_id` and `integration_key` query parameters and the relevant seller-approved permission."}},"schemas":{"ProductGeneral":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier of the product."},"name":{"type":"string","description":"Name of the product."},"status":{"type":"boolean","description":"Indicates whether the product is enabled."},"slug":{"type":"string","description":"URL-friendly name of the product."},"price":{"type":"integer","description":"Actual price of the product after any applicable discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used."},"old_price":{"type":"integer","description":"Original price of the product without any discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used."},"percent_off":{"type":"integer","description":"If a discount applies, the percentage off from the original price."},"recurring_discount":{"type":"boolean","description":"Indicates whether the discount applies to each occurrence of a subscription."},"discount_end":{"type":"integer","description":"Timestamp of the discount expiration. *(expressed in the store timezone)*"},"donation":{"type":"boolean","description":"Indicates if the product is a donation-type product, this allow the user to choose the amount of the donation,  `price` therefore defines the minimum donation amount."},"min_donation":{"type":"number","description":"Minimum donation amount (only present if donation is true). If currency parameter is used, this value is converted to the requested currency."},"small_description":{"type":"string","description":"Shortened description of the product, limited to 512 characters."},"category":{"oneOf":[{"type":"integer"},{"$ref":"#/components/schemas/Category"}],"description":"Category the product belongs to *(either as an integer or as a full category object if details are enabled)*."},"subscription":{"type":"boolean","description":"Indicates whether the product is a subscription."},"stock":{"type":"integer","description":"Available stock of the product."},"duration_periodicity":{"type":"string","description":"Unit of time for the subscription's duration.\n\nPossible values:  \n- `day` – duration in days  \n- `week` – duration in weeks  \n- `month` – duration in months  \n- `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the subscription lasts 3 months.\n"},"period_num":{"type":"number","description":"Number of `duration_periodicity` units before the subscription expires or the next charge occurs.\n\nExamples:  \n- Charge the customer every 3 months  \n- Charge the customer every 1 year\n\nAccepted ranges:  \n- 1–99 for days  \n- 1–52 for weeks  \n- 1–12 for months  \n- 1–1 for years\n\nExample: `period_num: 3` → charge every 3 months\n"},"trial":{"type":"number","description":"Number of trial days offered in the subscription."},"featured":{"type":"boolean","description":"Indicates whether the product is featured."},"image":{"type":"string","description":"Main thumbnail of the product."},"created_date":{"type":"number","description":"Timestamp of product creation in the store's timezone."},"currency":{"type":"string","description":"Currency in which all prices are expressed. Matches the requested `currency` parameter, or the store's default currency if not specified."}},"required":["id","name","slug","price","status","small_description","category","subscription","featured","created_date"]},"Category":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the category."},"name":{"type":"string","description":"Name of the category."},"description":{"type":"string","description":"Description of the category."},"slug":{"type":"string","description":"URL-friendly name of the category."},"hide":{"type":"boolean","description":"Determines if the category is hidden."},"main_redirect":{"type":"boolean","description":"Redirect to home page if category is accessed."},"parent_id":{"type":"integer","format":"int64","description":"Parent category ID if this is a sub-category."}},"required":["id","name","slug","hide","main_redirect"]}}},"paths":{"/store/products":{"get":{"tags":["Products"],"summary":"Get store products","description":"Retrieves information about all products in your store.\nUse the `page` parameter to paginate results.\nSet `details` to `true` to include detailed product information.\nSet `only_enabled` to `true` to retrieve only enabled products.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-products`.\n","operationId":"getProducts","parameters":[{"name":"page","in":"query","description":"The page number to retrieve.","required":false,"schema":{"type":"integer","default":1}},{"name":"max_page","in":"query","description":"The maximum number of elements per page. This number must be between 5-50.","required":false,"schema":{"type":"integer","default":50}},{"name":"details","in":"query","description":"Enable detailed response for each product.","required":false,"schema":{"type":"boolean","default":false}},{"name":"only_enabled","in":"query","description":"Include only enabled products.","required":false,"schema":{"type":"boolean","default":false}},{"name":"category","in":"query","description":"Limit products to a specific category ID.","required":false,"schema":{"type":"integer"}},{"name":"currency","in":"query","description":"Display currency code (optional). Supported currencies: GBP, USD, EUR, CAD, AUD, CHF. If omitted, prices are displayed in store currency. Converts all product prices (price, old_price, min_donation) and custom field prices.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"type":"object","properties":{"products":{"type":"array","items":{"$ref":"#/components/schemas/ProductGeneral"}},"product_count":{"type":"number"},"currency":{"type":"string","description":"Currency in which all prices are expressed. Matches the requested `currency` parameter, or the store's default currency if not specified."}}}}}},"403":{"description":"Didn't provide a valid Tip4Serv API Key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"number"}}}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}}}}}}}
```

## Get store categories

> Retrieves information about all categories. Use \`page\` to paginate results.\
> Use \`parent\` to filter subcategories of a specific parent category.\
> \
> &#x20; \*\*Authorization:\*\*\
> \- Requires a valid JWT Bearer token.\
> \- The token must include the permission: \`read-products\`.<br>

```json
{"openapi":"3.0.4","info":{"title":"Tip4Serv API","version":"1.0.12"},"tags":[{"name":"Products","description":"Operations related to products"}],"servers":[{"url":"https://api.tip4serv.com/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT or Partner API key","description":"Use a Tip4Serv JWT for standard store access, or a Partner API key as a Bearer token for Partner Connect. Partner Connect operations also require the `store_id` and `integration_key` query parameters and the relevant seller-approved permission."}},"schemas":{"Category":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the category."},"name":{"type":"string","description":"Name of the category."},"description":{"type":"string","description":"Description of the category."},"slug":{"type":"string","description":"URL-friendly name of the category."},"hide":{"type":"boolean","description":"Determines if the category is hidden."},"main_redirect":{"type":"boolean","description":"Redirect to home page if category is accessed."},"parent_id":{"type":"integer","format":"int64","description":"Parent category ID if this is a sub-category."}},"required":["id","name","slug","hide","main_redirect"]}}},"paths":{"/store/categories":{"get":{"tags":["Products"],"summary":"Get store categories","description":"Retrieves information about all categories. Use `page` to paginate results.\nUse `parent` to filter subcategories of a specific parent category.\n\n  **Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-products`.\n","operationId":"getCategories","parameters":[{"name":"page","in":"query","description":"The page number to retrieve.","required":false,"schema":{"type":"integer","default":1}},{"name":"max_page","in":"query","description":"The maximum number of elements per page. This number must be between 5-50.","required":false,"schema":{"type":"integer","default":50}},{"name":"parent","in":"query","description":"The parent category to which we will retrieve it's sub-categories.\nBy default it won't filter by parent category.\n","required":false,"schema":{"type":"integer","default":1}}],"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"type":"object","properties":{"categories":{"type":"array","items":{"$ref":"#/components/schemas/Category"}},"category_count":{"type":"number"}}}}}},"403":{"description":"Didn't provide a valid Tip4Serv API Key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"number"}}}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}}}}}}}
```

## Get product by slug

> Retrieves detailed information about a single product identified by it's \`slug\`.\
> set \`details\` to \`true\` for full product details.\
> \
> \*\*Authorization:\*\*\
> \- Requires a valid JWT Bearer token.\
> \- The token must include the permission: \`read-products\`.<br>

```json
{"openapi":"3.0.4","info":{"title":"Tip4Serv API","version":"1.0.12"},"tags":[{"name":"Products","description":"Operations related to products"}],"servers":[{"url":"https://api.tip4serv.com/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT or Partner API key","description":"Use a Tip4Serv JWT for standard store access, or a Partner API key as a Bearer token for Partner Connect. Partner Connect operations also require the `store_id` and `integration_key` query parameters and the relevant seller-approved permission."}},"schemas":{"Product":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier of the product."},"name":{"type":"string","description":"Name of the product."},"status":{"type":"boolean","description":"Indicates whether the product is enabled."},"slug":{"type":"string","description":"URL-friendly name of the product."},"price":{"type":"integer","description":"Current price of the product after any applicable discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used."},"old_price":{"type":"integer","description":"Original price of the product without discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used."},"percent_off":{"type":"integer","description":"Percentage off from the original price if a discount applies."},"recurring_discount":{"type":"boolean","description":"Indicates whether the discount is applied on each occurrence of the subscription."},"discount_end":{"type":"integer","description":"Timestamp of the discount expiration. *(expressed in the store timezone)*"},"donation":{"type":"boolean","description":"Indicates if the product is a donation-type product, this allow the user to choose the amount of the donation,  `price` therefore defines the minimum donation amount."},"min_donation":{"type":"number","description":"Minimum donation amount (only present if donation is true). If currency parameter is used, this value is converted to the requested currency."},"description":{"type":"string","description":"Full description of the product."},"gallery":{"type":"array","description":"List of all images related to the product.","items":{"type":"string"}},"youtube":{"type":"string","description":"URL of the video associated with the product."},"category":{"oneOf":[{"type":"integer"},{"$ref":"#/components/schemas/Category"}],"description":"Category the product belongs to (integer or full category object if details are enabled)."},"featured":{"type":"boolean","description":"Indicates whether the product is featured."},"stock":{"type":"integer","description":"Available stock of the product."},"trial":{"type":"integer","description":"Number of trial days available for this product."},"renewal_start":{"type":"string","description":"If trial days are enabled, defines when commands in the \"Do this after each renewal payment\" event start.\n\nAccepted values:  \n`first_payment`, `second_payment`\n"},"delivery_method":{"type":"string","description":"Indicates the delivery method used to deliver the actions of the product. Can\nPossible values:\n- `all_servers` : will deliver the product commands on every servers. - `server_choice` : the user will be prompted to choose on which server he wish to receive his product. - `auto_detect` : Tip4Serv will automatically detect on which server the user is connected, and deliver only on this server.\nIf no option is specified, the default option will be set to `all_servers`"},"server_choice":{"type":"boolean","description":"Indicates whether the customer can select the server for product delivery.\n⚠ This flag is deprecated, please use delivery_mode instead, to know the delivery method of the actions."},"quantity":{"type":"boolean","description":"Indicates whether the customer can select the quantity to purchase."},"cmd_multiplier":{"type":"boolean","description":"If quantity is selectable, determines whether commands are multiplied by the chosen quantity."},"files":{"type":"boolean","description":"Indicates if the product provides downloadable files upon purchase."},"subscription":{"type":"boolean","description":"Indicates whether the product is a subscription."},"disable_giftcard_payments":{"type":"boolean","description":"Indicates whether the product can be purchased with a giftcard. If not specified this option will be set to false by default. If set to true a customer won't be able to purchase this product with a giftcard.\n"},"giftcard":{"type":"boolean","description":"Indicates whether the product supports gift cards."},"giftcard_expiration":{"type":"boolean","description":"Indicates whether the generated gift card will eventually expire."},"giftcard_expiration_duration_periodicity":{"type":"string","description":"Unit of time for the gift card expiration duration.\n\nPossible values:  \n- `day` – duration in days   - `week` – duration in weeks   - `month` – duration in months   - `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the giftcard will expire 3 months after the purchase.\n"},"giftcard_expiration_period_num":{"type":"integer","description":"Number of `duration_periodicity` units before the giftcard expires.\nExamples:  \n- Giftcard expires after 3 months  \n- Giftcard expires after 1 year\nExample: `period_num: 3` → charge every 3 months\n"},"enable_stock":{"type":"boolean","description":"Indicates if stock management is enabled for the product."},"subscription_cycle":{"type":"string","description":"Determines whether subscriptions are recurring or expire by default. Accepted values:   `each`, `expire`"},"cumul_sub":{"type":"boolean","description":"If set to false prevents customers from subscribing to the same product multiple times."},"onetime_sub":{"type":"boolean","description":"Allows customers to purchase the product for a single billing cycle without subscribing."},"enable_trial":{"type":"boolean","description":"Indicates whether trial days are enabled."},"purchase_limit":{"$ref":"#/components/schemas/PurchaseLimit","description":"Rules limiting the number of times a customer can purchase the product."},"duration_periodicity":{"type":"string","description":"Unit of time for the subscription duration.\n\nPossible values:  \n- `day` – duration in days  \n- `week` – duration in weeks  \n- `month` – duration in months  \n- `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the subscription lasts 3 months.\n"},"period_num":{"type":"number","description":"Number of `duration_periodicity` units before the subscription expires or the next charge occurs.\n\nExamples:  \n- Charge the customer every 3 months  \n- Charge the customer every 1 year\n\nAccepted ranges:  \n- 1–99 for days  \n- 1–52 for weeks  \n- 1–12 for months  \n- 1–1 for years\n\nExample: `period_num: 3` → charge every 3 months\n"},"custom_rules":{"type":"array","description":"Array of custom rules applied to the product's custom fields.","items":{"$ref":"#/components/schemas/CustomRule"}},"custom_fields":{"type":"array","description":"Array of custom fields attached to the product.","items":{"$ref":"#/components/schemas/CustomField"}},"created_date":{"type":"integer","description":"Timestamp of product creation in the store's timezone."},"last_edited":{"type":"integer","description":"Timestamp of the last product modification in the store's timezone."},"server_options":{"type":"array","description":"Array of server options to choose, will be sent if the delivery_method is  `server_choice`.","items":{"$ref":"#/components/schemas/ServerChoice"}},"actions":{"type":"object","description":"Array of different actions to execute, indexed by it's server ID.","additionalProperties":{"$ref":"#/components/schemas/Action"}},"currency":{"type":"string","description":"Currency in which all prices are expressed. Matches the requested `currency` parameter, or the store's default currency if not specified."}},"required":["id","name","slug","price","status","description","gallery","category","featured","stock","trial","server_choice","delivery_method","quantity","files","subscription","giftcard","enable_stock","cumul_sub","enable_trial","created_date","last_edited","actions"]},"Category":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the category."},"name":{"type":"string","description":"Name of the category."},"description":{"type":"string","description":"Description of the category."},"slug":{"type":"string","description":"URL-friendly name of the category."},"hide":{"type":"boolean","description":"Determines if the category is hidden."},"main_redirect":{"type":"boolean","description":"Redirect to home page if category is accessed."},"parent_id":{"type":"integer","format":"int64","description":"Parent category ID if this is a sub-category."}},"required":["id","name","slug","hide","main_redirect"]},"PurchaseLimit":{"type":"object","properties":{"purchase_times":{"type":"integer","description":"Maximum number of times the product can be purchased."},"type":{"type":"string","description":"Defines when the purchase limit applies.\n\nAccepted values:  \n- `every` → limit purchases to a recurring time period  \n- `only` → limit purchases permanently\n"},"cycle":{"type":"integer","description":"Number of time units before the purchase limit resets.\n\nExample:  \n- Limit purchases to 1 time every 1 month  \n- Limit purchases to 1 time every 3 months\n\nAccepted ranges: 1–99 for days, 1–52 for weeks, 1–12 for months, 1–1 for years\n"},"periodicity":{"type":"string","description":"Unit of time used to define the purchase limit.\n\nAccepted values: `day`, `week`, `month`, `year`\n"}},"required":["purchase_times","type","cycle","periodicity"]},"CustomRule":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the custom rule."},"order":{"type":"integer","format":"int64","description":"Priority order of the custom rule."},"name":{"type":"string","description":"Name of the custom rule."},"type":{"type":"string","description":"Type of custom rule. Accepted values: `number_limit`"},"min":{"type":"integer","format":"int64","description":"Minimum value if the rule type is `number_limit`."},"max":{"type":"integer","format":"int64","description":"Maximum value if the rule type is `number_limit`."},"fields":{"type":"array","description":"IDs of custom fields affected by this rule.","items":{"type":"number","format":"int64"}}},"required":["id","order","name","type"]},"CustomField":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the custom field."},"order":{"type":"integer","format":"int64","description":"Priority order of the custom field."},"name":{"type":"string","description":"Name of the custom field."},"type":{"type":"string","description":"Type of custom field. Accepted values: `text`, `checkbox`, `number`, `selection`\n"},"marker":{"type":"string","description":"Placeholder marker used in commands."},"if_not_filled":{"type":"string","description":"Behavior if field is left empty. Accepted values: `do_not_execute`, `remove_marker`, `use_default`"},"default_value":{"type":"string","description":"Default value used if `if_not_filled` is set to `use_default`."},"required":{"type":"boolean","description":"Indicates if the custom field is mandatory."},"minimum":{"type":"integer","description":"Minimum value if field type is `number`."},"maximum":{"type":"integer","description":"Maximum value if field type is `number`."},"step":{"type":"integer","description":"Increment step if field type is `number`."},"number_type":{"type":"string","description":"Specifies number input type. Accepted values: `number`, `range`"},"price":{"type":"integer","description":"Additional price added to product if field is selected."},"options":{"type":"array","items":{"$ref":"#/components/schemas/CustomFieldOption"},"description":"Options available if field type is `selection`."}},"required":["id","order","name","type","required"]},"CustomFieldOption":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier of the option."},"order":{"type":"integer","description":"Priority order of the option."},"name":{"type":"string","description":"Name of the option."},"value":{"type":"integer","description":"Value corresponding to the option."},"price":{"type":"integer","description":"Price adjustment if option is selected."}},"required":["id","order","name","value","price"]},"ServerChoice":{"type":"object","properties":{"id":{"type":"integer","description":"Server ID"},"name":{"type":"string","description":"Server Name"}},"required":["id","name"]},"Action":{"type":"object","properties":{"payment_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}},"refund_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}},"renewal_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}},"expire_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}}}},"SimpleServerCommand":{"type":"object","properties":{"str":{"description":"Content of the command to be executed"},"event":{"description":"Event triggering the execution of the command. Can take the following values: `Execute`, `Must be online`"}}}}},"paths":{"/store/product/{slug}":{"get":{"tags":["Products"],"summary":"Get product by slug","description":"Retrieves detailed information about a single product identified by it's `slug`.\nset `details` to `true` for full product details.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-products`.\n","operationId":"getProductBySlug","parameters":[{"name":"slug","in":"path","required":true,"description":"the slug of the product to retrieve.","schema":{"type":"string"}},{"name":"details","in":"query","required":false,"description":"Enable detailed response.","schema":{"type":"boolean"}},{"name":"currency","in":"query","description":"Display currency code (optional). Supported currencies: GBP, USD, EUR, CAD, AUD, CHF. If omitted, prices are displayed in store currency. Converts all product prices (price, old_price, min_donation) and custom field prices.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Product found successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"400":{"description":"Error in your request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"403":{"description":"Didn't provide a valid Tip4Serv API Key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"404":{"description":"Couldn't find the product with that id.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"integer"}}}}}}}}}}}
```

## Create a product

> Create a new product in your store.\
> \
> \*\*Authorization:\*\*\
> \- Requires a valid JWT Bearer token.\
> \- The token must include the permission: \`create-products\`.<br>

```json
{"openapi":"3.0.4","info":{"title":"Tip4Serv API","version":"1.0.12"},"tags":[{"name":"Products","description":"Operations related to products"}],"servers":[{"url":"https://api.tip4serv.com/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT or Partner API key","description":"Use a Tip4Serv JWT for standard store access, or a Partner API key as a Bearer token for Partner Connect. Partner Connect operations also require the `store_id` and `integration_key` query parameters and the relevant seller-approved permission."}},"schemas":{"CreateProduct":{"type":"object","properties":{"name":{"type":"string","description":"Name of the product."},"status":{"type":"boolean","description":"Indicates whether the product is enabled. If not specified, the product will be automatically enabled","default":true},"slug":{"type":"string","description":"URL-friendly name of the product. If not specified will be automatically calculated."},"price":{"type":"integer","description":"Current price of the product after any applicable discounts, in the store's currency."},"recurring_discount":{"type":"boolean","description":"Indicates whether the discount is applied on each occurrence of the subscription."},"donation":{"type":"boolean","description":"Indicates if the product is a donation-type product, this allow the user to choose the amount of the donation,  `price` therefore defines the minimum donation amount."},"description":{"type":"string","description":"Full description of the product."},"youtube":{"type":"string","description":"URL of the video associated with the product."},"category":{"oneOf":[{"type":"integer"},{"$ref":"#/components/schemas/Category"}],"description":"Category the product belongs to (integer or full category object if details are enabled). If not specified, the product will be automatically added to the default category."},"featured":{"type":"boolean","description":"Indicates whether the product is featured. If not specified will be set to false."},"enable_stock":{"type":"integer","description":"Enable a system of limited stock for this product. By default if not set, no stock system will be implemented."},"stock":{"type":"integer","description":"Available stock of the product. `enable_stock` must be set to true first."},"enable_trial":{"type":"boolean","description":"Indicates whether trial days are enabled."},"trial":{"type":"integer","description":"Number of trial days available for this product. If not specified no trial period will be set. `enable_trial` must first be set to true."},"renewal_start":{"type":"string","description":"If trial days are enabled, defines when commands in the \"Do this after each renewal payment\" event start.\n\nAccepted values:  \n`first_payment`, `second_payment`\n"},"quantity":{"type":"boolean","description":"Indicates whether the customer can select the quantity to purchase. If not specified customers will by default be able to purchase the product multiple times."},"cmd_multiplier":{"type":"boolean","description":"If quantity is selectable, determines whether commands are multiplied by the chosen quantity. If set to true each command will be executed \"quantity\" times, by default `cmd_multiplier` is set to false."},"subscription":{"type":"boolean","description":"Indicates whether the product is a subscription. If not specified the product will not be an subscription."},"disable_giftcard_payments":{"type":"boolean","description":"Indicates whether the product can be purchased with a giftcard. If not specified this option will be set to false by default. If set to true a customer won't be able to purchase this product with a giftcard.\n"},"giftcard":{"type":"boolean","description":"Indicates whether the product supports gift cards. If not specified the product will not offer any giftcard."},"giftcard_expiration":{"type":"boolean","description":"Indicates whether the generated gift card will eventually expire."},"giftcard_expiration_duration_periodicity":{"type":"string","description":"Unit of time for the gift card expiration duration.\n\nPossible values:  \n- `day` – duration in days   - `week` – duration in weeks   - `month` – duration in months   - `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the giftcard will expire 3 months after the purchase.\n"},"giftcard_expiration_period_num":{"type":"integer","description":"Number of `duration_periodicity` units before the giftcard expires.\nExamples:  \n- Giftcard expires after 3 months  \n- Giftcard expires after 1 year\nExample: `period_num: 3` → charge every 3 months\n"},"custom_fields":{"type":"array","description":"Array of custom fields attached to the product.","items":{"$ref":"#/components/schemas/CustomField"}},"custom_rules":{"type":"array","description":"Array of custom rules applied to the product's custom fields.","items":{"$ref":"#/components/schemas/CreateCustomRule"}},"subscription_cycle":{"type":"string","description":"Determines whether subscriptions are recurring or expire by default. Accepted values:   `each`, `expire`"},"cumul_sub":{"type":"boolean","description":"If set to false prevents customers from subscribing to the same product multiple times. By default set to true."},"onetime_sub":{"type":"boolean","description":"Allows customers to purchase the product for a single billing cycle without subscribing. By default set to true."},"duration_periodicity":{"type":"string","description":"Unit of time for the subscription duration.\n\nPossible values:  \n- `day` – duration in days  \n- `week` – duration in weeks  \n- `month` – duration in months  \n- `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the subscription lasts 3 months.\n"},"period_num":{"type":"number","description":"Number of `duration_periodicity` units before the subscription expires or the next charge occurs.\n\nExamples:  \n- Charge the customer every 3 months  \n- Charge the customer every 1 year\n\nAccepted ranges:  \n- 1–99 for days  \n- 1–52 for weeks  \n- 1–12 for months  \n- 1–1 for years\n\nExample: `period_num: 3` → charge every 3 months\n\nIf not specified will be set by default to 1.\n"},"purchase_limit":{"$ref":"#/components/schemas/PurchaseLimit","description":"Rules limiting the number of times a customer can purchase the product."},"actions":{"type":"object","description":"Array of different actions to execute, indexed by it's server ID. By default if not specified no actions will be executed","additionalProperties":{"$ref":"#/components/schemas/Action"}}},"required":["name","price"]},"Category":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the category."},"name":{"type":"string","description":"Name of the category."},"description":{"type":"string","description":"Description of the category."},"slug":{"type":"string","description":"URL-friendly name of the category."},"hide":{"type":"boolean","description":"Determines if the category is hidden."},"main_redirect":{"type":"boolean","description":"Redirect to home page if category is accessed."},"parent_id":{"type":"integer","format":"int64","description":"Parent category ID if this is a sub-category."}},"required":["id","name","slug","hide","main_redirect"]},"CustomField":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the custom field."},"order":{"type":"integer","format":"int64","description":"Priority order of the custom field."},"name":{"type":"string","description":"Name of the custom field."},"type":{"type":"string","description":"Type of custom field. Accepted values: `text`, `checkbox`, `number`, `selection`\n"},"marker":{"type":"string","description":"Placeholder marker used in commands."},"if_not_filled":{"type":"string","description":"Behavior if field is left empty. Accepted values: `do_not_execute`, `remove_marker`, `use_default`"},"default_value":{"type":"string","description":"Default value used if `if_not_filled` is set to `use_default`."},"required":{"type":"boolean","description":"Indicates if the custom field is mandatory."},"minimum":{"type":"integer","description":"Minimum value if field type is `number`."},"maximum":{"type":"integer","description":"Maximum value if field type is `number`."},"step":{"type":"integer","description":"Increment step if field type is `number`."},"number_type":{"type":"string","description":"Specifies number input type. Accepted values: `number`, `range`"},"price":{"type":"integer","description":"Additional price added to product if field is selected."},"options":{"type":"array","items":{"$ref":"#/components/schemas/CustomFieldOption"},"description":"Options available if field type is `selection`."}},"required":["id","order","name","type","required"]},"CustomFieldOption":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier of the option."},"order":{"type":"integer","description":"Priority order of the option."},"name":{"type":"string","description":"Name of the option."},"value":{"type":"integer","description":"Value corresponding to the option."},"price":{"type":"integer","description":"Price adjustment if option is selected."}},"required":["id","order","name","value","price"]},"CreateCustomRule":{"type":"object","properties":{"name":{"type":"string","description":"Name of the custom rule."},"type":{"type":"string","description":"Type of custom rule. Accepted values: `number_limit`"},"min":{"type":"integer","format":"int64","description":"Minimum value if the rule type is `number_limit`."},"max":{"type":"integer","format":"int64","description":"Maximum value if the rule type is `number_limit`."},"fields":{"type":"array","description":"IDs of custom fields affected by this rule.","items":{"type":"number","format":"int64"}}},"required":["name","type"]},"PurchaseLimit":{"type":"object","properties":{"purchase_times":{"type":"integer","description":"Maximum number of times the product can be purchased."},"type":{"type":"string","description":"Defines when the purchase limit applies.\n\nAccepted values:  \n- `every` → limit purchases to a recurring time period  \n- `only` → limit purchases permanently\n"},"cycle":{"type":"integer","description":"Number of time units before the purchase limit resets.\n\nExample:  \n- Limit purchases to 1 time every 1 month  \n- Limit purchases to 1 time every 3 months\n\nAccepted ranges: 1–99 for days, 1–52 for weeks, 1–12 for months, 1–1 for years\n"},"periodicity":{"type":"string","description":"Unit of time used to define the purchase limit.\n\nAccepted values: `day`, `week`, `month`, `year`\n"}},"required":["purchase_times","type","cycle","periodicity"]},"Action":{"type":"object","properties":{"payment_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}},"refund_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}},"renewal_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}},"expire_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}}}},"SimpleServerCommand":{"type":"object","properties":{"str":{"description":"Content of the command to be executed"},"event":{"description":"Event triggering the execution of the command. Can take the following values: `Execute`, `Must be online`"}}},"Product":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier of the product."},"name":{"type":"string","description":"Name of the product."},"status":{"type":"boolean","description":"Indicates whether the product is enabled."},"slug":{"type":"string","description":"URL-friendly name of the product."},"price":{"type":"integer","description":"Current price of the product after any applicable discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used."},"old_price":{"type":"integer","description":"Original price of the product without discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used."},"percent_off":{"type":"integer","description":"Percentage off from the original price if a discount applies."},"recurring_discount":{"type":"boolean","description":"Indicates whether the discount is applied on each occurrence of the subscription."},"discount_end":{"type":"integer","description":"Timestamp of the discount expiration. *(expressed in the store timezone)*"},"donation":{"type":"boolean","description":"Indicates if the product is a donation-type product, this allow the user to choose the amount of the donation,  `price` therefore defines the minimum donation amount."},"min_donation":{"type":"number","description":"Minimum donation amount (only present if donation is true). If currency parameter is used, this value is converted to the requested currency."},"description":{"type":"string","description":"Full description of the product."},"gallery":{"type":"array","description":"List of all images related to the product.","items":{"type":"string"}},"youtube":{"type":"string","description":"URL of the video associated with the product."},"category":{"oneOf":[{"type":"integer"},{"$ref":"#/components/schemas/Category"}],"description":"Category the product belongs to (integer or full category object if details are enabled)."},"featured":{"type":"boolean","description":"Indicates whether the product is featured."},"stock":{"type":"integer","description":"Available stock of the product."},"trial":{"type":"integer","description":"Number of trial days available for this product."},"renewal_start":{"type":"string","description":"If trial days are enabled, defines when commands in the \"Do this after each renewal payment\" event start.\n\nAccepted values:  \n`first_payment`, `second_payment`\n"},"delivery_method":{"type":"string","description":"Indicates the delivery method used to deliver the actions of the product. Can\nPossible values:\n- `all_servers` : will deliver the product commands on every servers. - `server_choice` : the user will be prompted to choose on which server he wish to receive his product. - `auto_detect` : Tip4Serv will automatically detect on which server the user is connected, and deliver only on this server.\nIf no option is specified, the default option will be set to `all_servers`"},"server_choice":{"type":"boolean","description":"Indicates whether the customer can select the server for product delivery.\n⚠ This flag is deprecated, please use delivery_mode instead, to know the delivery method of the actions."},"quantity":{"type":"boolean","description":"Indicates whether the customer can select the quantity to purchase."},"cmd_multiplier":{"type":"boolean","description":"If quantity is selectable, determines whether commands are multiplied by the chosen quantity."},"files":{"type":"boolean","description":"Indicates if the product provides downloadable files upon purchase."},"subscription":{"type":"boolean","description":"Indicates whether the product is a subscription."},"disable_giftcard_payments":{"type":"boolean","description":"Indicates whether the product can be purchased with a giftcard. If not specified this option will be set to false by default. If set to true a customer won't be able to purchase this product with a giftcard.\n"},"giftcard":{"type":"boolean","description":"Indicates whether the product supports gift cards."},"giftcard_expiration":{"type":"boolean","description":"Indicates whether the generated gift card will eventually expire."},"giftcard_expiration_duration_periodicity":{"type":"string","description":"Unit of time for the gift card expiration duration.\n\nPossible values:  \n- `day` – duration in days   - `week` – duration in weeks   - `month` – duration in months   - `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the giftcard will expire 3 months after the purchase.\n"},"giftcard_expiration_period_num":{"type":"integer","description":"Number of `duration_periodicity` units before the giftcard expires.\nExamples:  \n- Giftcard expires after 3 months  \n- Giftcard expires after 1 year\nExample: `period_num: 3` → charge every 3 months\n"},"enable_stock":{"type":"boolean","description":"Indicates if stock management is enabled for the product."},"subscription_cycle":{"type":"string","description":"Determines whether subscriptions are recurring or expire by default. Accepted values:   `each`, `expire`"},"cumul_sub":{"type":"boolean","description":"If set to false prevents customers from subscribing to the same product multiple times."},"onetime_sub":{"type":"boolean","description":"Allows customers to purchase the product for a single billing cycle without subscribing."},"enable_trial":{"type":"boolean","description":"Indicates whether trial days are enabled."},"purchase_limit":{"$ref":"#/components/schemas/PurchaseLimit","description":"Rules limiting the number of times a customer can purchase the product."},"duration_periodicity":{"type":"string","description":"Unit of time for the subscription duration.\n\nPossible values:  \n- `day` – duration in days  \n- `week` – duration in weeks  \n- `month` – duration in months  \n- `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the subscription lasts 3 months.\n"},"period_num":{"type":"number","description":"Number of `duration_periodicity` units before the subscription expires or the next charge occurs.\n\nExamples:  \n- Charge the customer every 3 months  \n- Charge the customer every 1 year\n\nAccepted ranges:  \n- 1–99 for days  \n- 1–52 for weeks  \n- 1–12 for months  \n- 1–1 for years\n\nExample: `period_num: 3` → charge every 3 months\n"},"custom_rules":{"type":"array","description":"Array of custom rules applied to the product's custom fields.","items":{"$ref":"#/components/schemas/CustomRule"}},"custom_fields":{"type":"array","description":"Array of custom fields attached to the product.","items":{"$ref":"#/components/schemas/CustomField"}},"created_date":{"type":"integer","description":"Timestamp of product creation in the store's timezone."},"last_edited":{"type":"integer","description":"Timestamp of the last product modification in the store's timezone."},"server_options":{"type":"array","description":"Array of server options to choose, will be sent if the delivery_method is  `server_choice`.","items":{"$ref":"#/components/schemas/ServerChoice"}},"actions":{"type":"object","description":"Array of different actions to execute, indexed by it's server ID.","additionalProperties":{"$ref":"#/components/schemas/Action"}},"currency":{"type":"string","description":"Currency in which all prices are expressed. Matches the requested `currency` parameter, or the store's default currency if not specified."}},"required":["id","name","slug","price","status","description","gallery","category","featured","stock","trial","server_choice","delivery_method","quantity","files","subscription","giftcard","enable_stock","cumul_sub","enable_trial","created_date","last_edited","actions"]},"CustomRule":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the custom rule."},"order":{"type":"integer","format":"int64","description":"Priority order of the custom rule."},"name":{"type":"string","description":"Name of the custom rule."},"type":{"type":"string","description":"Type of custom rule. Accepted values: `number_limit`"},"min":{"type":"integer","format":"int64","description":"Minimum value if the rule type is `number_limit`."},"max":{"type":"integer","format":"int64","description":"Maximum value if the rule type is `number_limit`."},"fields":{"type":"array","description":"IDs of custom fields affected by this rule.","items":{"type":"number","format":"int64"}}},"required":["id","order","name","type"]},"ServerChoice":{"type":"object","properties":{"id":{"type":"integer","description":"Server ID"},"name":{"type":"string","description":"Server Name"}},"required":["id","name"]}}},"paths":{"/store/product":{"post":{"tags":["Products"],"summary":"Create a product","description":"Create a new product in your store.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `create-products`.\n","operationId":"createProduct","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProduct"}}}},"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"400":{"description":"Error in your request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"403":{"description":"Missing or invalid Tip4Serv API Key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"number"}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"number"}}}}}}}}}}}
```

## Upload a thumbnail

> Update a new product in your store.\
> \
> \*\*Authorization:\*\*\
> \- Requires a valid JWT Bearer token.\
> \- The token must include the permission: \`update-products\`.<br>

```json
{"openapi":"3.0.4","info":{"title":"Tip4Serv API","version":"1.0.12"},"tags":[{"name":"Products","description":"Operations related to products"}],"servers":[{"url":"https://api.tip4serv.com/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT or Partner API key","description":"Use a Tip4Serv JWT for standard store access, or a Partner API key as a Bearer token for Partner Connect. Partner Connect operations also require the `store_id` and `integration_key` query parameters and the relevant seller-approved permission."}}},"paths":{"/store/product/{id}/thumbnail":{"post":{"tags":["Products"],"summary":"Upload a thumbnail","description":"Update a new product in your store.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `update-products`.\n","operationId":"uploadProductThumbnail","parameters":[{"name":"id","in":"path","required":true,"description":"The ID of the product to attach the file to.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"The thumbnail to upload. Ther image must not be heavier than 8Mb."}}}}}},"responses":{"200":{"description":"File uploaded successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"status":{"type":"integer"}}}}}},"400":{"description":"Error in your request.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"403":{"description":"Missing or invalid Tip4Serv API Key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"404":{"description":"Product not found.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}}}}}}}
```

## Upload an image to be displayed in the product gallery

> Update a new product in your store.\
> \
> \*\*Authorization:\*\*\
> \- Requires a valid JWT Bearer token.\
> \- The token must include the permission: \`update-products\`.<br>

```json
{"openapi":"3.0.4","info":{"title":"Tip4Serv API","version":"1.0.12"},"tags":[{"name":"Products","description":"Operations related to products"}],"servers":[{"url":"https://api.tip4serv.com/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT or Partner API key","description":"Use a Tip4Serv JWT for standard store access, or a Partner API key as a Bearer token for Partner Connect. Partner Connect operations also require the `store_id` and `integration_key` query parameters and the relevant seller-approved permission."}}},"paths":{"/store/product/{id}/gallery":{"post":{"tags":["Products"],"summary":"Upload an image to be displayed in the product gallery","description":"Update a new product in your store.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `update-products`.\n","operationId":"uploadProductGallery","parameters":[{"name":"id","in":"path","required":true,"description":"The ID of the product to attach the image to.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"The image to upload. The image must not be heavier than 8Mb."}}}}}},"responses":{"200":{"description":"Image uploaded successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"status":{"type":"integer"}}}}}},"400":{"description":"Error in your request.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"403":{"description":"Missing or invalid Tip4Serv API Key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"404":{"description":"Product not found.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}}}}}}}
```

## Delete a monetized file

> Delete a monetized file.\
> \
> \*\*Authorization:\*\*\
> \- Requires a valid JWT Bearer token.\
> \- The token must include the permission: \`update-products\`.<br>

```json
{"openapi":"3.0.4","info":{"title":"Tip4Serv API","version":"1.0.12"},"tags":[{"name":"Products","description":"Operations related to products"}],"servers":[{"url":"https://api.tip4serv.com/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT or Partner API key","description":"Use a Tip4Serv JWT for standard store access, or a Partner API key as a Bearer token for Partner Connect. Partner Connect operations also require the `store_id` and `integration_key` query parameters and the relevant seller-approved permission."}}},"paths":{"/store/product/{id}/file/{file_id}":{"delete":{"tags":["Products"],"summary":"Delete a monetized file","description":"Delete a monetized file.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `update-products`.\n","operationId":"deleteProductFile","parameters":[{"name":"id","in":"path","required":true,"description":"The ID of the product to attach the file to.","schema":{"type":"integer"}},{"name":"file_id","in":"path","required":true,"description":"The id of the file attached to a product to delete.","schema":{"type":"integer"}}],"responses":{"200":{"description":"File uploaded successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"status":{"type":"integer"}}}}}},"400":{"description":"Error in your request.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"403":{"description":"Missing or invalid Tip4Serv API Key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"404":{"description":"Product not found.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}}}}}}}
```

## Upload a file to sell for a product

> Upload a file to sell in your product.\
> \
> \*\*Authorization:\*\*\
> \- Requires a valid JWT Bearer token.\
> \- The token must include the permission: \`update-products\`.<br>

```json
{"openapi":"3.0.4","info":{"title":"Tip4Serv API","version":"1.0.12"},"tags":[{"name":"Products","description":"Operations related to products"}],"servers":[{"url":"https://api.tip4serv.com/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT or Partner API key","description":"Use a Tip4Serv JWT for standard store access, or a Partner API key as a Bearer token for Partner Connect. Partner Connect operations also require the `store_id` and `integration_key` query parameters and the relevant seller-approved permission."}},"schemas":{"ProductFile":{"type":"object","properties":{"id":{"type":"integer","description":"Unique ID of the uploaded product file."},"file_name":{"type":"string","description":"Display name of the uploaded file."},"expiration":{"type":"integer","description":"Number of days the file remains available after purchase.\n`-1` means the file never expires.\n"},"url":{"type":"string","format":"uri","description":"Internal or signed URL used to download the file."},"created_at":{"type":"integer","description":"Unix timestamp when the file was uploaded."}},"required":["id","file_name","expiration","created_at"]}}},"paths":{"/store/product/{id}/file":{"post":{"tags":["Products"],"summary":"Upload a file to sell for a product","description":"Upload a file to sell in your product.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `update-products`.\n","operationId":"uploadProductFile","parameters":[{"name":"id","in":"path","required":true,"description":"The ID of the product to attach the file to.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"expiration":{"type":"integer","description":"Number of days the file remains available after purchase.\nUse `-1` to keep the file valid forever.\n\n(This will affect the other files for the same product)\n","default":-1},"file":{"type":"string","format":"binary","description":"The file to upload. The file must not be heavier than 50Mb."}}}}}},"responses":{"200":{"description":"File uploaded successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductFile"}}}},"400":{"description":"Error in your request.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"403":{"description":"Missing or invalid Tip4Serv API Key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"404":{"description":"Product not found.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"409":{"description":"Storage quota exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}}}}}}}
```

## Delete a gallery image from the product.

> Delete a gallery image from the product.\
> \
> \*\*Authorization:\*\*\
> \- Requires a valid JWT Bearer token.\
> \- The token must include the permission: \`update-products\`.<br>

````json
{"openapi":"3.0.4","info":{"title":"Tip4Serv API","version":"1.0.12"},"tags":[{"name":"Products","description":"Operations related to products"}],"servers":[{"url":"https://api.tip4serv.com/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT or Partner API key","description":"Use a Tip4Serv JWT for standard store access, or a Partner API key as a Bearer token for Partner Connect. Partner Connect operations also require the `store_id` and `integration_key` query parameters and the relevant seller-approved permission."}}},"paths":{"/store/product/{id}/gallery/{image_id}":{"delete":{"tags":["Products"],"summary":"Delete a gallery image from the product.","description":"Delete a gallery image from the product.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `update-products`.\n","operationId":"deleteProductGallery","parameters":[{"name":"id","in":"path","required":true,"description":"The ID of the product where the image is attached to.","schema":{"type":"integer"}},{"name":"image_id","in":"path","required":true,"description":"\nThe `image_id` corresponds to the gallery image position, starting at 1.\n\nFor example, given the gallery:\n\n```json\n[\"image_1.webp\", \"image_2.webp\", \"image_3.png\"]\n```\n\nTo delete `image_2.webp`, send:\n\n```text\nimage_id = 2\n```\n\n**Important:**\nIf your product uses both a thumbnail and a gallery, the thumbnail may appear at the beginning of the gallery array returned by the API.\n\nDo not include the thumbnail when calculating the `image_id`.\n\nFor example, given:\n\n```json\n[\"thumbnail.jpg\", \"image_1.webp\", \"image_2.webp\", \"image_3.png\"]\n```\n\nTo delete `image_2.webp`, the `image_id` is still `2`, not `3`.\n","schema":{"type":"integer"}}],"responses":{"200":{"description":"Image successfully deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"status":{"type":"integer"}}}}}},"400":{"description":"Error in your request.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"403":{"description":"Missing or invalid Tip4Serv API Key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"404":{"description":"Product not found.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"500":{"description":"Internal Server Error.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}}}}}}}
````

## Get product by ID

> Retrieves detailed information about a single product identified by \`id\`.\
> Set \`details\` to \`true\` for full product details.\
> \
> \*\*Authorization:\*\*\
> \- Requires a valid JWT Bearer token.\
> \- The token must include the permission: \`read-products\`.<br>

```json
{"openapi":"3.0.4","info":{"title":"Tip4Serv API","version":"1.0.12"},"tags":[{"name":"Products","description":"Operations related to products"}],"servers":[{"url":"https://api.tip4serv.com/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT or Partner API key","description":"Use a Tip4Serv JWT for standard store access, or a Partner API key as a Bearer token for Partner Connect. Partner Connect operations also require the `store_id` and `integration_key` query parameters and the relevant seller-approved permission."}},"schemas":{"Product":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier of the product."},"name":{"type":"string","description":"Name of the product."},"status":{"type":"boolean","description":"Indicates whether the product is enabled."},"slug":{"type":"string","description":"URL-friendly name of the product."},"price":{"type":"integer","description":"Current price of the product after any applicable discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used."},"old_price":{"type":"integer","description":"Original price of the product without discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used."},"percent_off":{"type":"integer","description":"Percentage off from the original price if a discount applies."},"recurring_discount":{"type":"boolean","description":"Indicates whether the discount is applied on each occurrence of the subscription."},"discount_end":{"type":"integer","description":"Timestamp of the discount expiration. *(expressed in the store timezone)*"},"donation":{"type":"boolean","description":"Indicates if the product is a donation-type product, this allow the user to choose the amount of the donation,  `price` therefore defines the minimum donation amount."},"min_donation":{"type":"number","description":"Minimum donation amount (only present if donation is true). If currency parameter is used, this value is converted to the requested currency."},"description":{"type":"string","description":"Full description of the product."},"gallery":{"type":"array","description":"List of all images related to the product.","items":{"type":"string"}},"youtube":{"type":"string","description":"URL of the video associated with the product."},"category":{"oneOf":[{"type":"integer"},{"$ref":"#/components/schemas/Category"}],"description":"Category the product belongs to (integer or full category object if details are enabled)."},"featured":{"type":"boolean","description":"Indicates whether the product is featured."},"stock":{"type":"integer","description":"Available stock of the product."},"trial":{"type":"integer","description":"Number of trial days available for this product."},"renewal_start":{"type":"string","description":"If trial days are enabled, defines when commands in the \"Do this after each renewal payment\" event start.\n\nAccepted values:  \n`first_payment`, `second_payment`\n"},"delivery_method":{"type":"string","description":"Indicates the delivery method used to deliver the actions of the product. Can\nPossible values:\n- `all_servers` : will deliver the product commands on every servers. - `server_choice` : the user will be prompted to choose on which server he wish to receive his product. - `auto_detect` : Tip4Serv will automatically detect on which server the user is connected, and deliver only on this server.\nIf no option is specified, the default option will be set to `all_servers`"},"server_choice":{"type":"boolean","description":"Indicates whether the customer can select the server for product delivery.\n⚠ This flag is deprecated, please use delivery_mode instead, to know the delivery method of the actions."},"quantity":{"type":"boolean","description":"Indicates whether the customer can select the quantity to purchase."},"cmd_multiplier":{"type":"boolean","description":"If quantity is selectable, determines whether commands are multiplied by the chosen quantity."},"files":{"type":"boolean","description":"Indicates if the product provides downloadable files upon purchase."},"subscription":{"type":"boolean","description":"Indicates whether the product is a subscription."},"disable_giftcard_payments":{"type":"boolean","description":"Indicates whether the product can be purchased with a giftcard. If not specified this option will be set to false by default. If set to true a customer won't be able to purchase this product with a giftcard.\n"},"giftcard":{"type":"boolean","description":"Indicates whether the product supports gift cards."},"giftcard_expiration":{"type":"boolean","description":"Indicates whether the generated gift card will eventually expire."},"giftcard_expiration_duration_periodicity":{"type":"string","description":"Unit of time for the gift card expiration duration.\n\nPossible values:  \n- `day` – duration in days   - `week` – duration in weeks   - `month` – duration in months   - `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the giftcard will expire 3 months after the purchase.\n"},"giftcard_expiration_period_num":{"type":"integer","description":"Number of `duration_periodicity` units before the giftcard expires.\nExamples:  \n- Giftcard expires after 3 months  \n- Giftcard expires after 1 year\nExample: `period_num: 3` → charge every 3 months\n"},"enable_stock":{"type":"boolean","description":"Indicates if stock management is enabled for the product."},"subscription_cycle":{"type":"string","description":"Determines whether subscriptions are recurring or expire by default. Accepted values:   `each`, `expire`"},"cumul_sub":{"type":"boolean","description":"If set to false prevents customers from subscribing to the same product multiple times."},"onetime_sub":{"type":"boolean","description":"Allows customers to purchase the product for a single billing cycle without subscribing."},"enable_trial":{"type":"boolean","description":"Indicates whether trial days are enabled."},"purchase_limit":{"$ref":"#/components/schemas/PurchaseLimit","description":"Rules limiting the number of times a customer can purchase the product."},"duration_periodicity":{"type":"string","description":"Unit of time for the subscription duration.\n\nPossible values:  \n- `day` – duration in days  \n- `week` – duration in weeks  \n- `month` – duration in months  \n- `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the subscription lasts 3 months.\n"},"period_num":{"type":"number","description":"Number of `duration_periodicity` units before the subscription expires or the next charge occurs.\n\nExamples:  \n- Charge the customer every 3 months  \n- Charge the customer every 1 year\n\nAccepted ranges:  \n- 1–99 for days  \n- 1–52 for weeks  \n- 1–12 for months  \n- 1–1 for years\n\nExample: `period_num: 3` → charge every 3 months\n"},"custom_rules":{"type":"array","description":"Array of custom rules applied to the product's custom fields.","items":{"$ref":"#/components/schemas/CustomRule"}},"custom_fields":{"type":"array","description":"Array of custom fields attached to the product.","items":{"$ref":"#/components/schemas/CustomField"}},"created_date":{"type":"integer","description":"Timestamp of product creation in the store's timezone."},"last_edited":{"type":"integer","description":"Timestamp of the last product modification in the store's timezone."},"server_options":{"type":"array","description":"Array of server options to choose, will be sent if the delivery_method is  `server_choice`.","items":{"$ref":"#/components/schemas/ServerChoice"}},"actions":{"type":"object","description":"Array of different actions to execute, indexed by it's server ID.","additionalProperties":{"$ref":"#/components/schemas/Action"}},"currency":{"type":"string","description":"Currency in which all prices are expressed. Matches the requested `currency` parameter, or the store's default currency if not specified."}},"required":["id","name","slug","price","status","description","gallery","category","featured","stock","trial","server_choice","delivery_method","quantity","files","subscription","giftcard","enable_stock","cumul_sub","enable_trial","created_date","last_edited","actions"]},"Category":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the category."},"name":{"type":"string","description":"Name of the category."},"description":{"type":"string","description":"Description of the category."},"slug":{"type":"string","description":"URL-friendly name of the category."},"hide":{"type":"boolean","description":"Determines if the category is hidden."},"main_redirect":{"type":"boolean","description":"Redirect to home page if category is accessed."},"parent_id":{"type":"integer","format":"int64","description":"Parent category ID if this is a sub-category."}},"required":["id","name","slug","hide","main_redirect"]},"PurchaseLimit":{"type":"object","properties":{"purchase_times":{"type":"integer","description":"Maximum number of times the product can be purchased."},"type":{"type":"string","description":"Defines when the purchase limit applies.\n\nAccepted values:  \n- `every` → limit purchases to a recurring time period  \n- `only` → limit purchases permanently\n"},"cycle":{"type":"integer","description":"Number of time units before the purchase limit resets.\n\nExample:  \n- Limit purchases to 1 time every 1 month  \n- Limit purchases to 1 time every 3 months\n\nAccepted ranges: 1–99 for days, 1–52 for weeks, 1–12 for months, 1–1 for years\n"},"periodicity":{"type":"string","description":"Unit of time used to define the purchase limit.\n\nAccepted values: `day`, `week`, `month`, `year`\n"}},"required":["purchase_times","type","cycle","periodicity"]},"CustomRule":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the custom rule."},"order":{"type":"integer","format":"int64","description":"Priority order of the custom rule."},"name":{"type":"string","description":"Name of the custom rule."},"type":{"type":"string","description":"Type of custom rule. Accepted values: `number_limit`"},"min":{"type":"integer","format":"int64","description":"Minimum value if the rule type is `number_limit`."},"max":{"type":"integer","format":"int64","description":"Maximum value if the rule type is `number_limit`."},"fields":{"type":"array","description":"IDs of custom fields affected by this rule.","items":{"type":"number","format":"int64"}}},"required":["id","order","name","type"]},"CustomField":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the custom field."},"order":{"type":"integer","format":"int64","description":"Priority order of the custom field."},"name":{"type":"string","description":"Name of the custom field."},"type":{"type":"string","description":"Type of custom field. Accepted values: `text`, `checkbox`, `number`, `selection`\n"},"marker":{"type":"string","description":"Placeholder marker used in commands."},"if_not_filled":{"type":"string","description":"Behavior if field is left empty. Accepted values: `do_not_execute`, `remove_marker`, `use_default`"},"default_value":{"type":"string","description":"Default value used if `if_not_filled` is set to `use_default`."},"required":{"type":"boolean","description":"Indicates if the custom field is mandatory."},"minimum":{"type":"integer","description":"Minimum value if field type is `number`."},"maximum":{"type":"integer","description":"Maximum value if field type is `number`."},"step":{"type":"integer","description":"Increment step if field type is `number`."},"number_type":{"type":"string","description":"Specifies number input type. Accepted values: `number`, `range`"},"price":{"type":"integer","description":"Additional price added to product if field is selected."},"options":{"type":"array","items":{"$ref":"#/components/schemas/CustomFieldOption"},"description":"Options available if field type is `selection`."}},"required":["id","order","name","type","required"]},"CustomFieldOption":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier of the option."},"order":{"type":"integer","description":"Priority order of the option."},"name":{"type":"string","description":"Name of the option."},"value":{"type":"integer","description":"Value corresponding to the option."},"price":{"type":"integer","description":"Price adjustment if option is selected."}},"required":["id","order","name","value","price"]},"ServerChoice":{"type":"object","properties":{"id":{"type":"integer","description":"Server ID"},"name":{"type":"string","description":"Server Name"}},"required":["id","name"]},"Action":{"type":"object","properties":{"payment_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}},"refund_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}},"renewal_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}},"expire_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}}}},"SimpleServerCommand":{"type":"object","properties":{"str":{"description":"Content of the command to be executed"},"event":{"description":"Event triggering the execution of the command. Can take the following values: `Execute`, `Must be online`"}}}}},"paths":{"/store/product/{id}":{"get":{"tags":["Products"],"summary":"Get product by ID","description":"Retrieves detailed information about a single product identified by `id`.\nSet `details` to `true` for full product details.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `read-products`.\n","operationId":"getProductById","parameters":[{"name":"id","in":"path","required":true,"description":"The ID of the product to retrieve.","schema":{"type":"integer"}},{"name":"details","in":"query","required":false,"description":"Enable detailed response.","schema":{"type":"boolean"}},{"name":"currency","in":"query","description":"Display currency code (optional). Supported currencies: GBP, USD, EUR, CAD, AUD, CHF. If omitted, prices are displayed in store currency. Converts all product prices (price, old_price, min_donation) and custom field prices.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Product found successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"400":{"description":"Error in your request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"403":{"description":"Didn't provide a valid Tip4Serv API Key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"404":{"description":"Couldn't find the product with that id.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"integer"}}}}}}}}}}}
```

## Delete the specified product.

> Delete the specified product.\
> \
> \*\*Authorization:\*\*\
> \- Requires a valid JWT Bearer token.\
> \- The token must include the permission: \`update-products\`.<br>

```json
{"openapi":"3.0.4","info":{"title":"Tip4Serv API","version":"1.0.12"},"tags":[{"name":"Products","description":"Operations related to products"}],"servers":[{"url":"https://api.tip4serv.com/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT or Partner API key","description":"Use a Tip4Serv JWT for standard store access, or a Partner API key as a Bearer token for Partner Connect. Partner Connect operations also require the `store_id` and `integration_key` query parameters and the relevant seller-approved permission."}}},"paths":{"/store/product/{id}":{"delete":{"tags":["Products"],"summary":"Delete the specified product.","description":"Delete the specified product.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `update-products`.\n","operationId":"deleteProduct","parameters":[{"name":"id","in":"path","required":true,"description":"the ID of the product to update.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"status":{"type":"number"}}}}}},"400":{"description":"Error in your request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"403":{"description":"Missing or invalid Tip4Serv API Key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"number"}}}}}},"409":{"description":"Conflicting conditions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"number"}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"number"}}}}}}}}}}}
```

## Update a product

> Update a new product in your store.\
> \
> \*\*Authorization:\*\*\
> \- Requires a valid JWT Bearer token.\
> \- The token must include the permission: \`update-products\`.<br>

```json
{"openapi":"3.0.4","info":{"title":"Tip4Serv API","version":"1.0.12"},"tags":[{"name":"Products","description":"Operations related to products"}],"servers":[{"url":"https://api.tip4serv.com/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT or Partner API key","description":"Use a Tip4Serv JWT for standard store access, or a Partner API key as a Bearer token for Partner Connect. Partner Connect operations also require the `store_id` and `integration_key` query parameters and the relevant seller-approved permission."}},"schemas":{"UpdateProduct":{"type":"object","properties":{"name":{"type":"string","description":"Name of the product."},"status":{"type":"boolean","description":"Indicates whether the product is enabled. If not specified, the product will be automatically enabled","default":true},"slug":{"type":"string","description":"URL-friendly name of the product. If not specified will be automatically calculated."},"price":{"type":"integer","description":"Current price of the product after any applicable discounts, in the store's currency."},"recurring_discount":{"type":"boolean","description":"Indicates whether the discount is applied on each occurrence of the subscription."},"donation":{"type":"boolean","description":"Indicates if the product is a donation-type product, this allow the user to choose the amount of the donation,  `price` therefore defines the minimum donation amount."},"description":{"type":"string","description":"Full description of the product."},"youtube":{"type":"string","description":"URL of the video associated with the product."},"category":{"oneOf":[{"type":"integer"},{"$ref":"#/components/schemas/Category"}],"description":"Category the product belongs to (integer or full category object if details are enabled). If not specified, the product will be automatically added to the default category."},"featured":{"type":"boolean","description":"Indicates whether the product is featured. If not specified will be set to false."},"enable_stock":{"type":"integer","description":"Enable a system of limited stock for this product. By default if not set, no stock system will be implemented."},"stock":{"type":"integer","description":"Available stock of the product. `enable_stock` must be set to true first."},"enable_trial":{"type":"boolean","description":"Indicates whether trial days are enabled."},"trial":{"type":"integer","description":"Number of trial days available for this product. If not specified no trial period will be set. `enable_trial` must first be set to true."},"renewal_start":{"type":"string","description":"If trial days are enabled, defines when commands in the \"Do this after each renewal payment\" event start.\n\nAccepted values:  \n`first_payment`, `second_payment`\n"},"quantity":{"type":"boolean","description":"Indicates whether the customer can select the quantity to purchase. If not specified customers will by default be able to purchase the product multiple times."},"cmd_multiplier":{"type":"boolean","description":"If quantity is selectable, determines whether commands are multiplied by the chosen quantity. If set to true each command will be executed \"quantity\" times, by default `cmd_multiplier` is set to false."},"subscription":{"type":"boolean","description":"Indicates whether the product is a subscription. If not specified the product will not be an subscription."},"disable_giftcard_payments":{"type":"boolean","description":"Indicates whether the product can be purchased with a giftcard. If not specified this option will be set to false by default. If set to true a customer won't be able to purchase this product with a giftcard.\n"},"giftcard":{"type":"boolean","description":"Indicates whether the product supports gift cards. If not specified the product will not offer any giftcard."},"giftcard_expiration":{"type":"boolean","description":"Indicates whether the generated gift card will eventually expire."},"giftcard_expiration_duration_periodicity":{"type":"string","description":"Unit of time for the gift card expiration duration.\n\nPossible values:  \n- `day` – duration in days   - `week` – duration in weeks   - `month` – duration in months   - `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the giftcard will expire 3 months after the purchase.\n"},"giftcard_expiration_period_num":{"type":"integer","description":"Number of `duration_periodicity` units before the giftcard expires.\nExamples:  \n- Giftcard expires after 3 months  \n- Giftcard expires after 1 year\nExample: `period_num: 3` → charge every 3 months\n"},"custom_fields":{"type":"array","description":"Array of custom fields attached to the product.","items":{"$ref":"#/components/schemas/CreateCustomField"}},"custom_rules":{"type":"array","description":"Array of custom rules applied to the product's custom fields.","items":{"$ref":"#/components/schemas/CreateCustomRule"}},"subscription_cycle":{"type":"string","description":"Determines whether subscriptions are recurring or expire by default. Accepted values:   `each`, `expire`"},"cumul_sub":{"type":"boolean","description":"If set to false prevents customers from subscribing to the same product multiple times."},"onetime_sub":{"type":"boolean","description":"Allows customers to purchase the product for a single billing cycle without subscribing."},"duration_periodicity":{"type":"string","description":"Unit of time for the subscription duration.\n\nPossible values:  \n- `day` – duration in days  \n- `week` – duration in weeks  \n- `month` – duration in months  \n- `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the subscription lasts 3 months.\n"},"period_num":{"type":"number","description":"Number of `duration_periodicity` units before the subscription expires or the next charge occurs.\n\nExamples:  \n- Charge the customer every 3 months  \n- Charge the customer every 1 year\n\nAccepted ranges:  \n- 1–99 for days  \n- 1–52 for weeks  \n- 1–12 for months  \n- 1–1 for years\n\nExample: `period_num: 3` → charge every 3 months\n"},"purchase_limit":{"$ref":"#/components/schemas/PurchaseLimit","description":"Rules limiting the number of times a customer can purchase the product."},"actions":{"type":"object","description":"Array of different actions to execute, indexed by it's server ID. By default if not specified no actions will be executed","additionalProperties":{"$ref":"#/components/schemas/Action"}}}},"Category":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the category."},"name":{"type":"string","description":"Name of the category."},"description":{"type":"string","description":"Description of the category."},"slug":{"type":"string","description":"URL-friendly name of the category."},"hide":{"type":"boolean","description":"Determines if the category is hidden."},"main_redirect":{"type":"boolean","description":"Redirect to home page if category is accessed."},"parent_id":{"type":"integer","format":"int64","description":"Parent category ID if this is a sub-category."}},"required":["id","name","slug","hide","main_redirect"]},"CreateCustomField":{"type":"object","properties":{"order":{"type":"integer","format":"int64","description":"Priority order of the custom field. If no order is provided, this custom field will have the smallest priority."},"name":{"type":"string","description":"Name of the custom field."},"type":{"type":"string","description":"Type of custom field. Accepted values: `text`, `checkbox`, `number`, `selection`\n"},"marker":{"type":"string","description":"Placeholder marker used in commands."},"if_not_filled":{"type":"string","description":"Behavior if field is left empty. Accepted values: `do_not_execute`, `remove_marker`, `use_default`"},"default_value":{"type":"string","description":"Default value used if `if_not_filled` is set to `use_default`."},"required":{"type":"boolean","description":"Indicates if the custom field is mandatory."},"minimum":{"type":"integer","description":"Minimum value if field type is `number`."},"maximum":{"type":"integer","description":"Maximum value if field type is `number`."},"step":{"type":"integer","description":"Increment step if field type is `number`."},"number_type":{"type":"string","description":"Specifies number input type. Accepted values: `number`, `range`"},"price":{"type":"integer","description":"Additional price added to product if field is selected."},"options":{"type":"array","items":{"$ref":"#/components/schemas/CreateCustomFieldOption"},"description":"Options available if field type is `selection`."}},"required":["name","type","required"]},"CreateCustomFieldOption":{"type":"object","properties":{"name":{"type":"string","description":"Name of the option."},"value":{"type":"integer","description":"Value corresponding to the option."},"price":{"type":"integer","description":"Price adjustment if option is selected."}},"required":["name","value","price"]},"CreateCustomRule":{"type":"object","properties":{"name":{"type":"string","description":"Name of the custom rule."},"type":{"type":"string","description":"Type of custom rule. Accepted values: `number_limit`"},"min":{"type":"integer","format":"int64","description":"Minimum value if the rule type is `number_limit`."},"max":{"type":"integer","format":"int64","description":"Maximum value if the rule type is `number_limit`."},"fields":{"type":"array","description":"IDs of custom fields affected by this rule.","items":{"type":"number","format":"int64"}}},"required":["name","type"]},"PurchaseLimit":{"type":"object","properties":{"purchase_times":{"type":"integer","description":"Maximum number of times the product can be purchased."},"type":{"type":"string","description":"Defines when the purchase limit applies.\n\nAccepted values:  \n- `every` → limit purchases to a recurring time period  \n- `only` → limit purchases permanently\n"},"cycle":{"type":"integer","description":"Number of time units before the purchase limit resets.\n\nExample:  \n- Limit purchases to 1 time every 1 month  \n- Limit purchases to 1 time every 3 months\n\nAccepted ranges: 1–99 for days, 1–52 for weeks, 1–12 for months, 1–1 for years\n"},"periodicity":{"type":"string","description":"Unit of time used to define the purchase limit.\n\nAccepted values: `day`, `week`, `month`, `year`\n"}},"required":["purchase_times","type","cycle","periodicity"]},"Action":{"type":"object","properties":{"payment_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}},"refund_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}},"renewal_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}},"expire_command":{"type":"array","description":"Commands which are executed when a payment is made.","items":{"$ref":"#/components/schemas/SimpleServerCommand"}}}},"SimpleServerCommand":{"type":"object","properties":{"str":{"description":"Content of the command to be executed"},"event":{"description":"Event triggering the execution of the command. Can take the following values: `Execute`, `Must be online`"}}},"Product":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier of the product."},"name":{"type":"string","description":"Name of the product."},"status":{"type":"boolean","description":"Indicates whether the product is enabled."},"slug":{"type":"string","description":"URL-friendly name of the product."},"price":{"type":"integer","description":"Current price of the product after any applicable discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used."},"old_price":{"type":"integer","description":"Original price of the product without discounts. Expressed in the store's currency, or the requested display currency if the `currency` parameter was used."},"percent_off":{"type":"integer","description":"Percentage off from the original price if a discount applies."},"recurring_discount":{"type":"boolean","description":"Indicates whether the discount is applied on each occurrence of the subscription."},"discount_end":{"type":"integer","description":"Timestamp of the discount expiration. *(expressed in the store timezone)*"},"donation":{"type":"boolean","description":"Indicates if the product is a donation-type product, this allow the user to choose the amount of the donation,  `price` therefore defines the minimum donation amount."},"min_donation":{"type":"number","description":"Minimum donation amount (only present if donation is true). If currency parameter is used, this value is converted to the requested currency."},"description":{"type":"string","description":"Full description of the product."},"gallery":{"type":"array","description":"List of all images related to the product.","items":{"type":"string"}},"youtube":{"type":"string","description":"URL of the video associated with the product."},"category":{"oneOf":[{"type":"integer"},{"$ref":"#/components/schemas/Category"}],"description":"Category the product belongs to (integer or full category object if details are enabled)."},"featured":{"type":"boolean","description":"Indicates whether the product is featured."},"stock":{"type":"integer","description":"Available stock of the product."},"trial":{"type":"integer","description":"Number of trial days available for this product."},"renewal_start":{"type":"string","description":"If trial days are enabled, defines when commands in the \"Do this after each renewal payment\" event start.\n\nAccepted values:  \n`first_payment`, `second_payment`\n"},"delivery_method":{"type":"string","description":"Indicates the delivery method used to deliver the actions of the product. Can\nPossible values:\n- `all_servers` : will deliver the product commands on every servers. - `server_choice` : the user will be prompted to choose on which server he wish to receive his product. - `auto_detect` : Tip4Serv will automatically detect on which server the user is connected, and deliver only on this server.\nIf no option is specified, the default option will be set to `all_servers`"},"server_choice":{"type":"boolean","description":"Indicates whether the customer can select the server for product delivery.\n⚠ This flag is deprecated, please use delivery_mode instead, to know the delivery method of the actions."},"quantity":{"type":"boolean","description":"Indicates whether the customer can select the quantity to purchase."},"cmd_multiplier":{"type":"boolean","description":"If quantity is selectable, determines whether commands are multiplied by the chosen quantity."},"files":{"type":"boolean","description":"Indicates if the product provides downloadable files upon purchase."},"subscription":{"type":"boolean","description":"Indicates whether the product is a subscription."},"disable_giftcard_payments":{"type":"boolean","description":"Indicates whether the product can be purchased with a giftcard. If not specified this option will be set to false by default. If set to true a customer won't be able to purchase this product with a giftcard.\n"},"giftcard":{"type":"boolean","description":"Indicates whether the product supports gift cards."},"giftcard_expiration":{"type":"boolean","description":"Indicates whether the generated gift card will eventually expire."},"giftcard_expiration_duration_periodicity":{"type":"string","description":"Unit of time for the gift card expiration duration.\n\nPossible values:  \n- `day` – duration in days   - `week` – duration in weeks   - `month` – duration in months   - `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the giftcard will expire 3 months after the purchase.\n"},"giftcard_expiration_period_num":{"type":"integer","description":"Number of `duration_periodicity` units before the giftcard expires.\nExamples:  \n- Giftcard expires after 3 months  \n- Giftcard expires after 1 year\nExample: `period_num: 3` → charge every 3 months\n"},"enable_stock":{"type":"boolean","description":"Indicates if stock management is enabled for the product."},"subscription_cycle":{"type":"string","description":"Determines whether subscriptions are recurring or expire by default. Accepted values:   `each`, `expire`"},"cumul_sub":{"type":"boolean","description":"If set to false prevents customers from subscribing to the same product multiple times."},"onetime_sub":{"type":"boolean","description":"Allows customers to purchase the product for a single billing cycle without subscribing."},"enable_trial":{"type":"boolean","description":"Indicates whether trial days are enabled."},"purchase_limit":{"$ref":"#/components/schemas/PurchaseLimit","description":"Rules limiting the number of times a customer can purchase the product."},"duration_periodicity":{"type":"string","description":"Unit of time for the subscription duration.\n\nPossible values:  \n- `day` – duration in days  \n- `week` – duration in weeks  \n- `month` – duration in months  \n- `year` – duration in years\n\nExample: If `duration_periodicity = month` and `period_num = 3`, the subscription lasts 3 months.\n"},"period_num":{"type":"number","description":"Number of `duration_periodicity` units before the subscription expires or the next charge occurs.\n\nExamples:  \n- Charge the customer every 3 months  \n- Charge the customer every 1 year\n\nAccepted ranges:  \n- 1–99 for days  \n- 1–52 for weeks  \n- 1–12 for months  \n- 1–1 for years\n\nExample: `period_num: 3` → charge every 3 months\n"},"custom_rules":{"type":"array","description":"Array of custom rules applied to the product's custom fields.","items":{"$ref":"#/components/schemas/CustomRule"}},"custom_fields":{"type":"array","description":"Array of custom fields attached to the product.","items":{"$ref":"#/components/schemas/CustomField"}},"created_date":{"type":"integer","description":"Timestamp of product creation in the store's timezone."},"last_edited":{"type":"integer","description":"Timestamp of the last product modification in the store's timezone."},"server_options":{"type":"array","description":"Array of server options to choose, will be sent if the delivery_method is  `server_choice`.","items":{"$ref":"#/components/schemas/ServerChoice"}},"actions":{"type":"object","description":"Array of different actions to execute, indexed by it's server ID.","additionalProperties":{"$ref":"#/components/schemas/Action"}},"currency":{"type":"string","description":"Currency in which all prices are expressed. Matches the requested `currency` parameter, or the store's default currency if not specified."}},"required":["id","name","slug","price","status","description","gallery","category","featured","stock","trial","server_choice","delivery_method","quantity","files","subscription","giftcard","enable_stock","cumul_sub","enable_trial","created_date","last_edited","actions"]},"CustomRule":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the custom rule."},"order":{"type":"integer","format":"int64","description":"Priority order of the custom rule."},"name":{"type":"string","description":"Name of the custom rule."},"type":{"type":"string","description":"Type of custom rule. Accepted values: `number_limit`"},"min":{"type":"integer","format":"int64","description":"Minimum value if the rule type is `number_limit`."},"max":{"type":"integer","format":"int64","description":"Maximum value if the rule type is `number_limit`."},"fields":{"type":"array","description":"IDs of custom fields affected by this rule.","items":{"type":"number","format":"int64"}}},"required":["id","order","name","type"]},"CustomField":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier of the custom field."},"order":{"type":"integer","format":"int64","description":"Priority order of the custom field."},"name":{"type":"string","description":"Name of the custom field."},"type":{"type":"string","description":"Type of custom field. Accepted values: `text`, `checkbox`, `number`, `selection`\n"},"marker":{"type":"string","description":"Placeholder marker used in commands."},"if_not_filled":{"type":"string","description":"Behavior if field is left empty. Accepted values: `do_not_execute`, `remove_marker`, `use_default`"},"default_value":{"type":"string","description":"Default value used if `if_not_filled` is set to `use_default`."},"required":{"type":"boolean","description":"Indicates if the custom field is mandatory."},"minimum":{"type":"integer","description":"Minimum value if field type is `number`."},"maximum":{"type":"integer","description":"Maximum value if field type is `number`."},"step":{"type":"integer","description":"Increment step if field type is `number`."},"number_type":{"type":"string","description":"Specifies number input type. Accepted values: `number`, `range`"},"price":{"type":"integer","description":"Additional price added to product if field is selected."},"options":{"type":"array","items":{"$ref":"#/components/schemas/CustomFieldOption"},"description":"Options available if field type is `selection`."}},"required":["id","order","name","type","required"]},"CustomFieldOption":{"type":"object","properties":{"id":{"type":"integer","description":"Unique identifier of the option."},"order":{"type":"integer","description":"Priority order of the option."},"name":{"type":"string","description":"Name of the option."},"value":{"type":"integer","description":"Value corresponding to the option."},"price":{"type":"integer","description":"Price adjustment if option is selected."}},"required":["id","order","name","value","price"]},"ServerChoice":{"type":"object","properties":{"id":{"type":"integer","description":"Server ID"},"name":{"type":"string","description":"Server Name"}},"required":["id","name"]}}},"paths":{"/store/product/{id}":{"patch":{"tags":["Products"],"summary":"Update a product","description":"Update a new product in your store.\n\n**Authorization:**\n- Requires a valid JWT Bearer token.\n- The token must include the permission: `update-products`.\n","operationId":"updateProduct","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProduct"}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"The ID of the product to update.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"400":{"description":"Error in your request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"integer"}}}}}},"403":{"description":"Missing or invalid Tip4Serv API Key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"number"}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"status":{"type":"number"}}}}}}}}}}}
```
