Products and files
Create product
/ v1 / products Creates a product as a draft, so buyers cannot see it yet. You set the type, name, price and billing, sales page text, images, content and settings.
The type decides what buyers get:
download: content blocks (texts, images, videos, audio, files, video links, buttons).link: alink_urland/or anaccess_text_htmlafter the purchase.newsletter: a sign-up for the email list, free or paid.external: sold on another site, atexternal_url.course: sells a course. Create the course withPOST /v1/coursesfirst, then give itscourse_id. To sell the same course again, use the samecourse_id. Do not create a copy.bundle: other products together, inbundle_items.
download, link and course can have variants. Bookings can only be created in the Tentary app.
- Images and the banner are copied from their URLs. A YouTube link in
imagesshows as a video. - For files, call
POST /v1/filesfirst and use thefile_idin a file block. - To publish, call
PATCH /v1/products/{product_id}withstatuslive.
Authorization
-
Authorizationstring header requiredBearer tnt_…· A personal API key (tnt_...). Create it in the Tentary app on the page AI & API. Introduction
Body application/json
-
typestring requiredThe product type (see above). update_product cannot change it.
Allowed values:
downloadlinknewsletterexternalcoursebundle -
namestring requiredProduct name.
min length
1max length255 -
pricenumber | stringAmount 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_monthsintegersubscription: months between payments, default 1.
min
1max12 -
intro_pricenumber | stringsubscription: 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 | stringone_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_offerobjectone_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_urlstringBanner 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_urlstringlink: the link that buyers get.
max length
2048 -
access_text_htmlstringlink: 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 objectbundle: 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_urlstringexternal: 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 objectdownload, 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_limitintegerHow many can be sold. null or 0 = no limit.
min
0 -
buy_button_textstringText of the buy button. Empty = default.
max length
30 -
url_slugstringOwn URL part: shop URL/p/<url_slug>. Lowercase letters, digits and hyphens.
max length
120 -
access_daysintegerAccess ends this many days after purchase (3 to 9999). null or 0 = no end.
min
0max9999 -
access_starts_onstringBuyers 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_fromstringFirst day of sale.
pattern
^[0-9]{4}-[0-9]{2}-[0-9]{2}$ -
available_untilstringLast 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.