TEASEDocs
На русском

Хранилище контента

Индексируйте, ищите и анализируйте своё хранилище OnlyFans — находите любое медиа за одно нажатие, видьте, что реально продаётся, и получайте подобранные по когортам рекомендации контента.

Хранилище контента — это поисковый, размеченный ИИ индекс каждого медиа-элемента в вашем хранилище OnlyFans, плюс аналитика поверх него. Как только ваше хранилище проиндексировано, вы можете найти любой клип или сет по названию или тегу за одно нажатие, вытащить целую папку как бандл и — что гораздо ценнее — читать, какой контент реально приносит выручку, что лежит без дела, где ваш спрос обгоняет предложение и какие невиданные части отправить данной когорте следующими.

Каждый endpoint ниже находится по адресу https://app.tease.link/api/admin/vault и аутентифицируется Bearer-al_live_* ключом. Все чтения требуют scope read; триггер сканирования и авто-тег требуют write. Каждый ответ — это JSON, привязанный к владельцу, выпустившему ключ — вы всегда видите только своё собственное хранилище.

Индекс хранилища строится и обновляется целиком на стороне TEASE. Вы никогда не загружаете нам медиа и вам никогда не нужно поддерживать индекс вручную — вы запускаете сканирование, затем читаете из него.

Как всё устроено


Сканировать и индексировать хранилище

Индексирование — это фоновая задача. Вы запускаете её, затем опрашиваете статус, пока он не устаканится. Сканирование идемпотентно — повторный запуск обновляет индекс, а не дублирует его.

Запустить сканирование

curl -X POST "https://app.tease.link/api/admin/vault/scan" \
  -H "Authorization: Bearer $TEASE_API_KEY"

Триггер сканирования не принимает тела или query-параметров.

{ "started": true, "already_running": false }

Если сканирование уже в процессе, вызов является no-op, и вы получаете { "started": false, "already_running": true }. Если ваш аккаунт OnlyFans ещё не подключён, вызов возвращает 400 с сообщением, говорящим вам сначала завершить подключение.

Опросить статус

curl "https://app.tease.link/api/admin/vault/scan/status" \
  -H "Authorization: Bearer $TEASE_API_KEY"
{
  "folders": 84,
  "items": 5120,
  "ai_tagged": 4870,
  "last_indexed_ts": 1751280000,
  "running": false,
  "last_error": ""
}
ПолеТипОписание
foldersintegerЧисло проиндексированных папок/альбомов.
itemsintegerЧисло проиндексированных медиа-элементов.
ai_taggedintegerСколько элементов уже несут ИИ-теги.
last_indexed_tsintegerUnix-секунды последнего успешного индекса. 0, если никогда не индексировалось.
runningbooleantrue, пока сканирование в процессе — опрашивайте, пока не перевернётся в false.
last_errorstringПусто при успехе; короткое сообщение, если последнее сканирование сбойнуло.

Индексирование — клиентская функция, а не API, который вы собираете

Как индекс строится из вашего аккаунта OnlyFans и как выводятся теги, обрабатывается целиком на стороне сервера. От вас не ожидается перечислять медиа или генерировать теги самостоятельно — запустите сканирование и читайте результаты.


Поиск по хранилищу

Мгновенный поиск по названию и тегу через индекс. Результаты возвращаются сгруппированными по папке, с любыми свободными (без папки) элементами, вынесенными отдельно, так что пикер контента панели может отрендерить дерево мгновенно.

curl "https://app.tease.link/api/admin/vault/search?q=lingerie&scope=all&limit=200" \
  -H "Authorization: Bearer $TEASE_API_KEY"

Query-параметры

ПолеТипОбязательноОписание
qstringнетПоисковый текст, сопоставляемый с названиями и тегами. Пусто возвращает всё (вплоть до limit).
scopestringнетall (по умолчанию), sorted (только элементы, разложенные в папку) или unsorted (свободные элементы).
limitintegerнетМакс. число возвращаемых элементов, 1–1000. По умолчанию 200.

Ответ

{
  "query": "lingerie",
  "scope": "all",
  "folders": [
    {
      "folder_id": "f_2291",
      "name": "Red lingerie set",
      "items": [
        {
          "media_id": "m_88120",
          "media_type": "photo",
          "folder_id": "f_2291",
          "folder_name": "Red lingerie set",
          "sorted": true,
          "title": "red set — teaser",
          "has_cover": true
        }
      ]
    }
  ],
  "loose": [],
  "counts": { "folders": 1, "items": 1 }
}
ПолеТипОписание
querystringЭхо поискового текста.
scopestringЭхо фильтра scope.
foldersarrayНайденные элементы, сгруппированные по их папке. См. форму элемента ниже.
loosearrayНайденные элементы, которые не находятся ни в одной папке.
counts.foldersintegerЧисло папок в результате.
counts.itemsintegerВсего найденных элементов.

Каждый элемент несёт: media_id, media_type (photo, video, gif, …), folder_id, folder_name, sorted (разложен ли он), title и has_cover (доступна ли миниатюра — см. обложки).

Поиск возвращает media_id-ы, никогда не байты медиа. Используйте media_id-ы, чтобы скомпоновать PPV в панели, или получите миниатюру из endpoint-а обложки.

Открыть папку

Вытащите каждый элемент в одной папке — действие «выбрать весь пак». Ответ включает плоский массив media_ids, готовый к вставке прямо в композер сообщений.

curl "https://app.tease.link/api/admin/vault/folder/f_2291" \
  -H "Authorization: Bearer $TEASE_API_KEY"
{
  "folder_id": "f_2291",
  "name": "Red lingerie set",
  "media_ids": ["m_88120", "m_88121", "m_88122"],
  "items": [
    { "media_id": "m_88120", "media_type": "photo", "title": "red set — teaser", "has_cover": true }
  ]
}
ПолеТипОписание
folder_idstringЗапрошенный id папки.
namestringИмя папки, или пусто, если неизвестно.
media_idsarrayКаждый id медиа в папке, по порядку.
itemsarrayПолная запись элемента для каждого id (та же форма, что у поиска).

Вытащить дроп

Папку также можно прочитать как дроп — её элементы сгруппированы по роли (video, photoset, bts, other) с заранее упорядоченным bundle_media_ids для отправки в одно касание «отправить весь дроп». Это естественная единица, которую продаёт чаттер.

curl "https://app.tease.link/api/admin/vault/drop/f_2291" \
  -H "Authorization: Bearer $TEASE_API_KEY"
{
  "folder_id": "f_2291",
  "name": "Red lingerie set",
  "cover_media_id": "m_88120",
  "roles": {
    "video":    { "count": 1, "media_ids": ["m_88130"] },
    "photoset": { "count": 8, "media_ids": ["m_88120", "m_88121"] },
    "bts":      { "count": 2, "media_ids": ["m_88140", "m_88141"] },
    "other":    { "count": 0, "media_ids": [] }
  },
  "bundle_media_ids": ["m_88130", "m_88120", "m_88121", "m_88140", "m_88141"],
  "counts": { "total": 11, "video": 1, "photoset": 8, "bts": 2, "other": 0 },
  "is_drop": true
}
ПолеТипОписание
cover_media_idstringПредлагаемая обложка для дропа.
rolesobjectЭлементы, разбитые на video, photoset, bts, other, каждый со счётчиком и id.
bundle_media_idsarrayВесь дроп в порядке отправки — вставьте прямо в композер.
countsobjecttotal плюс счётчик по каждой роли.
is_dropbooleanНепрозрачный флаг, который TEASE устанавливает, когда папка квалифицируется как дроп.

Обложки

Получите изображение-миниатюру для любого id медиа. Endpoint возвращает изображение-миниатюру (image/jpeg), так что направьте <img> прямо на него — обложка есть только у элементов, где has_cover равно true.

curl "https://app.tease.link/api/admin/vault/cover/m_88120" \
  -H "Authorization: Bearer $TEASE_API_KEY" \
  -o cover.jpg

Возвращает 404, когда у id медиа нет обложки. Endpoint всегда отдаёт миниатюру только для id медиа в вашем собственном хранилище.


Авто-тег бэклога

auto-tag запускает ИИ-тегирование по вашим нетегированным элементам, чтобы они стали поисковыми и начали поступать в аналитику эффективности, пробелов и рекомендаций. ИИ-тегирование выполняется на стороне сервера. Это явное действие — оно никогда не прочёсывает всё ваше хранилище само по себе — и оно ограничено по стоимости и идемпотентно: уже тегированные элементы пропускаются и никогда не оплачиваются повторно, а limit зажимается до жёсткого серверного потолка, а не отклоняется.

curl -X POST "https://app.tease.link/api/admin/vault/auto-tag" \
  -H "Authorization: Bearer $TEASE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "all_untagged": true, "limit": 100 }'
const res = await fetch('https://app.tease.link/api/admin/vault/auto-tag', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TEASE_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ all_untagged: true, limit: 100 }),
});
const result = await res.json();
res = requests.post(
    "https://app.tease.link/api/admin/vault/auto-tag",
    headers={"Authorization": f"Bearer {os.environ['TEASE_API_KEY']}"},
    json={"all_untagged": True, "limit": 100},
)
result = res.json()

Параметры тела

ПолеТипОбязательноОписание
media_idsstring[]нетЯвные id для тегирования. Опустите, чтобы использовать бэклог вместо этого.
all_untaggedbooleanнетКогда true, тегировать нетегированный бэклог вплоть до limit. По умолчанию false.
limitintegerнетМакс. число элементов для тегирования в этом вызове. Зажимается до жёсткого серверного потолка, так что завышенное значение зажимается, а не отклоняется.

Ответ

{
  "tagged": [{ "media_id": "m_88120", "tags": ["lingerie", "solo", "teaser"] }],
  "tagged_count": 1,
  "skipped": [{ "media_id": "m_88121", "reason": "already_tagged" }],
  "skipped_count": 1,
  "errors": [],
  "capped": false,
  "requested": 2
}
ПолеТипОписание
taggedarrayЭлементы, получившие новые теги, каждый со своим media_id и применёнными tags.
tagged_countintegerСчётчик заново тегированных элементов.
skippedarrayПропущенные элементы, каждый с reason (например, уже тегирован, нечего тегировать).
skipped_countintegerСчётчик пропущенных элементов.
errorsarrayСбои по элементам. Плохой элемент деградирует до ошибки здесь — он никогда не выдаёт 500 на весь вызов.
cappedbooleantrue, если requested превысил потолок и запуск был урезан.
requestedintegerСколько элементов вызов попытался обработать до зажима.

Тегирование безопасно к деградации по элементам: единственный элемент, который не может быть тегирован, возвращается в errors или skipped с причиной; остальная часть пакета всё равно успешна. Повторный запуск всегда безопасен — тегированные элементы пропускаются, так что вам никогда не выставляют счёт дважды за то же медиа.


Что продаётся — эффективность

performance ранжирует ваше хранилище по выручке: какие отдельные медиа и какие теги реально приводят к покупкам, каждый с unlock rate (как часто фанат, получивший его, его купил). Это чтение за «что работает» в панели.

curl "https://app.tease.link/api/admin/vault/performance?limit=20" \
  -H "Authorization: Bearer $TEASE_API_KEY"

Query-параметры

ПолеТипОбязательноОписание
from_tsintegerнетНачало окна, Unix-секунды. По умолчанию 30 дней назад.
to_tsintegerнетКонец окна, Unix-секунды. По умолчанию сейчас.
limitintegerнетМакс. число строк на список (медиа и теги), 1–200. По умолчанию 20.

Ответ

{
  "range": { "from_ts": 1748688000, "to_ts": 1751280000 },
  "media": [
    {
      "media_id": "m_88130",
      "title": "red set — full video",
      "media_type": "video",
      "folder_name": "Red lingerie set",
      "has_cover": true,
      "tags": ["lingerie", "solo"],
      "sent": 247,
      "opened": 181,
      "purchased": 89,
      "revenue_cents": 142800,
      "unlock_rate": 0.34
    }
  ],
  "tags": [
    { "tag": "lingerie", "sent": 988, "opened": 731, "purchased": 301, "revenue_cents": 461500, "unlock_rate": 0.29 }
  ],
  "ppv_sends": 1320
}
ПолеТипОписание
rangeobjectРазрешённое окно from_ts/to_ts.
mediaarrayТоп медиа по выручке. См. поля строки ниже.
tagsarrayТоп тегов по выручке, с теми же sent/opened/purchased/revenue_cents/unlock_rate.
ppv_sendsintegerВсего PPV-отправок, подсчитанных в окне.

Каждая строка медиа несёт media_id, title, media_type, folder_name, has_cover, tags и числа эффективности:

ПолеТипОписание
sentintegerСколько раз это медиа было отправлено в окне.
openedintegerСколько раз оно было открыто/просмотрено.
purchasedintegerСколько раз оно было разблокировано/куплено.
revenue_centsintegerЧистая выручка, которую оно принесло, в центах.
unlock_ratenumber | nullДоля получателей, которые его разблокировали. null, когда слишком мало отправок, чтобы быть значимым.

unlock_rate сообщается как исход, уже подавленный, когда выборка слишком тонка, чтобы доверять — вам не нужно вычислять его или решать, когда он надёжен.


Что снять следующим — пробелы

gaps отвечает на «что мне снять?», выявляя теги, где спрос обгоняет предложение — темы, которые хорошо продаются, но где у вас мало элементов для отправки — наряду с тем, сколько вашего хранилища ещё неразложено или нетегировано.

curl "https://app.tease.link/api/admin/vault/gaps?limit=20" \
  -H "Authorization: Bearer $TEASE_API_KEY"

Query-параметры

ПолеТипОбязательноОписание
from_tsintegerнетНачало окна, Unix-секунды. По умолчанию 30 дней назад.
to_tsintegerнетКонец окна, Unix-секунды. По умолчанию сейчас.
limitintegerнетМакс. число строк shoot_more, 1–200. По умолчанию 20.

Ответ

{
  "range": { "from_ts": 1748688000, "to_ts": 1751280000 },
  "shoot_more": [
    {
      "tag": "shower",
      "revenue_cents": 88200,
      "purchased": 61,
      "sent": 140,
      "rank": 1
    }
  ],
  "total_items": 5120,
  "unsorted": 380,
  "untagged": 250
}
ПолеТипОписание
rangeobjectРазрешённое окно.
shoot_morearrayТеги, ранжированные как недопоставленные для их спроса — ваш список съёмки. См. строки ниже.
total_itemsintegerВсего проиндексированных элементов.
unsortedintegerЭлементы, ещё не разложенные в папку.
untaggedintegerЭлементы без ИИ-тегов пока — кандидаты на авто-тег.

Каждая строка shoot_more сообщает revenue_cents, purchased, sent тега и его rank — его позицию в списке съёмки, где 1 — самый недопоставленный для своего спроса. Список приходит уже упорядоченным; вам не нужно выводить ранжирование.

unsorted и untagged — это сигнал бэклога: элементы там не могут всплыть в поиске или аналитике, пока не будут разложены или тегированы. Запустите авто-тег, чтобы очистить счётчик нетегированных.


Что остыло — спящее

dormant возвращает элементы хранилища, у которых была нулевая активность отправок в окне — контент, который просто лежит там и мог бы быть переотправлен. Это разность множеств между вашим хранилищем и тем, что реально продавалось или отправлялось недавно; ничто в чистом итоге вашего аккаунта OnlyFans не затрагивается.

curl "https://app.tease.link/api/admin/vault/dormant?window_days=30" \
  -H "Authorization: Bearer $TEASE_API_KEY"

Query-параметры

ПолеТипОбязательноОписание
window_daysintegerнетОкно обратного отсчёта, 1–3650 дней. По умолчанию 30.

Ответ

{
  "items": [
    {
      "media_id": "m_70011",
      "title": "beach throwback",
      "tags": ["outdoor", "bikini"],
      "cover": true,
      "last_sent": 1741000000
    }
  ],
  "count": 1,
  "window_days": 30
}
ПолеТипОписание
itemsarrayСпящее медиа. У каждого есть media_id, title, tags, cover и last_sent.
countintegerЧисло спящих элементов.
window_daysintegerЭхо использованного окна.
last_sentinteger | nullКогда элемент был отправлен в последний раз (Unix-секунды), или null, если никогда.

Когортные рекомендации

recommend — это самое ценное чтение хранилища: для заданной когорты фанатов оно возвращает невиданный контент — элементы, которые этой когорте не отправлялись — ранжированные по тому, насколько хорошо они подходят. Направьте его на контент (рекомендовать для людей, купивших данную часть) или опишите когорту теми же фильтрами аудитории, которые использует композер рассылок.

curl "https://app.tease.link/api/admin/vault/recommend?source=tiktok&rfm_tag=whale&limit=20" \
  -H "Authorization: Bearer $TEASE_API_KEY"

Query-параметры

Укажите либо content_id (рекомендовать для когорты, купившей этот контент), либо один или более фильтров аудитории. Все параметры необязательны и комбинируются как AND-фильтр.

ПолеТипОбязательноОписание
content_idintegerнетПостроить когорту из покупателей этого контента.
sourcestringнетФильтровать когорту по источнику привлечения (например, tiktok).
countrystringнетФильтровать по стране (ISO-код).
rfm_tagstringнетФильтровать по RFM/lifecycle-тегу (например, whale, dormant).
spend_minintegerнетМинимальные пожизненные траты, в центах.
spend_maxintegerнетМаксимальные пожизненные траты, в центах.
inactive_daysintegerнетТолько фанаты, неактивные как минимум столько дней.
bought_ppvbooleanнетОграничить фанатами, которые покупали (или не покупали) PPV.
new_vs_returningstringнетnew или returning.
is_trialbooleanнетОграничить пробными (или не-пробными) фанатами.
limitintegerнетМакс. число рекомендаций, 1–200. По умолчанию 20.

Ответ

{
  "items": [
    {
      "media_id": "m_88130",
      "title": "red set — full video",
      "tags": ["lingerie", "solo"],
      "cover": true,
      "unlock_rate": 0.4,
      "fit_reason": "Recommended for this cohort"
    }
  ],
  "cohort_summary": {
    "filters": { "source": "tiktok", "rfm_tag": "whale" },
    "source": "tiktok",
    "fan_count": 312
  },
  "thin": false
}
ПолеТипОписание
itemsarrayРекомендованный невиданный контент, лучшее соответствие первым. См. поля строки ниже.
cohort_summaryobjectРазрешённая когорта: применённые filters, доминирующий source и fan_count. Когда построена из content_id, она также несёт from_content_id и buyer_count.
thinbooleantrue, когда у когорты мало покупательского сигнала, так что ранжирование менее уверенное. Относитесь к порядку как к более слабой подсказке.

Каждая строка рекомендации несёт media_id, title, tags, cover, unlock_rate и короткую, человекочитаемую fit_reason, которую вы можете показать рядом с подсказкой.

Рекомендация — это исход, а не рецепт

TEASE выбирает и ранжирует невиданный контент за вас — какие сигналы питают ранжирование и как они взвешиваются, является внутренним. Вы даёте ему когорту; он даёт вам упорядоченный список того, что эта когорта не видела и с наибольшей вероятностью купит. Флаг thin говорит вам, когда доверять меньше.


Дальнейшие шаги

On this page