Products and files
Update product
/ v1 / products / {product_id} Changes the fields that you send. All other fields stay.
statuslivepublishes the product. This needs a finished account setup and content.drafthides it.contentreplaces all content blocks. CallGET /v1/products/{product_id}first and send back the blocks that should stay, with theirfile_id.nullremoves an optional value:compare_at_price,intro_price,limited_offer, dates, limits,url_slugandbanner.course_idchanges the course that buyers of a course product get.
The fields have the same names and formats as in GET /v1/products/{product_id}.
Authorization
-
Authorizationstring header requiredBearer tnt_…· A personal API key (tnt_...). Create it in the Tentary app on the page AI & API. Introduction
Path parameters
-
product_idinteger requiredThe id from list_products.
min
1Example:105
Body application/json
-
statusstringlive = buyers can see and buy it. draft = hidden.
Allowed values:
draftlive -
namestringProduct name.
min length
1max length255 -
pricenumber | string can be nullAmount in the account currency, like 49 or 19.99. 0 = free. Paid prices start at 1.00. For external: the price shown on the card.
min
0pattern^[0-9]{1,9}(\.[0-9]{1,2})?$ -
billingstringDefault one_time.
Allowed values:
one_timesubscription -
billing_interval_monthsinteger can be nullsubscription: months between payments, default 1.
min
1max12 -
intro_pricenumber | string can be nullsubscription: price of the first period, less than price.
min
0pattern^[0-9]{1,9}(\.[0-9]{1,2})?$ -
installment_plansarray of objectone_time: payment plans that buyers can choose. [] removes them.
max items
5Show 2 fields Hide fields
-
countinteger requiredmin
2max100 -
amountnumber | string requiredPer installment. Amount in the account currency, like 49 or 19.99.
pattern
^[0-9]{1,9}(\.[0-9]{1,2})?$
-
-
compare_at_pricenumber | string can be nullone_time: crossed-out old price, higher than price. While a limited_offer runs, price is the crossed-out price instead; compare_at_price shows again when the offer ends.
pattern
^[0-9]{1,9}(\.[0-9]{1,2})?$ -
limited_offerobject can be nullone_time: a lower price for a time. While it runs, the sales page and the checkout show price crossed out and the offer price. Times with a zone; convert the seller's local time with timezone from get_account_overview.
Show 4 fields Hide fields
-
pricenumber | string requiredpattern
^[0-9]{1,9}(\.[0-9]{1,2})?$ -
starts_atstring requiredLike 2026-11-26T23:00:00Z.
-
ends_atstring requiredLike 2026-11-30T22:59:00Z.
-
countdownobject can be nullA countdown to ends_at on the sales page and the checkout while the offer runs (made by JavaScript in the browser). null = none. Left out = unchanged. An object replaces the whole countdown.
Show 4 fields Hide fields
-
stylestring requiredclassic and slim: a bar at the top (sticky: it stays while buyers scroll). card_*: a box next to the price.
Allowed values:
classicclassic_stickyslimslim_stickycard_classiccard_slimcard_special_1 -
textstring can be nullShort text in the countdown, like "Launch price ends in".
max length
255 -
colorstringBackground, hex like #ff4400 (default).
-
secondary_colorstring can be nullBars: the text color (default white). Cards: the card background (default #1a1a1a).
-
-
-
description_htmlstringSales page text as HTML (p, h1-h4, strong, em, ul, ol, li, a, img, blockquote; a with class "button" is a button). The page always has its own buy button. A buy button in the text links to the url of the product + "/checkout" (create_product and get_product give url); there is no #buy anchor.
max length
200000 -
checkout_description_htmlstringExtra text only on the checkout page, HTML. Not for external.
max length
20000 -
checkout_banner_urlstring can be nullBanner image only on the checkout page, above the product title (it replaces the small product image). Recommended 1200 x 300 px. The image_url from finish_image, or a public image URL that Tentary copies. Not for external.
max length
2048 -
imagesarray of stringProduct images on the sales page as https URLs: the image_url from finish_image (for an image on your disk), or a public image URL that Tentary copies (PNG, JPG, GIF, WebP, at most 10 MB). The first is the cover. YouTube links show as video. Replaces all images.
max length
2048max items20 -
contentarray of objectdownload: what buyers get, in order. booking: what buyers get in addition to the appointment. Replaces all content.
max items
100Show 8 fields Hide fields
-
typestring requiredtext: formatted text. image: shows the image. video: an uploaded video in the player (streamed, converted some minutes after its first use). audio: an audio player. file: a download. video_embed: a YouTube, Vimeo or Loom video. button: a link button. image, video, audio and file need file_id. Type, name and description are stored with the file: one file shows the same way in every product and lesson.
Allowed values:
textimagevideoaudiofilevideo_embedbutton -
htmlstringtext: the text as HTML (p, h1-h4, strong, em, ul, ol, li, a, img, blockquote). Placeholders for the buyer: %FIRST_NAME%, %FULL_NAME%, %EMAIL%, %PRODUCT_TITLE%, %VARIANT_TITLE%, %ORDER_ID%, %ACCESS_LINK[Text]%, %ACCESS_LINK_BUTTON[Text]%, %SELLER_NAME%, %SELLER_SUPPORT_EMAIL%; bookings also %ORDER_BOOKING_FROM%, %ORDER_BOOKING_TO%, %ORDER_BOOKING_ZOOM_LINK%.
max length
65535 -
urlstringvideo_embed: YouTube, Vimeo or Loom link. button: the link target.
max length
2048 -
labelstringbutton: the button text.
max length
250 -
file_idintegerimage, video, audio, file: a file from upload_file, or a file_id from get_product or get_lesson content.
min
1 -
namestringimage, video, audio, file: the name of the file (file: shown above the download).
min length
1max length250 -
descriptionstringfile: plain text under the download. audio: the title above the player.
max length
65535 -
folderstring can be nullOptional folder name. Blocks with the same folder show together. Not in lessons.
max length
250
-
-
link_urlstring can be nulllink: the link that buyers get.
max length
2048 -
access_text_htmlstring can be nulllink: text that buyers see after purchase. bundle: extra details for the buyers. HTML. Takes the placeholders of text blocks.
max length
65535 -
bundle_itemsarray of object can be nullbundle: the products that buyers get, from list_products (live or draft; no bundles or bookings). For a product with variants, give the variant_id of one variant. Replaces the list. Needed to go live.
max items
100Show 2 fields Hide fields
-
product_idinteger requiredmin
1 -
variant_idinteger can be nullOnly for a product with variants.
min
1
-
-
external_urlstring can be nullexternal: where buyers buy it.
max length
2048 -
course_idintegercourse: the course that buyers get (from list_courses or create_course). Needed to go live.
min
1 -
variantsarray of object can be nulldownload, link and course: options that buyers choose at checkout, each with its own name, price, stock and content (download: content, link: link_url and access_text_html, course: course_id). Replaces the list: a variant with id stays and changes (fields that you leave out stay), one without id is new, a variant that is not in the list is removed (its buyers keep access). [] or null removes all variants. With variants, price is the lowest variant price; billing must be one_time, without installment_plans, limited_offer and compare_at_price; a download product has no content of its own.
max items
50Show 8 fields Hide fields
-
idintegerAn existing variant (from get_product). Leave out for a new variant.
min
1 -
namestringNeeded for a new variant.
min length
1max length255 -
pricenumber | stringAmount in the account currency, like 49 or 19.99. 0 = free. Needed for a new variant.
min
0pattern^[0-9]{1,9}(\.[0-9]{1,2})?$ -
stock_limitinteger can be nullHow many can be sold. null or 0 = no limit.
min
0 -
contentarray of objectdownload: what buyers of this variant get. Replaces its content.
max items
100Show 8 fields Hide fields
-
typestring requiredtext: formatted text. image: shows the image. video: an uploaded video in the player (streamed, converted some minutes after its first use). audio: an audio player. file: a download. video_embed: a YouTube, Vimeo or Loom video. button: a link button. image, video, audio and file need file_id. Type, name and description are stored with the file: one file shows the same way in every product and lesson.
Allowed values:
textimagevideoaudiofilevideo_embedbutton -
htmlstringtext: the text as HTML (p, h1-h4, strong, em, ul, ol, li, a, img, blockquote). Placeholders for the buyer: %FIRST_NAME%, %FULL_NAME%, %EMAIL%, %PRODUCT_TITLE%, %VARIANT_TITLE%, %ORDER_ID%, %ACCESS_LINK[Text]%, %ACCESS_LINK_BUTTON[Text]%, %SELLER_NAME%, %SELLER_SUPPORT_EMAIL%; bookings also %ORDER_BOOKING_FROM%, %ORDER_BOOKING_TO%, %ORDER_BOOKING_ZOOM_LINK%.
max length
65535 -
urlstringvideo_embed: YouTube, Vimeo or Loom link. button: the link target.
max length
2048 -
labelstringbutton: the button text.
max length
250 -
file_idintegerimage, video, audio, file: a file from upload_file, or a file_id from get_product or get_lesson content.
min
1 -
namestringimage, video, audio, file: the name of the file (file: shown above the download).
min length
1max length250 -
descriptionstringfile: plain text under the download. audio: the title above the player.
max length
65535 -
folderstring can be nullOptional folder name. Blocks with the same folder show together. Not in lessons.
max length
250
-
-
link_urlstring can be nulllink: the link that buyers of this variant get.
max length
2048 -
access_text_htmlstring can be nulllink: text that buyers of this variant see after purchase, HTML. Takes the placeholders of text blocks.
max length
65535 -
course_idintegercourse: the course that buyers of this variant get. Needed for a new variant.
min
1
-
-
marketing_emailsbooleanSubscribe buyers to the marketing e-mails (always on for newsletter).
-
ebookbooleanTreat as e-publication (e-book) for VAT.
-
pdf_stampbooleanStamp PDFs with the buyer's e-mail address.
-
login_protectionbooleanBuyers must log in to open the product.
-
show_in_searchbooleanShow the sales page in Google.
-
hide_in_shopbooleanDo not show the product on the shop page.
-
coupon_fieldbooleanShow the coupon field at checkout (default true).
-
stock_limitinteger can be nullHow many can be sold. null or 0 = no limit.
min
0 -
buy_button_textstringText of the buy button. Empty = default.
max length
30 -
url_slugstring can be nullOwn URL part: shop URL/p/<url_slug>. Lowercase letters, digits and hyphens.
max length
120 -
access_daysinteger can be nullAccess ends this many days after purchase (3 to 9999). null or 0 = no end.
min
0max9999 -
access_starts_onstring can be nullBuyers get access from this day at the earliest (for example the start of a program). Before it they wait. null = at once. Not for newsletter and external.
pattern
^[0-9]{4}-[0-9]{2}-[0-9]{2}$ -
lead_magnetbooleanA free product that grows the e-mail list: buyers first confirm the marketing e-mails, then they get the product. Needs price 0 and billing one_time, and turns on marketing_emails. Not for newsletter, booking and external.
-
withdrawal_daysintegerWithdrawal period shown at checkout.
Allowed values:
01430 -
available_fromstring can be nullFirst day of sale.
pattern
^[0-9]{4}-[0-9]{2}-[0-9]{2}$ -
available_untilstring can be nullLast day of sale.
pattern
^[0-9]{4}-[0-9]{2}-[0-9]{2}$
Response
Fields of the answer with status 200. Errors always have the same format, see Errors.
The short form. get_product has all fields.
-
idintegerThe ID.
-
namestringThe name.
-
typestringThe type.
Allowed values:
downloadlinknewsletterbookingcoursebundleexternal -
statusstringarchived = deleted.
Allowed values:
livedraftarchived -
urlstring<uri>Sales page.
-
admin_urlstring<uri>The page in the Tentary app.
-
notestringWhat to do next.