Перейти к содержимому

Справочник эндпоинтов

Эндпоинты участника доступны под префиксом /api/v1/public/ на https://api.vibevo.io и требуют API-ключ с нужным скоупом. Два гостевых GET каталога креаторов под /api/v1/ не требуют API-ключа и описаны ниже.

Каталог креаторов и размещения

Гостевое чтение отделено от защищённых операций участника. В URL ниже пути указаны относительно https://api.vibevo.io/api/v1.

Гостевой каталог

GET /creator-catalog принимает q, channelType (STREAMER или SOCIAL), platform, format, topic, language, geo, audienceGeo, minPriceCents, maxPriceCents, availability, sort (price, relevance, activity), limit (1–100) и cursor. audienceGeo — ISO-код страны из текущего проверенного распределения аудитории с положительной долей; lowercase нормализуется в uppercase. Старый geo остаётся тегом географии профиля. platform и audienceGeo должны совпасть с одной активной опубликованной услугой канала. Сортировка price и её cursor используют минимальную опубликованную цену автора, которая может отличаться от услуги, подобранной фильтрами. Единственное допустимое значение availability — AVAILABLE; фильтр учитывает опубликованные услуги. Даты заказа и «по договорённости» фильтром не являются.

curl 'https://api.vibevo.io/api/v1/creator-catalog?channelType=STREAMER&availability=AVAILABLE&limit=20'

# Anonymous response (public fields only)
{
  "data": [{
    "publicId": "d8e805e4-1ec5-4ab6-a734-4ea389cecc6c",
    "metricsObservationId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "lastModified": "2026-10-08T12:00:00.000Z",
    "displayName": "Streamer One",
    "topics": ["gaming"],
    "languages": ["en"],
    "channelType": "STREAMER",
    "channels": [{"platform":"TWITCH","handle":"streamer_one","canonicalUrl":"https://www.twitch.tv/streamer_one"}],
    "services": [{
      "serviceListingId": 7, "type": "STREAM", "variant": "MENTION",
      "channel":{"platform":"TWITCH","handle":"streamer_one","canonicalUrl":"https://www.twitch.tv/streamer_one"},
      "proofModes":["PUBLIC_VOD"],
      "title": "Product mention", "unit": "broadcast",
      "basePrice": {"raw":"100000000","currency":"USDT","decimals":6},
      "packageOptions": [{"quantity":1,"discountBps":0,"packageBase":{"raw":"100000000","currency":"USDT","decimals":6}},{"quantity":5,"discountBps":500,"packageBase":{"raw":"475000000","currency":"USDT","decimals":6}}]
    }],
    "metrics": []
  }],
  "nextCursor": null
}

GET /creator-pages/{publicId} отдаёт страницу, пока креатор её опубликовал и у неё есть доступные услуги с условиями использования. Иначе API отвечает 404 с кодом RESOURCE_NOT_FOUND. Предварительная модерация профиля, цен, услуг и ручной ссылки не требуется. Черновики, контакты, файлы подтверждений, расписание и комиссионные поля не выдаются. Отзыв публикации обновляет доступность страницы, HTML, Open Graph, кэш и sitemap; неопубликованные страницы не индексируются.

Публичный ответ и цены

В каталоге указывается опубликованная базовая цена услуги без комиссий и дохода креатора. Денежное значение имеет вид {raw, currency: "USDT", decimals: 6}; raw — целое число в микросуммах USDT. Например, raw "100000000" означает 100 USDT. В запросе priceCents передаётся целая строка центов; ввод цены в USDT допускает максимум два знака после запятой.

Для подключённого верифицированного соцаккаунта channels[].audience может содержать проверенную географию, возраст и пол именно этого аккаунта: source, capturedAt, verifiedAt, periodDays, geo и demo. Средние просмотры считаются по известным неотрицательным просмотрам последних пяти публичных публикаций. Для ручных каналов доверенных статистических показателей нет; отсутствие данных не заменяется нулём. Приватные snapshot/evidence/connection IDs не возвращаются.

Защищённый поток участника

Все пути в этом списке имеют префикс /public и требуют API-ключа: GET-запросы — read, мутации — write плюс актуальные роль и права объекта.

  • Креатор: GET/PATCH /public/influencer-profile; GET /public/influencer-profile/page; POST /public/influencer-profile/page/generate, /submit, /page/publish и /page/unpublish; GET/POST /public/influencer-channels; GET/PUT /public/influencer-channels/{id}/pricing; POST /public/influencer-channels/{id}/ownership-challenge, /ownership-uploads, /ownership-uploads/{uploadId}/complete, /ownership-evidence и /submit. Профиль, страницы, каналы, ownership и pricing имеют JWT twins под /api/v1 без /public. GET/PUT /public/influencer-accounts/{accountId}/pricing — совместимый alias для собственного активного и верифицированного соцаккаунта; цены канала настраиваются через channel pricing. Совместимое поле publishAfterApproval принимает boolean: true публикует текущую версию сразу без предварительной модерации, false только создаёт private preview. Ручной канал создаётся через {kind:"MANUAL", platform, canonicalUrl}; безопасная публичная HTTPS-ссылка подходит для любой разрешённой платформы, а прежний запрос только с handle сохранён для Twitch/Kick. Проверка владения необязательна и не блокирует публикацию или покупку. Нативный аккаунт должен оставаться активным, верифицированным, принадлежать креатору и не быть заблокированным, приостановленным, проданным или удалённым. Отдельный JWT-only маршрут POST /api/v1/creator/social-accounts/{id}/avatar/refresh обновляет аватар своего аккаунта без нового OAuth; URL в body передавать нельзя. В owner DTO поля socialAccountId и avatarUrl необязательны. MCP-инструмент для обновления аватара не добавляется.
  • Рекламодатель: POST /public/placement-orders создаёт черновик; PATCH /public/placement-orders/{id} меняет его; POST /public/placement-orders/{id}/quote рассчитывает цену; POST /public/placement-orders/{id}/checkout подтверждает резерв. Для договорной цены доступны POST /public/placement-offers/quote и POST /public/placement-offers. Заказы и аналитика читаются через GET /public/placement-orders, GET /public/placement-orders/{id}, GET /public/analytics/placements и GET /public/placement-orders/{id}/analytics.
  • После funding стороны заказа используют GET /public/placement-assignments, GET /public/placement-assignments/{id}, /events и /deliverables; доступны accept, decline, submit, approve, request-changes, cancel, issues и change-proposals (предложить/принять срок). Deliverable меняется через PUT /public/placement-assignments/{id}/deliverables/{deliverableId}; private uploads имеют create/complete и attached-result download. JWT twins работают под /api/v1 без /public. Staff использует отдельные JWT-only review routes.

Если публикация временно отключена, явный запрос сохраняет publish intent и отвечает 503 WRITE_NOT_AVAILABLE_FOR_FEATURE; после разрешённого включения повторите тот же запрос с тем же UUID Idempotency-Key. Это не создаёт staff review; уже опубликованные страницы остаются доступны, unpublish работает.

Пример создания заказа

curl -X POST 'https://api.vibevo.io/api/v1/public/placement-orders' \
  -H "Authorization: Bearer $VIBEVO_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: 7ddc2979-9a7f-4d4f-8f89-38ea3353e444' \
  -d '{"items":[{"serviceListingId":7,"quantity":1,"discountBps":0,"dueAt":"2026-10-20T18:00:00.000Z","brief":"Mention the product during the broadcast.","results":[{"expectedAt":"2026-10-20T17:00:00.000Z"}],"rights":{}}]}'

В results должно быть ровно столько обязательств, сколько выбрано размещений (1, 5 или 10); expectedAt — дата каждого выхода, dueAt — общий крайний срок. rights содержит согласованные условия использования.

Quote и подтверждение

POST /api/v1/public/placement-orders/{id}/quote
Idempotency-Key: <stable UUID>
{ "expectedVersion": 1 }

# Advertiser-safe quote projection
{
  "data": {
    "quoteId": "9e955328-7a2b-42a4-9963-330fcc83ad92",
    "quoteVersion": 1, "orderId": 14,
    "expiresAt": "2026-10-08T12:10:00.000Z",
    "payloadHash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "currency": "USDT",
    "items": [{"serviceListingId":7,"base":{"raw":"100000000","currency":"USDT","decimals":6},"brandFee":{"raw":"5000000","currency":"USDT","decimals":6},"total":{"raw":"105000000","currency":"USDT","decimals":6}}],
    "totals": {"base":{"raw":"100000000","currency":"USDT","decimals":6},"brandFee":{"raw":"5000000","currency":"USDT","decimals":6},"total":{"raw":"105000000","currency":"USDT","decimals":6}}
  }
}

POST /api/v1/public/placement-orders/{id}/checkout
Idempotency-Key: <new stable UUID>
{ "quoteId": "9e955328-7a2b-42a4-9963-330fcc83ad92", "quoteVersion": 1, "payloadHash": "<copy the quote hash>", "confirm": true }

Quote возвращает рекламодателю базовую сумму, его комиссию и общий резерв. Клиент показывает эти суммы и явно подтверждает checkout с quoteId, quoteVersion, payloadHash и confirm:true. Комиссия и чистый доход креатора не входят в ответ рекламодателю. В собственном creator pricing креатор видит свою базовую сумму, комиссию и чистый доход; комиссия бренда туда не входит.

Пример приватного UGC-предложения

POST /api/v1/public/placement-offers/quote
Idempotency-Key: <stable UUID>
{
  "origin": "CUSTOM",
  "creatorPublicId": "d8e805e4-1ec5-4ab6-a734-4ea389cecc6c",
  "serviceType": "UGC",
  "proofModes": ["PRIVATE_FILE"],
  "priceCents": "12000",
  "expectedEndAt": "2026-10-20T18:00:00.000Z",
  "quantity": 1,
  "discountBps": 0,
  "brief": "Create and deliver a short private product video.",
  "results": [{"expectedAt":"2026-10-20T17:00:00.000Z","description":"Deliver the private video"}],
  "rights": {"usage":"As agreed in the brief"}
}

# Quote response: { data: { quoteId, quoteVersion, payloadHash, items: [{ serviceListingId: null, base, brandFee, total }], totals, ... } }

POST /api/v1/public/placement-offers
Idempotency-Key: <new stable UUID>
{ "quoteId": "<quote ID>", "quoteVersion": 1, "payloadHash": "<quote hash>", "confirm": true }

# Without serviceListingId, only UGC + PRIVATE_FILE is accepted; do not send accountId or channelRef.

При отсутствии serviceListingId допустимы только serviceType "UGC" и proofModes ["PRIVATE_FILE"]. Не отправляйте accountId или channelRef. Quote показывает рекламодателю базовую сумму, его комиссию и общий резерв; serviceListingId будет null. У FILE result channelRef и publishedRevision равны null; url/contentId также null, metrics пустой. Файл не получает публичный URL или social metrics.

Повторы и ошибки

UUID Idempotency-Key обязателен для profile PATCH, page/generate, channel create и pricing PUT, а также для order, assignment и ownership mutations, где это указано в контракте. При неизвестном результате повторяйте тот же метод, путь, UUID и body; тот же ключ с другим body/action/target даёт IDEMPOTENCY_CONFLICT. Операции проверяют свежую роль и ownership до replay. Profile PATCH возвращает сохранённый DTO, page/generate заново строит preview. Pricing PUT возвращает сохранённый operation/version и свежий current projection; replay не повторяет денежную операцию или изменение цены.

Приватные загрузки
Сначала создайте owner-scoped или assignment-scoped upload session, затем отправьте файл напрямую по краткоживущему подписанному PUT URL и вызовите complete. Не передавайте полный файл/base64 в API или MCP; ключ API не посылается на storage URL. Файл не становится доказательством до серверной проверки и статуса VERIFIED. Лимиты первого релиза: изображения до 10 MiB, видео до 100 MiB; PDF до 50 MiB только для шаблонов, которые его разрешают. Ссылки, токены и файлы подтверждений не попадают в каталог, OG, логи и публичный кэш.

Структурные ошибки

Ответ ошибки содержит стабильное поле code и безопасное сообщение. Возможные коды: API_KEY_INVALID (401), API_KEY_MISSING_SCOPE / ROLE_NOT_ALLOWED / ACCOUNT_ACCESS_DENIED (403), RESOURCE_NOT_FOUND (404), INVALID_MONEY_PRECISION / INVALID_PROOF (400), VERSION_CONFLICT / QUOTE_EXPIRED / PRICE_CHANGED / IDEMPOTENCY_CONFLICT / INSUFFICIENT_FUNDS (409), RATE_LIMITED (429), SERVICE_UNAVAILABLE / PRIVATE_UPLOAD_SERVICE_UNAVAILABLE (503). Чужой или недоступный объект выглядит как not found.

Пример безопасного тела ошибки:

{"code":"IDEMPOTENCY_CONFLICT","message":"The idempotency key was used with a different payload."}

Идентификация ключа

  • GET /me — данные текущего ключа (кто владелец, скоупы). Достаточно любого валидного ключа.

Кампании (для рекламодателя)

  • GET /campaigns — список ваших кампаний (бюджет, потрачено, статус). Скоуп read. Курсорная пагинация.
  • GET /campaigns/{id} — одна кампания. Скоуп read.
  • GET /campaigns/{id}/posts — посты кампании. Скоуп read. Курсор + необязательный фильтр по статусу.
  • GET /campaigns/{id}/creators — креаторы, агрегированные по аккаунту и отсортированные по просмотрам. Скоуп read.
  • GET /campaigns/{id}/tracking-links — трекинг-ссылки с uniqueClicks. Скоуп read.
  • GET /campaigns/{id}/posts/{postId}/proofs — скриншоты просмотров поста Instagram, новые сверху: id, takenAt, views (что прочитал тот же скан; null, если Instagram скрыл просмотры). Скоуп read.
  • GET /campaigns/{id}/posts/{postId}/proofs/{proofId}/image — один скриншот (JPEG): плитка рилса в профиле, как её показал Instagram, — превью, просмотры, ник и время UTC. Других роликов, постов и кампаний на нём нет. Скоуп read.
  • GET /campaigns/{id}/proofs/zip — ZIP с последним скриншотом каждого поста Instagram кампании и таблицей index.csv (пост, ссылка, аккаунт, рилс, время, просмотры). Скоуп read.

ER и сохранения

ER = 100 × (likes + comments) / views, с округлением до двух знаков. Он считается по последним полным наблюдениям просмотров, лайков и комментариев. Итог использует суммы этих счётчиков, а не среднее процентов постов. При нулевых просмотрах или отсутствии полного наблюдения ER равен null. Сохранения и репосты в формулу не входят.

Список и карточка кампании, её аналитика, посты и креаторы возвращают engagement со scope: accepted_video. В расчёт входят только принятые видеопосты; в строке поста — только этот пост, в строке креатора — его аккаунт. Для знаменателя используйте engagement.views: прежний totalViews может включать другие статусы или отражать оплаченные просмотры.

В фабриках канонический ER находится в metrics.er (в сводке — totals.er), сохранения — в metrics.saves. Те же поля доступны в точках истории и snapshotBaseline. Прежнее верхнеуровневое er сохраняет старую семантику; новые клиенты используют вложенное поле. Отсутствие новых полей в старом ответе не подтверждает измерение.

saves — отдельный последний известный счётчик. Автоматические источники: TikTok collectCount и X bookmarkCount, только когда поставщик вернул корректное значение. На остальных платформах он недоступен без фактического измерения. 0 означает измеренный ноль, null — отсутствие данных. Не подменяйте null нулём. Старая история кампаний не доказывает исходное число просмотров: новый ER появится после обычного скана, без массового платного перескана.

erCoverage и savesCoverage содержат measuredPosts / totalPosts для всей выбранной выборки до пагинации. Частичное покрытие означает частичный итог. updatedAt и savesUpdatedAt — самое раннее время включённого измерения; null означает неизвестную свежесть. Перенос старого счётчика в новый снимок не обновляет его время. ER и сохранения на графиках — абсолютные снимки, без режима прироста.

В hiddenFields отчёта можно передать saves: сервер уберёт число, покрытие и время измерения. Скрытие views, likes, comments или er также убирает зависимый ER; скрытие posts — покрытие, lastScanned — время измерения. Эти правила действуют для сводок, строк, истории и baseline.

{
  "engagement": {
    "scope": "accepted_video",
    "views": 100,
    "likes": 0,
    "comments": 0,
    "er": 0,
    "saves": null,
    "erCoverage": { "measuredPosts": 1, "totalPosts": 2 },
    "savesCoverage": { "measuredPosts": 0, "totalPosts": 2 },
    "updatedAt": "2026-10-09T08:00:00.000Z",
    "savesUpdatedAt": null
  }
}

Офферы (для креатора)

  • GET /offers — лента доступных офферов (RUNNING-кампаний, которые креатор может взять), с полями оффера: ставка/CPM, требования, takenAt. Без бюджета/потраченного рекламодателя. Скоуп read. Курсорная пагинация.
  • GET /posts — ваши поданные посты по всем кампаниям: статус, просмотры, заработок, кампания, аккаунт, дата подачи; плюс summary (всего постов, на модерации, заработано всего). Скоуп read. Курсор + необязательные фильтры status, platform.
  • GET /posts/{id}/proofs и GET /posts/{id}/proofs/{proofId}/image — скриншоты просмотров вашего поста Instagram: список и сам JPEG. Скоуп read.

Соцаккаунты (для креатора)

  • GET /social-accounts — ваши соцаккаунты: платформа, ник, статус, isVerified, verifiedVia (PLATFORM_API / BIO_CODE / MANUAL), statsAvailability и подключение socialConnection, если оно есть. Скоуп read.
  • GET /social-accounts/{id}/verification — активный код для bio-верификации и инструкция, что с ним делать. Скоуп read.
  • GET /social-accounts/{id}/stats — статистика аккаунта: текущая сессия записи экрана, снапшот аудитории и история. Скоуп read.

Фабрики контента

  • GET /factories — список фабрик с агрегатами по аккаунтам, постам и просмотрам.
  • GET /factories/{id}/summary — сводка: публикации, просмотры, реакции, средние и медианные просмотры.
  • GET /factories/{id}/accounts и GET /factories/{id}/accounts/{accountId} — креаторы и детальная аналитика одного аккаунта.
  • GET /factories/{id}/posts — посты с обложкой, длительностью, хэштегами, метриками и мини-графиками.

Для сводки, креаторов и постов доступны фильтры from, to, platform, search, tag и factoryAccountId, а также сортировки accountSort и postSort. Списки используют курсорную пагинацию.

Теги, мониторинг и отчёты

Управляйте аккаунтами, тегами, мониторингом и публичными отчётами фабрики через API.

  • GET /factories/tags — read
  • GET /factories/{id}/tag-groups — read
  • GET /factories/credits — read
  • GET /factories/{id}/credits — read
  • GET /factories/{id}/credit-usage — read
  • GET /factories/{id}/credit-history — read
  • GET /factories/{id}/share-links — read

Интервалы: 24, 12, 10, 8, 6, 4 часа от последнего скана; срок 1–365 дней. В REST: scansPerPostPerDay = 24 / intervalHours. История содержит только начисления и списания, расходы — за всё время, 30 дней и сегодня UTC.

Если id не указан, инструменты расходов и истории используют /factories/credits/usage и /factories/credits/history для общего кошелька, включая покупки.

hiddenFields скрывает поля на сервере, включая производные значения и ссылки. По умолчанию видны все поля. Доступ к чужим фабрикам и админским отчётам не открывается. Скопируйте sharePath при создании — секрет повторно не выдаётся.

Аналитика

  • GET /analytics/campaigns/{id} — аналитика кампании. Скоуп read.

Кошелёк

  • GET /wallet — текущий баланс. Скоуп read.
  • GET /wallet/transactions — история биллинга. Скоуп read. Курсорная пагинация.

Курсорная пагинация

Списочные эндпоинты используют курсорную пагинацию. Передайте limit (от 1 до 100) и cursor (идентификатор последнего элемента предыдущей страницы):

GET /api/v1/public/campaigns?limit=50&cursor=1234

Ответ содержит массив данных и курсор следующей страницы:

{
  "data": [ /* ... */ ],
  "nextCursor": "5678"
}

Когда nextCursor равен null, страниц больше нет.

Формат денег

Денежные значения возвращаются структурой:

{
  "raw": "1500",
  "currency": "USD",
  "decimals": 2
}

raw — целое число в минимальных единицах, переданное строкой; реальное значение = raw / 10^decimals. Обратите внимание на разные масштабы:

  • Бюджеты кампаний и заработок по постам — центы: decimals: 2, валюта USD (например, raw: "1500" = 15.00 USD).
  • Баланс кошелька и транзакции биллинга — минимальные единицы USDT: decimals: 6.

Формат ошибок

Ошибки возвращаются единым конвертом:

{
  "statusCode": 403,
  "code": "insufficient_scope",
  "message": "Missing required scope: read",
  "timestamp": "2026-07-11T12:00:00.000Z",
  "path": "/api/v1/public/campaigns"
}

Ориентируйтесь на строковое поле code для программной обработки — оно стабильнее, чем человекочитаемый message.

Примеры curl

Список кампаний (заголовок Bearer):

curl https://api.vibevo.io/api/v1/public/campaigns?limit=20 \
  -H "Authorization: Bearer vibevo_live_ab12cd.xxxxxxxxxxxxxxxx"

Баланс кошелька (заголовок X-API-Key):

curl https://api.vibevo.io/api/v1/public/wallet \
  -H "X-API-Key: vibevo_live_ab12cd.xxxxxxxxxxxxxxxx"

Была ли эта статья полезна?

Обновлено: 9 октября 2026

Справочник эндпоинтов API VibeVO | VibeVO Docs