JoinPoint · для разработчиковJoinPoint · dasturchilar uchun

JoinPoint API

API для программистов, которые подключают канал в JoinPoint к своей CRM, сайту или аналитике: подписчики, подписки, платежи, тарифы, ссылки-источники, промокоды и статистика. Каждый запрос видит данные только вашего бота.

JoinPoint’dagi kanalni oʻz CRM, sayt yoki analitikasiga ulaydigan dasturchilar uchun API: obunachilar, obunalar, toʻlovlar, tariflar, manba-havolalar, promokodlar va statistika. Har bir soʻrov faqat botingiz maʼlumotlarini koʻradi.

Базовый адресAsosiy manzil
https://prod-api.joinpoint.uz/api
АвторизацияAvtorizatsiya
Bearer-токен, 24 часаBearer-token, 24 soat
ФорматFormat
JSON, UTF-8
МетодовMetodlar
25
СодержаниеMundarija
ОсновыAsoslar
ВходKirish
ПодписчикиObunachilar
ПодпискиObunalar
ПлатежиToʻlovlar
ТарифыTariflar
Ссылки-источникиManba-havolalar
ПромокодыPromokodlar
СтатистикаStatistika
СправочникMaʼlumotnoma

Быстрый стартTezkor boshlash

1. Получите токен по телефону и паролю от кабинета JoinPoint:

1. JoinPoint kabineti telefoni va paroli orqali token oling:

ЗапросSoʻrov
curl -X POST 'https://prod-api.joinpoint.uz/api/auth/admin-login' \
  -H 'Content-Type: application/json' \
  -d '{"phone":"+998901234567","password":"YOUR_PASSWORD"}'

2. Возьмите meta.token из ответа и передавайте его в каждом запросе:

2. Javobdagi meta.token ni oling va uni har bir soʻrovda yuboring:

ЗапросSoʻrov
curl -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/user-bot?page=1&count=50&filter=subscribed'

То же на Node.js 18+:

Xuddi shu Node.js 18+ da:

Node.jsNode.js
const BASE = 'https://prod-api.joinpoint.uz/api';

// 1. token: phone and password come from environment variables
const login = await fetch(`${BASE}/auth/admin-login`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ phone: process.env.JP_PHONE, password: process.env.JP_PASSWORD }),
}).then((r) => r.json());
const token = login.meta.token; // valid for 24 hours, reuse it

// 2. first page of paying subscribers
const res = await fetch(`${BASE}/user-bot?page=1&count=50&filter=subscribed`, {
  headers: { Authorization: `Bearer ${token}` },
}).then((r) => r.json());
console.log(res.meta.total, res.data.length);

Доступ и токенKirish va token

Токен выдаёт метод POST /auth/admin-login по телефону и паролю от кабинета JoinPoint. Передавайте его в заголовке Authorization: Bearer <токен>.

Tokenni POST /auth/admin-login metodi JoinPoint kabineti telefoni va paroli boʻyicha beradi. Uni Authorization: Bearer <token> sarlavhasida yuboring.

Токен действует 24 часа. Когда он истечёт, запросы вернут 401 — получите новый тем же методом. Не входите заново перед каждым запросом: используйте один токен, пока он действует.

Token 24 soat amal qiladi. Muddati tugagach, soʻrovlar 401 qaytaradi — xuddi shu metod bilan yangisini oling. Har bir soʻrovdan oldin qayta kirmang: token amal qilguncha bittasidan foydalaning.

Отдельных API-ключей нет: доступ дают логин и пароль кабинета. Если кабинета ещё нет — оставьте заявку на главной странице.

Alohida API-kalitlar yoʻq: kirishni kabinet logini va paroli beradi. Kabinetingiz hali boʻlmasa — bosh sahifada ariza qoldiring.

HTTPHTTPКогдаQachon
401Нет токена, токен истёк или неверный.Token yoʻq, muddati tugagan yoki notoʻgʻri.
403Метод недоступен для кабинета инфлюенсера, кабинет приостановлен или бот на паузе.Metod influenser kabineti uchun yopiq, kabinet toʻxtatilgan yoki bot pauzada.
429Слишком много неудачных попыток входа: 5 на один номер или 10 с одного IP за 15 минут. Подождите 15 минут.Kirish urinishlari juda koʻp: 15 daqiqada bitta raqamga 5 ta yoki bitta IP dan 10 ta. 15 daqiqa kuting.

Заголовок lang со значением ru, uz или eng задаёт язык текстов ошибок.

lang sarlavhasi (ru, uz yoki eng) xato matnlari tilini belgilaydi.

БезопасностьXavfsizlik

Формат ответаJavob formati

Ответы — JSON: данные в data, служебная информация в meta. Исключение — /clients, у него своя обёртка.

Javoblar — JSON: maʼlumotlar data da, xizmat maʼlumotlari meta da. Istisno — /clients, uning oʻz qobigʻi bor.

Ответ спискаRoʻyxat javobi
{
  "data": [
    "…"
  ],
  "meta": {
    "message": "found",
    "statusCode": 200,
    "currentPage": 1,
    "totalPages": 25,
    "total": 1238,
    "count": 50,
    "hasPrev": false,
    "hasNext": true
  }
}
СитуацияHolatHTTPHTTPmeta.statusCodemeta.statusCodemeta.messagemeta.message
Данные найденыMaʼlumot topildi200200found или successfound yoki success
Создано (POST)Yaratildi (POST)201201Зависит от методаMetodga bogʻliq
Пустой списокBoʻsh roʻyxat200204empty
Ошибка в параметрахParametrlarda xato400400Текст ошибки, например page should not be emptyXato matni, masalan page should not be empty
Нет авторизацииAvtorizatsiya yoʻq401401Authorization Error!
Нет доступаRuxsat yoʻq403403Forbidden Error!
Не найдено или чужая записьTopilmadi yoki begona yozuv404404Текст ошибкиXato matni
Много неудачных входовMuvaffaqiyatsiz kirishlar koʻp429429Текст ошибкиXato matni
Ошибка сервераServer xatosi500500Повторите запрос через минутуBir daqiqadan soʻng qayta urinib koʻring

Пустой список приходит с HTTP 200: проверяйте meta.statusCode или длину data. Лишние поля в теле или параметрах запроса дают 400 — передавайте только описанные. Звёздочкой * отмечены обязательные параметры.

Boʻsh roʻyxat HTTP 200 bilan keladi: meta.statusCode yoki data uzunligini tekshiring. Soʻrov tanasi yoki parametrlaridagi ortiqcha maydonlar 400 beradi — faqat tavsiflanganlarini yuboring. Majburiy parametrlar * belgisi bilan belgilangan.

Постраничная выдачаSahifalab olish

Списки с параметрами page и count требуют их обязательно: page от 1 до 500, count от 5 до 200 000. Без них ответ — 400.

page va count parametrlari bor roʻyxatlarda ular majburiy: page 1 dan 500 gacha, count 5 dan 200 000 gacha. Ularsiz javob — 400.

Записи идут от новых к старым. Дойти можно максимум до 500 × count записей. Если во время выгрузки появятся новые записи, на границе страниц одна повторится — убирайте повторы по id.

Yozuvlar yangisidan eskisiga qarab tartiblangan. Eng koʻpi bilan 500 × count ta yozuvgacha yetib borish mumkin. Yuklab olish paytida yangi yozuvlar qoʻshilsa, sahifalar chegarasida bittasi takrorlanadi — takrorlarni id boʻyicha olib tashlang.

Деньги: сумы и тийиныPul: soʻm va tiyin

В разных методах деньги приходят в разных единицах. 1 сум = 100 тийин. Сверяйтесь с таблицей:

Turli metodlarda pul turli birliklarda keladi. 1 soʻm = 100 tiyin. Jadvalga qarang:

МетодMetodПоляMaydonlarЕдиницыBirlik
GET /planpriceсумыsoʻm
GET /plan/{id}priceтийиныtiyin
GET /user-bot-planplan.priceтийиныtiyin
GET /transaction-meta/transactions/{botId}, /userbot/{id}price, plan.priceсумыsoʻm
GET /transaction-meta/{id}priceтийиныtiyin
GET /transaction-meta/statistics/{id}, /plan-summaryвсе суммыbarcha summalarсумыsoʻm
GET /user-bot/…statistics…выручка, средний чекtushum, oʻrtacha chekсумыsoʻm
GET /promodiscount_value (для fixed), discount_given_tiyindiscount_value (fixed uchun), discount_given_tiyinтийиныtiyin
POST /promodiscountValue (для fixed)discountValue (fixed uchun)сумыsoʻm

Часть сумм приходит строкой ("500000"), часть — числом. Приводите к числу перед расчётами.

Summalarning bir qismi satr ("500000"), bir qismi son boʻlib keladi. Hisoblashdan oldin songa aylantiring.

Даты и IDSanalar va ID

ЧтоNimaФорматFormatПримерMisol
Дата и время в ответеJavobdagi sana va vaqtISO 8601, UTC. Ташкент = UTC + 5 часов.ISO 8601, UTC. Toshkent = UTC + 5 soat.2026-09-28T07:16:55.231Z = 28.09.2026, 12:16 по Ташкенту2026-09-28T07:16:55.231Z = 28.09.2026, Toshkent vaqti bilan 12:16
Дата в параметрахParametrlardagi sanaISO 8601 (fromDate, toDate) или YYYY-MM-DD там, где указано.ISO 8601 (fromDate, toDate) yoki koʻrsatilgan joylarda YYYY-MM-DD.2026-09-01T00:00:00Z
Telegram IDTelegram IDСтрока. Храните как строку или BIGINT.Satr. Satr yoki BIGINT sifatida saqlang."1234567890"
ID подписчикаObunachi ID si/user-bot[].id — на него ссылаются подписки и отчёты./user-bot[].id — obunalar va hisobotlar shunga bogʻlanadi.100501
ID человекаFoydalanuvchi ID si/user-bot[].user.id — на него ссылаются платежи (userId)./user-bot[].user.id — toʻlovlar (userId) shunga bogʻlanadi.900001

Статусы подпискиObuna holatlari

Доступ оплачен, если у подписчика есть подписка с nextDate в будущем. Статус показывает, как получен доступ:

Agar obunachida nextDate kelajakda boʻlgan obuna boʻlsa, kirish toʻlangan. Holat kirish qanday olinganini koʻrsatadi:

statusstatusЧто значитMaʼnosi
activeОплачено картой, автопродление включено.Karta bilan toʻlangan, avtouzaytirish yoqilgan.
manual-canceledАвтопродление выключено. Доступ до nextDate.Avtouzaytirish oʻchirilgan. Kirish nextDate gacha.
manual-activeДоступ выдан вручную: бесплатно, наличными или переводом.Kirish qoʻlda berilgan: bepul, naqd pul yoki oʻtkazma orqali.
free-trialПробный период; в конце система попробует списать оплату.Sinov muddati; oxirida tizim toʻlovni yechishga urinadi.
freeБесплатный тариф без карты.Kartasiz bepul tarif.
canceledЗакончилась. Если nextDate в будущем — разовая оплата, доступ до nextDate.Tugagan. Agar nextDate kelajakda boʻlsa — bir martalik toʻlov, kirish nextDate gacha.
createdНачал оформление, не оплатил.Rasmiylashtirishni boshlagan, lekin toʻlamagan.

Правила работыIshlash qoidalari

ВходKirish

POST/auth/admin-login

Вход, получение токенаKirish, token olish

Выдаёт токен по номеру телефона и паролю от кабинета JoinPoint. Токен действует 24 часа; после этого запросы возвращают 401 — войдите снова.

JoinPoint kabineti telefon raqami va paroli boʻyicha token beradi. Token 24 soat amal qiladi; shundan soʻng soʻrovlar 401 qaytaradi — qayta kiring.

Тело запроса (JSON)Soʻrov tanasi (JSON)

ПолеMaydonТипTuriОписаниеTavsif
phoneобязательныйmajburiystringТелефон кабинета в формате +998XXXXXXXXX.Kabinet telefoni, +998XXXXXXXXX formatida.
passwordобязательныйmajburiystringПароль от кабинета.Kabinet paroli.

Что приходит в ответеJavobda nima keladi

ПолеMaydonТипTuriЧто означаетMaʼnosi
meta.tokenstringТокен. Передавайте его в заголовке Authorization: Bearer <токен>.Token. Uni Authorization: Bearer <token> sarlavhasida yuboring.
data.idintegerID вашего бота в JoinPoint.JoinPoint’dagi botingiz ID si.
data.namestringНазвание бота.Bot nomi.
data.channelIdstringID платного канала.Pullik kanal ID si.
data.channelNamestring | nullНазвание канала.Kanal nomi.
data.statusstringactive или paused.active yoki paused.
data.isSuspendedbooleanКабинет приостановлен.Kabinet toʻxtatilgan.
meta.hasTelegramUsersbooleanСлужебное поле.Xizmat maydoni.
  • HTTP-код успешного входа — 201.Muvaffaqiyatli kirishning HTTP kodi — 201.
  • Неверный телефон или пароль — 400. Кабинет приостановлен или бот на паузе — 403.Telefon yoki parol notoʻgʻri — 400. Kabinet toʻxtatilgan yoki bot pauzada — 403.
  • 5 неудачных попыток на один номер или 10 с одного IP за 15 минут — ответ 429, вход закрыт на 15 минут.15 daqiqada bitta raqamga 5 ta yoki bitta IP dan 10 ta muvaffaqiyatsiz urinish — 429 javobi, kirish 15 daqiqaga yopiladi.
ЗапросSoʻrov
curl -X POST \
  -H 'Content-Type: application/json' \
  -d '{"phone":"+998901234567","password":"YOUR_PASSWORD"}' \
  'https://prod-api.joinpoint.uz/api/auth/admin-login'
ОтветJavob
{
  "data": {
    "id": 42,
    "phone": "+998901234567",
    "name": "Premium kanal",
    "channelId": "-1001234567890",
    "channelName": "Premium kanal",
    "freeTrial": 0,
    "isActive": true,
    "note": null,
    "isNavigation": false,
    "status": "active",
    "isSuspended": false,
    "role": "admin",
    "trialNotifyEnabled": false
  },
  "meta": {
    "message": "success",
    "statusCode": 200,
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.…",
    "hasTelegramUsers": true
  }
}

ПодписчикиObunachilar

GET/user-bot

ПодписчикиObunachilar

Все, кто запускал вашего бота, с фильтром по сегменту и поиском.

Botingizni ishga tushirgan barcha foydalanuvchilar — segment boʻyicha filtr va qidiruv bilan.

Параметры запросаSoʻrov parametrlari

ИмяNomiТипTuriОписаниеTavsif
pageобязательныйmajburiyintegerНомер страницы, от 1 до 500.Sahifa raqami, 1 dan 500 gacha.
countобязательныйmajburiyintegerСтрок на странице, от 5 до 200 000. Рекомендуем до 1 000.Sahifadagi qatorlar soni, 5 dan 200 000 gacha. 1 000 tagacha tavsiya qilamiz.
filterstringСегмент: all — все; subscribed — с действующей подпиской; not_subscribed — ни разу не оформляли; not_confirm_card — начали оплату, но не подтвердили карту; subscribed_ended — подписка закончилась; subscribed_ended_after_free_trial — пробный период закончился без оплаты; free_trial — сейчас на пробном периоде; free — на бесплатном тарифе без карты.Segment: all — hammasi; subscribed — amaldagi obunasi borlar; not_subscribed — hech qachon obuna boʻlmaganlar; not_confirm_card — toʻlovni boshlagan, lekin kartani tasdiqlamaganlar; subscribed_ended — obunasi tugaganlar; subscribed_ended_after_free_trial — sinov muddati toʻlovsiz tugaganlar; free_trial — hozir sinov muddatida; free — kartasiz bepul tarifda.
searchstringПоиск по имени, Telegram ID, username или телефону.Ism, Telegram ID, username yoki telefon boʻyicha qidiruv.
createdAtstringСортировка по дате появления: ascend или descend. Так же работают name и status.Paydo boʻlish sanasi boʻyicha saralash: ascend yoki descend. name va status ham shunday ishlaydi.

Поля записи в datadata dagi yozuv maydonlari

ПолеMaydonТипTuriЧто означаетMaʼnosi
idintegerID подписчика в вашем боте. На него ссылаются подписки и методы ниже.Botingizdagi obunachi ID si. Obunalar va quyidagi metodlar shunga bogʻlanadi.
createdAtstring (UTC)Когда человек впервые запустил бота.Foydalanuvchi botni birinchi marta qachon ishga tushirgani.
firstnamestring | nullИмя, указанное в боте.Botda koʻrsatilgan ism.
lastnamestring | nullФамилия.Familiya.
statusstringcreated — обычный подписчик, blocked — заблокировал бота.created — oddiy obunachi, blocked — botni bloklagan.
inChannelbooleanОтметка «в канале». Может отставать от реальности.«Kanalda» belgisi. Haqiqiy holatdan orqada qolishi mumkin.
isUnlimitedbooleanБессрочный доступ, выданный вручную.Qoʻlda berilgan muddatsiz kirish.
langstring | nullЯзык бота: uz, ru, uz-cyrl, en.Bot tili: uz, ru, uz-cyrl, en.
rolestringuser или manager.user yoki manager.
useFreeTrialbooleanУже использовал пробный период.Sinov muddatidan allaqachon foydalangan.
userobjectid (ID человека в JoinPoint), tgId, tgUsername, tgPhone.id (JoinPoint’dagi foydalanuvchi ID si), tgId, tgUsername, tgPhone.
startingPointobject | nullСсылка, по которой пришёл, пока не оформил подписку: id, extId, redirectUrl.Obuna boʻlgunicha kelgan havolasi: id, extId, redirectUrl.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/user-bot?page=1&count=50&filter=subscribed'
ОтветJavob
{
  "data": [
    {
      "id": 100501,
      "createdAt": "2026-06-08T12:31:40.512Z",
      "lastUpdatedAt": "2026-09-28T07:17:02.114Z",
      "firstname": "Aziz",
      "lastname": null,
      "status": "created",
      "inChannel": true,
      "isUnlimited": false,
      "lang": "uz",
      "role": "user",
      "useFreeTrial": false,
      "bot": {
        "id": 42,
        "name": "Premium kanal"
      },
      "user": {
        "id": 900001,
        "tgUsername": "aziz_example",
        "tgId": "1234567890",
        "tgPhone": "998901234567",
        "createdAt": "2026-06-08T12:31:40.500Z",
        "lastUpdatedAt": "2026-06-08T12:31:40.500Z",
        "userDetail": null
      },
      "startingPoint": null
    }
  ],
  "meta": {
    "message": "found",
    "statusCode": 200,
    "currentPage": 1,
    "totalPages": 25,
    "total": 1238,
    "count": 50,
    "hasPrev": false,
    "hasNext": true
  }
}
GET/user-bot/get-count

Размер сегментаSegment hajmi

Сколько подписчиков в сегменте. Параметры page и count обязательны, но на результат не влияют.

Segmentda nechta obunachi borligi. page va count parametrlari majburiy, lekin natijaga taʼsir qilmaydi.

Параметры запросаSoʻrov parametrlari

ИмяNomiТипTuriОписаниеTavsif
pageобязательныйmajburiyintegerНомер страницы, от 1 до 500.Sahifa raqami, 1 dan 500 gacha.
countобязательныйmajburiyintegerСтрок на странице, от 5 до 200 000. Рекомендуем до 1 000.Sahifadagi qatorlar soni, 5 dan 200 000 gacha. 1 000 tagacha tavsiya qilamiz.
filterstringСегмент, как в /user-bot.Segment, /user-bot dagidek.
searchstringПоиск, как в /user-bot.Qidiruv, /user-bot dagidek.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/user-bot/get-count?page=1&count=5&filter=subscribed'
ОтветJavob
{
  "data": {
    "count": 1238
  },
  "meta": {
    "message": "success",
    "statusCode": 200
  }
}
GET/user-bot/{id}

Карточка подписчикаObunachi kartochkasi

Один подписчик вашего бота. Чужой ID — ответ 404.

Botingizning bitta obunachisi. Begona ID — 404 javobi.

Параметры путиYoʻl parametrlari

ИмяNomiТипTuriОписаниеTavsif
idобязательныйmajburiyintegerID подписчика (/user-bot[].id).Obunachi ID si (/user-bot[].id).
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/user-bot/100501'
ОтветJavob
{
  "data": {
    "id": 100501,
    "createdAt": "2026-06-08T12:31:40.512Z",
    "lastUpdatedAt": "2026-09-28T07:17:02.114Z",
    "firstname": "Aziz",
    "lastname": null,
    "status": "created",
    "inChannel": true,
    "isUnlimited": false,
    "lang": "uz",
    "role": "user",
    "useFreeTrial": false,
    "bot": {
      "id": 42,
      "name": "Premium kanal"
    },
    "user": {
      "id": 900001,
      "tgUsername": "aziz_example",
      "tgId": "1234567890",
      "tgPhone": "998901234567",
      "createdAt": "2026-06-08T12:31:40.500Z",
      "lastUpdatedAt": "2026-06-08T12:31:40.500Z"
    },
    "startingPoint": null
  },
  "meta": {
    "message": "found",
    "statusCode": 200
  }
}
GET/clients

Реестр клиентовMijozlar reyestri

Плоский список подписчиков для CRM: статус подписки и ссылка, по которой человек пришёл. Телефоны приходят с маской. У метода своя обёртка ответа — без meta.

CRM uchun obunachilarning tekis roʻyxati: obuna holati va foydalanuvchi kelgan havola. Telefonlar niqoblangan holda keladi. Metodning oʻz javob qobigʻi bor — meta siz.

Параметры запросаSoʻrov parametrlari

ИмяNomiТипTuriОписаниеTavsif
pageintegerНомер страницы, по умолчанию 1.Sahifa raqami, standart qiymati 1.
countintegerСтрок на странице, по умолчанию 50, максимум 500.Sahifadagi qatorlar soni, standart 50, eng koʻpi 500.
fromstringДата регистрации «с», формат YYYY-MM-DD.Roʻyxatdan oʻtish sanasi «dan», YYYY-MM-DD formatida.
tostringДата регистрации «по», формат YYYY-MM-DD.Roʻyxatdan oʻtish sanasi «gacha», YYYY-MM-DD formatida.
statusstringactive — оплачен доступ, expired — закончился, cancelled — отменён, never_paid — ни разу не оформлял.active — kirish toʻlangan, expired — tugagan, cancelled — bekor qilingan, never_paid — hech qachon rasmiylashtirmagan.
sourceIdintegerТолько пришедшие по ссылке с этим ID.Faqat shu ID li havola orqali kelganlar.
searchstringПоиск по имени, username, Telegram ID, телефону.Ism, username, Telegram ID, telefon boʻyicha qidiruv.

Поля записи в datadata dagi yozuv maydonlari

ПолеMaydonТипTuriЧто означаетMaʼnosi
user_bot_idintegerID подписчика (/user-bot[].id).Obunachi ID si (/user-bot[].id).
tg_idstringTelegram ID.Telegram ID.
full_namestring | nullИмя и фамилия.Ism va familiya.
phonestring | nullТелефон с маской, например +99890***4567.Niqoblangan telefon, masalan +99890***4567.
tg_usernamestring | nullUsername без @.@ belgisisiz username.
langstring | nullЯзык бота.Bot tili.
registered_atstring (UTC)Когда впервые запустил бота.Botni birinchi marta qachon ishga tushirgani.
source_idinteger | nullID ссылки, по которой пришёл впервые.Birinchi marta kelgan havolasining ID si.
source_namestring | nullНазвание этой ссылки.Shu havolaning nomi.
attributed_atstring (UTC) | nullКогда засчитан переход по ссылке.Havola orqali oʻtish qachon hisobga olingani.
in_channelbooleanОтметка «в канале».«Kanalda» belgisi.
subscription_statusstringactive, expired, cancelled или never_paid.active, expired, cancelled yoki never_paid.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/clients?page=1&count=100&status=active'
ОтветJavob
{
  "data": [
    {
      "user_bot_id": 100501,
      "tg_id": "1234567890",
      "full_name": "Aziz",
      "phone": "+99890***4567",
      "tg_username": "aziz_example",
      "lang": "uz",
      "registered_at": "2026-06-08T12:31:40.512Z",
      "bot_id": 42,
      "bot_name": "Premium kanal",
      "source_id": 12,
      "source_name": "Instagram stories",
      "source_raw": "1759000000001",
      "attributed_at": "2026-06-08T12:31:41.000Z",
      "in_channel": true,
      "subscription_status": "active"
    }
  ],
  "total": 1238,
  "page": 1,
  "count": 100,
  "phonesMasked": true
}

ПодпискиObunalar

GET/user-bot-plan

ПодпискиObunalar

История подписок ваших подписчиков. У одного человека может быть несколько записей.

Obunachilaringiz obunalari tarixi. Bitta foydalanuvchida bir nechta yozuv boʻlishi mumkin.

Параметры запросаSoʻrov parametrlari

ИмяNomiТипTuriОписаниеTavsif
pageобязательныйmajburiyintegerНомер страницы, от 1 до 500.Sahifa raqami, 1 dan 500 gacha.
countобязательныйmajburiyintegerСтрок на странице, от 5 до 200 000. Рекомендуем до 1 000.Sahifadagi qatorlar soni, 5 dan 200 000 gacha. 1 000 tagacha tavsiya qilamiz.
userBotIdintegerТолько подписки этого подписчика.Faqat shu obunachining obunalari.
statusstringТолько в этом статусе, см. «Статусы подписки».Faqat shu holatdagilar, «Obuna holatlari» boʻlimiga qarang.

Поля записи в datadata dagi yozuv maydonlari

ПолеMaydonТипTuriЧто означаетMaʼnosi
idintegerID подписки.Obuna ID si.
createdAtstring (UTC)Когда создана запись.Yozuv qachon yaratilgani.
statusstringСтатус, см. «Статусы подписки».Holat, «Obuna holatlari» boʻlimiga qarang.
paymentTypestringatmos-uzcard-humo или atmos-visa-mastercard.atmos-uzcard-humo yoki atmos-visa-mastercard.
nextDatestring (UTC) | nullДо какого момента оплачен доступ; для активной подписки — время следующего списания.Kirish qaysi paytgacha toʻlangani; faol obuna uchun — keyingi yechish vaqti.
retryDatestring (UTC) | nullСледующая попытка списания после неудачной.Muvaffaqiyatsiz urinishdan keyingi navbatdagi yechish urinishi.
repeatTimesintegerНеудачных попыток подряд в текущем периоде.Joriy davrdagi ketma-ket muvaffaqiyatsiz urinishlar soni.
isActivebooleantrue — автопродление включено.true — avtouzaytirish yoqilgan.
userBotobjectПодписчик целиком (как в /user-bot, без user).Obunachi toʻliq (/user-bot dagidek, user siz).
planobjectТариф целиком. plan.price здесь в тийинах.Tarif toʻliq. plan.price bu yerda tiyinda.
  • Есть ли доступ сейчас: у подписчика есть запись с nextDate в будущем.Hozir kirish bormi: obunachida nextDate kelajakda boʻlgan yozuv bor.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/user-bot-plan?page=1&count=50&userBotId=100501'
ОтветJavob
{
  "data": [
    {
      "id": 70001,
      "createdAt": "2026-09-28T07:16:55.231Z",
      "lastUpdatedAt": "2026-09-28T07:17:01.903Z",
      "deletedAt": null,
      "note": null,
      "isActive": true,
      "isDeleted": false,
      "createdBy": null,
      "lastUpdatedBy": null,
      "deletedBy": null,
      "status": "active",
      "paymentType": "atmos-uzcard-humo",
      "nextDate": "2026-10-28T07:16:55.000Z",
      "retryDate": "2026-10-28T07:16:55.000Z",
      "repeatTimes": 0,
      "userBot": {
        "id": 100501,
        "firstname": "Aziz",
        "status": "created",
        "inChannel": true,
        "isUnlimited": false,
        "lang": "uz",
        "role": "user"
      },
      "plan": {
        "id": 7,
        "name": "1 oy",
        "type": "1",
        "price": "50000000",
        "status": "accepted",
        "freeTrial": 0,
        "cardRequired": true,
        "freeDays": 0
      }
    }
  ],
  "meta": {
    "message": "found",
    "statusCode": 200,
    "currentPage": 1,
    "totalPages": 1,
    "total": 3,
    "count": 50,
    "hasPrev": false,
    "hasNext": false
  }
}
POST/user-bot-plan

Выдать доступ вручнуюQoʻlda kirish berish

Открывает подписчику доступ без списания с карты: бесплатно на N дней или по тарифу, оплаченному наличными или переводом.

Obunachiga kartadan yechmasdan kirish ochadi: N kunga bepul yoki naqd pul yoxud oʻtkazma bilan toʻlangan tarif boʻyicha.

Тело запроса (JSON)Soʻrov tanasi (JSON)

ПолеMaydonТипTuriОписаниеTavsif
userBotIdобязательныйmajburiyintegerID подписчика вашего бота.Botingiz obunachisining ID si.
typeобязательныйmajburiystringfree — бесплатно; cash — наличными; transfer — переводом.free — bepul; cash — naqd pul; transfer — oʻtkazma.
dayintegerТолько для free: на сколько дней, от 1 до 200.Faqat free uchun: necha kunga, 1 dan 200 gacha.
planIdintegerТолько для cash и transfer: ID вашего тарифа в статусе accepted. Срок берётся из тарифа.Faqat cash va transfer uchun: accepted holatidagi tarifingiz ID si. Muddat tarifdan olinadi.
  • Передайте ровно одно из полей: day (для free) или planId (для cash/transfer). Иначе — 400.Maydonlardan aynan bittasini yuboring: day (free uchun) yoki planId (cash/transfer uchun). Aks holda — 400.
  • Если у человека уже действует ручной доступ или разовая оплата, новый период добавляется к его концу.Agar foydalanuvchida qoʻlda berilgan kirish yoki bir martalik toʻlov amal qilayotgan boʻlsa, yangi davr uning oxiriga qoʻshiladi.
  • Если у человека включено автопродление картой, выдать доступ нельзя — ответ 400.Agar foydalanuvchida karta orqali avtouzaytirish yoqilgan boʻlsa, kirish berib boʻlmaydi — 400 javobi.
  • Для cash и transfer создаётся запись об успешной оплате на сумму тарифа: она попадает в выручку и статистику.cash va transfer uchun tarif summasiga muvaffaqiyatli toʻlov yozuvi yaratiladi: u tushum va statistikaga kiradi.
  • Ссылку в канал человек получает сам: команда /link в боте или кнопка в мини-приложении. Сообщите ему об этом.Kanal havolasini foydalanuvchi oʻzi oladi: botdagi /link buyrugʻi yoki mini-ilovadagi tugma orqali. Bu haqda unga xabar bering.
  • Успешный ответ — HTTP 201, запись со статусом manual-active.Muvaffaqiyatli javob — HTTP 201, manual-active holatidagi yozuv.
ЗапросSoʻrov
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"userBotId":100501,"type":"free","day":30}' \
  'https://prod-api.joinpoint.uz/api/user-bot-plan'
ОтветJavob
{
  "data": {
    "id": 70002,
    "createdAt": "2026-09-29T09:00:00.000Z",
    "lastUpdatedAt": "2026-09-29T09:00:00.000Z",
    "status": "manual-active",
    "paymentType": "atmos-uzcard-humo",
    "nextDate": "2026-10-29T09:00:00.000Z",
    "retryDate": "2026-10-29T09:00:00.000Z",
    "repeatTimes": 0,
    "isActive": false,
    "note": "Manual created"
  },
  "meta": {
    "message": "created",
    "statusCode": 201
  }
}
PATCH/user-bot-plan/{id}

Отключить автопродлениеAvtouzaytirishni oʻchirish

Выключает автопродление подписки. Доступ сохраняется до nextDate, дальше списаний не будет. Тело запроса не нужно.

Obunaning avtouzaytirishini oʻchiradi. Kirish nextDate gacha saqlanadi, keyin yechishlar boʻlmaydi. Soʻrov tanasi kerak emas.

Параметры путиYoʻl parametrlari

ИмяNomiТипTuriОписаниеTavsif
idобязательныйmajburiyintegerID подписки вашего подписчика (/user-bot-plan[].id).Obunachingiz obunasining ID si (/user-bot-plan[].id).
  • После вызова статус подписки — manual-canceled, isActive = false.Chaqiruvdan soʻng obuna holati — manual-canceled, isActive = false.
  • Работает только для подписки с включённым автопродлением (isActive = true), иначе — ошибка.Faqat avtouzaytirish yoqilgan obuna uchun ishlaydi (isActive = true), aks holda — xato.
ЗапросSoʻrov
curl -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/user-bot-plan/70001'
ОтветJavob
{
  "data": {
    "id": 70001,
    "status": "manual-canceled",
    "isActive": false,
    "repeatTimes": 0,
    "nextDate": "2026-10-28T07:16:55.000Z"
  },
  "meta": {
    "message": "update",
    "statusCode": 200
  }
}
DELETE/user-bot-plan/{id}

Удалить ручной доступQoʻlda berilgan kirishni oʻchirib tashlash

Удаляет запись о ручном доступе (статус manual-active или manual-canceled). Другие подписки так удалить нельзя — ответ 400.

Qoʻlda berilgan kirish yozuvini oʻchirib tashlaydi (manual-active yoki manual-canceled holati). Boshqa obunalarni bunday oʻchirib boʻlmaydi — 400 javobi.

Параметры путиYoʻl parametrlari

ИмяNomiТипTuriОписаниеTavsif
idобязательныйmajburiyintegerID ручной подписки.Qoʻlda berilgan obuna ID si.
ЗапросSoʻrov
curl -X DELETE \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/user-bot-plan/70002'
ОтветJavob
{
  "data": {
    "status": "manual-active",
    "isActive": false
  },
  "meta": {
    "message": "removed",
    "statusCode": 200
  }
}

ПлатежиToʻlovlar

GET/transaction-meta/transactions/{botId}

ПлатежиToʻlovlar

Все платежи и попытки списания по вашему боту, включая неудачные. Выручка — записи со статусом success.

Botingiz boʻyicha barcha toʻlovlar va yechish urinishlari, muvaffaqiyatsizlari ham. Tushum — success holatidagi yozuvlar.

Параметры путиYoʻl parametrlari

ИмяNomiТипTuriОписаниеTavsif
botIdобязательныйmajburiyintegerЛюбое число: всегда используется бот из токена. Удобно передавать 0.Istalgan son: har doim tokendagi bot ishlatiladi. 0 yuborish qulay.

Параметры запросаSoʻrov parametrlari

ИмяNomiТипTuriОписаниеTavsif
pageобязательныйmajburiyintegerНомер страницы, от 1 до 500.Sahifa raqami, 1 dan 500 gacha.
countобязательныйmajburiyintegerСтрок на странице, от 5 до 200 000. Рекомендуем до 1 000.Sahifadagi qatorlar soni, 5 dan 200 000 gacha. 1 000 tagacha tavsiya qilamiz.
statusstringТолько в этом статусе, например success.Faqat shu holatdagilar, masalan success.
userBotIdintegerТолько платежи этого подписчика.Faqat shu obunachining toʻlovlari.
planIdintegerТолько по этому тарифу.Faqat shu tarif boʻyicha.
fromDatestringНачало периода, ISO 8601. Только вместе с toDate.Davr boshi, ISO 8601. Faqat toDate bilan birga.
toDatestringКонец периода, ISO 8601.Davr oxiri, ISO 8601.
searchstringПоиск по имени, телефону, username.Ism, telefon, username boʻyicha qidiruv.

Поля записи в datadata dagi yozuv maydonlari

ПолеMaydonТипTuriЧто означаетMaʼnosi
idintegerID платежа.Toʻlov ID si.
createdatstring (UTC)Когда платёж создан. Имя поля в этом методе — строчными буквами.Toʻlov qachon yaratilgani. Bu metodda maydon nomi kichik harflarda.
statusstringРезультат, см. «Статусы оплаты».Natija, «Toʻlov holatlari» boʻlimiga qarang.
pricestringСумма в сумах.Summa soʻmda.
typestringСпособ оплаты: atmos-uzcard-humo, atmos-visa-mastercard, cash, transfer и др.Toʻlov usuli: atmos-uzcard-humo, atmos-visa-mastercard, cash, transfer va boshqalar.
extIdstringИдентификатор операции; manual — ручная.Operatsiya identifikatori; manual — qoʻlda kiritilgan.
refundedatstring (UTC) | nullКогда сделан возврат.Pul qachon qaytarilgani.
refundamountnumber | nullСумма возврата.Qaytarilgan summa.
planobjectid, name, type (месяцев), price (в сумах).id, name, type (oy), price (soʻmda).
userobjectid, tgId, tgUsername, tgPhone.id, tgId, tgUsername, tgPhone.
userbotobjectПодписчик: id, firstname, status, inChannel и др.Obunachi: id, firstname, status, inChannel va boshqalar.
basketobjectmessage, code — ответ платёжной системы при ошибке.message, code — xatolik boʻlganda toʻlov tizimining javobi.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/transaction-meta/transactions/0?page=1&count=100&status=success&fromDate=2026-09-01T00:00:00Z&toDate=2026-09-30T23:59:59Z'
ОтветJavob
{
  "data": [
    {
      "id": 500001,
      "createdat": "2026-09-28T07:16:55.231Z",
      "lastUpdatedAt": "2026-09-28T07:17:01.903Z",
      "status": "success",
      "price": "500000",
      "type": "atmos-uzcard-humo",
      "extId": "5f1c2a9e-3b7d-4e61-9a0c-2d84b6e1f3a7",
      "refundedat": null,
      "refundamount": null,
      "plan": {
        "id": 7,
        "name": "1 oy",
        "type": "1",
        "price": 500000
      },
      "user": {
        "id": 900001,
        "tgUsername": "aziz_example",
        "tgId": "1234567890",
        "tgPhone": "998901234567",
        "username": null
      },
      "userbot": {
        "id": 100501,
        "firstname": "Aziz",
        "lastname": null,
        "status": "created",
        "inChannel": true,
        "isUnlimited": false,
        "lang": "uz",
        "role": "user",
        "useFreeTrial": false
      },
      "basket": {
        "message": null,
        "code": null
      },
      "transactionId": null
    }
  ],
  "meta": {
    "message": "found",
    "statusCode": 200,
    "currentPage": 1,
    "totalPages": 4,
    "total": 312,
    "count": 100,
    "hasPrev": false,
    "hasNext": true
  }
}
GET/transaction-meta/{id}

Карточка платежаToʻlov kartochkasi

Один платёж вашего бота. Сумма здесь в тийинах, номер карты замаскирован.

Botingizning bitta toʻlovi. Summa bu yerda tiyinda, karta raqami niqoblangan.

Параметры путиYoʻl parametrlari

ИмяNomiТипTuriОписаниеTavsif
idобязательныйmajburiyintegerID платежа.Toʻlov ID si.

Поля записи в datadata dagi yozuv maydonlari

ПолеMaydonТипTuriЧто означаетMaʼnosi
pricestringСумма в тийинах.Summa tiyinda.
statusstringРезультат, см. «Статусы оплаты».Natija, «Toʻlov holatlari» boʻlimiga qarang.
userIdintegerID человека (/user-bot[].user.id).Foydalanuvchi ID si (/user-bot[].user.id).
planIdintegerID тарифа.Tarif ID si.
cardNumberstringНомер карты с маской.Niqoblangan karta raqami.
userBotPlanIdinteger | nullID подписки, если записан.Obuna ID si, agar yozilgan boʻlsa.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/transaction-meta/500001'
ОтветJavob
{
  "data": {
    "id": 500001,
    "createdAt": "2026-09-28T07:16:55.231Z",
    "lastUpdatedAt": "2026-09-28T07:17:01.903Z",
    "deletedAt": null,
    "note": null,
    "isActive": true,
    "isDeleted": false,
    "createdBy": null,
    "lastUpdatedBy": null,
    "deletedBy": null,
    "extId": "5f1c2a9e-3b7d-4e61-9a0c-2d84b6e1f3a7",
    "type": "atmos-uzcard-humo",
    "price": "50000000",
    "cardNumber": "860012******3456",
    "userId": 900001,
    "botId": 42,
    "planId": 7,
    "status": "success",
    "userBotPlanId": null,
    "transactionId": null
  },
  "meta": {
    "message": "found",
    "statusCode": 200
  }
}
GET/transaction-meta/userbot/{userBotId}

Платежи подписчикаObunachi toʻlovlari

История оплат одного подписчика. Суммы в сумах.

Bitta obunachining toʻlovlar tarixi. Summalar soʻmda.

Параметры путиYoʻl parametrlari

ИмяNomiТипTuriОписаниеTavsif
userBotIdобязательныйmajburiyintegerID подписчика.Obunachi ID si.

Параметры запросаSoʻrov parametrlari

ИмяNomiТипTuriОписаниеTavsif
pageобязательныйmajburiyintegerНомер страницы, от 1 до 500.Sahifa raqami, 1 dan 500 gacha.
countобязательныйmajburiyintegerСтрок на странице, от 5 до 200 000. Рекомендуем до 1 000.Sahifadagi qatorlar soni, 5 dan 200 000 gacha. 1 000 tagacha tavsiya qilamiz.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/transaction-meta/userbot/100501?page=1&count=50'
ОтветJavob
{
  "data": [
    {
      "id": 500001,
      "createdat": "2026-09-28T07:16:55.231Z",
      "lastupdatedat": "2026-09-28T07:17:01.903Z",
      "status": "success",
      "price": "500000",
      "type": "atmos-uzcard-humo",
      "plan": {
        "id": 7,
        "name": "1 oy",
        "type": "1",
        "price": 500000
      }
    }
  ],
  "meta": {
    "message": "found",
    "statusCode": 200,
    "currentPage": 1,
    "totalPages": 1,
    "total": 4,
    "count": 50,
    "hasPrev": false,
    "hasNext": false
  }
}
GET/transaction-meta/statistics/{userBotId}

Итоги подписчикаObunachi yakunlari

Сколько подписчик заплатил за всё время.

Obunachi butun davr mobaynida qancha toʻlagani.

Параметры путиYoʻl parametrlari

ИмяNomiТипTuriОписаниеTavsif
userBotIdобязательныйmajburiyintegerID подписчика.Obunachi ID si.

Поля записи в datadata dagi yozuv maydonlari

ПолеMaydonТипTuriЧто означаетMaʼnosi
totalAmountnumberСумма успешных оплат, в сумах.Muvaffaqiyatli toʻlovlar summasi, soʻmda.
totalPlansnumberСколько было оплат.Toʻlovlar soni.
yearlyPlansnumberСколько из них годовых.Ulardan nechtasi yillik.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/transaction-meta/statistics/100501'
ОтветJavob
{
  "data": {
    "yearlyPlans": 0,
    "totalPlans": 4,
    "totalAmount": 2000000
  },
  "meta": {
    "message": "found",
    "statusCode": 200
  }
}
GET/transaction-meta/plan-summary

Выручка по тарифамTariflar boʻyicha tushum

Успешные оплаты, сгруппированные по тарифам. Суммы в сумах.

Tariflar boʻyicha guruhlangan muvaffaqiyatli toʻlovlar. Summalar soʻmda.

Параметры запросаSoʻrov parametrlari

ИмяNomiТипTuriОписаниеTavsif
fromDatestringНачало периода, ISO 8601. Только вместе с toDate.Davr boshi, ISO 8601. Faqat toDate bilan birga.
toDatestringКонец периода, ISO 8601.Davr oxiri, ISO 8601.

Поля записи в datadata dagi yozuv maydonlari

ПолеMaydonТипTuriЧто означаетMaʼnosi
plan_idintegerID тарифа.Tarif ID si.
plan_namestring | nullНазвание.Nomi.
plan_monthsstringСрок в месяцах.Muddat, oyda.
plan_pricestringЦена тарифа, сумы.Tarif narxi, soʻm.
paymentsintegerЧисло успешных оплат.Muvaffaqiyatli toʻlovlar soni.
amountstringСумма оплат, сумы.Toʻlovlar summasi, soʻm.
subscribersintegerСколько разных людей оплатили.Nechta turli foydalanuvchi toʻlagani.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/transaction-meta/plan-summary?fromDate=2026-09-01T00:00:00Z&toDate=2026-09-30T23:59:59Z'
ОтветJavob
{
  "data": [
    {
      "plan_id": 7,
      "plan_name": "1 oy",
      "plan_months": "1",
      "plan_price": "500000",
      "payments": 118,
      "amount": "59000000",
      "subscribers": 113
    }
  ],
  "meta": {
    "message": "found",
    "statusCode": 200
  }
}

ТарифыTariflar

GET/plan

ТарифыTariflar

Тарифы вашего бота. Удалённые не показываются, если не передать status=deleted. Цена здесь в сумах.

Botingiz tariflari. status=deleted yuborilmasa, oʻchirilganlari koʻrsatilmaydi. Narx bu yerda soʻmda.

Параметры запросаSoʻrov parametrlari

ИмяNomiТипTuriОписаниеTavsif
statusstringaccepted, pending, rejected, paused или deleted.accepted, pending, rejected, paused yoki deleted.

Поля записи в datadata dagi yozuv maydonlari

ПолеMaydonТипTuriЧто означаетMaʼnosi
idintegerID тарифа.Tarif ID si.
namestring | nullНазвание.Nomi.
typestringСрок в месяцах.Muddat, oyda.
pricenumberЦена в сумах.Narx soʻmda.
statusstringaccepted — продаётся, paused, pending — на модерации, rejected, deleted.accepted — sotuvda, paused, pending — moderatsiyada, rejected, deleted.
freeTrialintegerДней пробного периода.Sinov muddati, kun.
cardRequiredbooleanНужна ли карта.Karta talab qilinadimi.
freeDaysintegerДлительность бесплатного тарифа без карты, дней.Kartasiz bepul tarif davomiyligi, kun.
startingPointobject | nullСсылка, по которой доступен тариф; null — общий тариф.Tarif mavjud boʻlgan havola; null — umumiy tarif.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/plan'
ОтветJavob
{
  "data": [
    {
      "id": 7,
      "createdAt": "2025-06-02T07:14:03.120Z",
      "isActive": true,
      "name": "1 oy",
      "type": "1",
      "price": 500000,
      "status": "accepted",
      "freeTrial": 0,
      "cardRequired": true,
      "freeDays": 0,
      "startingPoint": null,
      "bot": {
        "id": 42,
        "name": "Premium kanal"
      }
    }
  ],
  "meta": {
    "message": "found",
    "statusCode": 200
  }
}
GET/plan/{id}

Карточка тарифаTarif kartochkasi

Один тариф вашего бота. Цена здесь в тийинах. Чужой тариф — ответ 403.

Botingizning bitta tarifi. Narx bu yerda tiyinda. Begona tarif — 403 javobi.

Параметры путиYoʻl parametrlari

ИмяNomiТипTuriОписаниеTavsif
idобязательныйmajburiyintegerID тарифа.Tarif ID si.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/plan/7'
ОтветJavob
{
  "data": {
    "id": 7,
    "createdAt": "2025-06-02T07:14:03.120Z",
    "name": "1 oy",
    "type": "1",
    "price": "50000000",
    "status": "accepted",
    "freeTrial": 0,
    "cardRequired": true,
    "freeDays": 0,
    "bot": {
      "id": 42,
      "name": "Premium kanal"
    },
    "userBotPlans": [
      {
        "id": 70001
      }
    ],
    "startingPoint": null
  },
  "meta": {
    "message": "found",
    "statusCode": 200
  }
}

Ссылки-источникиManba-havolalar

GET/starting-point

Ссылки-источникиManba-havolalar

Ссылки, по которым люди приходят в бота, со счётчиками.

Foydalanuvchilar botga keladigan havolalar, hisoblagichlar bilan.

Параметры запросаSoʻrov parametrlari

ИмяNomiТипTuriОписаниеTavsif
pageобязательныйmajburiyintegerНомер страницы, от 1 до 500.Sahifa raqami, 1 dan 500 gacha.
countобязательныйmajburiyintegerСтрок на странице, от 5 до 200 000. Рекомендуем до 1 000.Sahifadagi qatorlar soni, 5 dan 200 000 gacha. 1 000 tagacha tavsiya qilamiz.
searchstringПоиск по названию и метке.Nomi va belgisi boʻyicha qidiruv.
fromDatestringПересчитать счётчики за период: начало, ISO 8601. Только вместе с toDate.Hisoblagichlarni davr uchun qayta hisoblash: boshi, ISO 8601. Faqat toDate bilan birga.
toDatestringКонец периода, ISO 8601.Davr oxiri, ISO 8601.

Поля записи в datadata dagi yozuv maydonlari

ПолеMaydonТипTuriЧто означаетMaʼnosi
idintegerID ссылки.Havola ID si.
namestringНазвание.Nomi.
extIdstringМетка ссылки.Havola belgisi.
deepLinkstringГотовая ссылка в бота: https://t.me/<бот>?start=<extId>.Botga tayyor havola: https://t.me/<bot>?start=<extId>.
redirectUrlstring | nullСайт, который открывается перед ботом.Botdan oldin ochiladigan sayt.
clickCountintegerПереходы по ссылке.Havola orqali oʻtishlar.
userCountintegerЗапустили бота.Botni ishga tushirganlar.
subscribersCountintegerОформили подписку.Obuna boʻlganlar.
expireDatestring (UTC)После этой даты переходы не засчитываются.Shu sanadan keyin oʻtishlar hisobga olinmaydi.
attributionDisabledReasonstring | nullЕсли не пусто — почему переходы по ссылке сейчас не засчитываются.Boʻsh boʻlmasa — havola orqali oʻtishlar hozir nega hisobga olinmayotgani.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/starting-point?page=1&count=50'
ОтветJavob
{
  "data": [
    {
      "id": 12,
      "createdAt": "2026-03-10T09:00:00.000Z",
      "lastUpdatedAt": "2026-03-10T09:00:00.000Z",
      "deletedAt": null,
      "note": null,
      "isActive": true,
      "isDeleted": false,
      "createdBy": null,
      "lastUpdatedBy": null,
      "deletedBy": null,
      "name": "Instagram stories",
      "extId": "1759000000001",
      "redirectUrl": null,
      "clickCount": 1520,
      "userCount": 845,
      "subscribersCount": 61,
      "allowedTelegramIds": null,
      "expireDate": "2030-12-31T19:00:00.000Z",
      "deepLink": "https://t.me/my_channel_bot?start=1759000000001",
      "redirectDropsPayload": false,
      "attributionDisabledReason": null
    }
  ],
  "meta": {
    "message": "found",
    "statusCode": 200,
    "currentPage": 1,
    "totalPages": 1,
    "total": 21,
    "count": 50,
    "hasPrev": false,
    "hasNext": false
  }
}
POST/starting-point

Создать ссылку-источникManba-havola yaratish

Создаёт новую отслеживаемую ссылку. Метка extId генерируется автоматически.

Yangi kuzatiladigan havola yaratadi. extId belgisi avtomatik yaratiladi.

Тело запроса (JSON)Soʻrov tanasi (JSON)

ПолеMaydonТипTuriОписаниеTavsif
nameобязательныйmajburiystringНазвание, например «Instagram — сторис».Nomi, masalan «Instagram — storis».
expireDateобязательныйmajburiystringДо какой даты ссылка работает, ISO 8601.Havola qaysi sanagacha ishlashi, ISO 8601.
redirectUrlstringСайт, который открыть перед ботом (полный URL).Botdan oldin ochiladigan sayt (toʻliq URL).
allowedTelegramIdsstring[]Если задан, ссылка засчитывается только для этих Telegram ID.Koʻrsatilsa, havola faqat shu Telegram ID lar uchun hisobga olinadi.
  • Успешный ответ — HTTP 201. В ответе есть готовая deepLink.Muvaffaqiyatli javob — HTTP 201. Javobda tayyor deepLink bor.
ЗапросSoʻrov
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Instagram stories","expireDate":"2030-12-31T19:00:00.000Z"}' \
  'https://prod-api.joinpoint.uz/api/starting-point'
ОтветJavob
{
  "data": {
    "id": 13,
    "name": "Instagram stories",
    "extId": "1759200000077",
    "redirectUrl": null,
    "clickCount": 0,
    "userCount": 0,
    "subscribersCount": 0,
    "expireDate": "2030-12-31T19:00:00.000Z",
    "deepLink": "https://t.me/my_channel_bot?start=1759200000077",
    "redirectDropsPayload": false,
    "attributionDisabledReason": null
  },
  "meta": {
    "message": "created",
    "statusCode": 201
  }
}

ПромокодыPromokodlar

GET/promo

ПромокодыPromokodlar

Промокоды вашего бота со статистикой использования. Поля в snake_case.

Botingiz promokodlari, foydalanish statistikasi bilan. Maydonlar snake_case da.

Поля записи в datadata dagi yozuv maydonlari

ПолеMaydonТипTuriЧто означаетMaʼnosi
codestringПромокод.Promokod.
discount_typestringpercent или fixed.percent yoki fixed.
discount_valueintegerДля percent — проценты; для fixed — тийины.percent uchun — foiz; fixed uchun — tiyin.
max_usesintegerСколько раз можно применить всего.Jami necha marta qoʻllash mumkin.
used_countintegerСколько раз применён.Necha marta qoʻllangan.
per_user_oncebooleanОдин раз на человека.Bir kishiga bir marta.
valid_fromstring | nullС какого момента действует.Qaysi paytdan amal qiladi.
valid_untilstringДо какого момента действует.Qaysi paytgacha amal qiladi.
is_activebooleanВключён ли код.Kod faolmi.
plan_idinteger | nullТариф; null — все платные тарифы.Tarif; null — barcha pullik tariflar.
redemption_countintegerЧисло оплат с этим кодом.Shu kod bilan qilingan toʻlovlar soni.
discount_given_tiyinstringСумма скидок, тийины.Chegirmalar summasi, tiyin.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/promo'
ОтветJavob
{
  "data": [
    {
      "id": 3,
      "code": "STORY30",
      "discount_type": "percent",
      "discount_value": 30,
      "scope": "bot",
      "bot_id": 42,
      "plan_id": null,
      "max_uses": 100,
      "used_count": 7,
      "per_user_once": true,
      "valid_from": null,
      "valid_until": "2026-10-31T18:59:59.000Z",
      "is_active": true,
      "created_at": "2026-09-20T08:00:00.000Z",
      "updated_at": "2026-09-20T08:00:00.000Z",
      "bot_name": "Premium kanal",
      "plan_name": null,
      "redemption_count": 7,
      "discount_given_tiyin": "105000000"
    }
  ],
  "meta": {
    "message": "Promo codes",
    "statusCode": 200
  }
}
POST/promo

Создать промокодPromokod yaratish

Создаёт промокод на скидку при оформлении подписки.

Obunani rasmiylashtirishda chegirma beradigan promokod yaratadi.

Тело запроса (JSON)Soʻrov tanasi (JSON)

ПолеMaydonТипTuriОписаниеTavsif
discountTypeобязательныйmajburiystringpercent — процент, fixed — фиксированная сумма.percent — foiz, fixed — qatʼiy summa.
discountValueобязательныйmajburiyintegerДля percent — от 1 до 50. Для fixed — сумма в сумах.percent uchun — 1 dan 50 gacha. fixed uchun — summa soʻmda.
maxUsesобязательныйmajburiyintegerСколько раз код можно применить всего, от 1 до 100 000.Kodni jami necha marta qoʻllash mumkin, 1 dan 100 000 gacha.
validUntilобязательныйmajburiystringДо какого момента действует, ISO 8601, в будущем.Qaysi paytgacha amal qiladi, ISO 8601, kelajakdagi sana.
validFromstringС какого момента действует.Qaysi paytdan amal qiladi.
codestringСвой код: 3–32 символа, латиница, цифры, _ и -. Приводится к верхнему регистру. Без него код сгенерируется.Oʻz kodingiz: 3–32 belgi, lotin harflari, raqamlar, _ va -. Katta harflarga oʻtkaziladi. Koʻrsatilmasa, kod avtomatik yaratiladi.
planIdintegerТолько для этого тарифа. Без поля — для всех платных тарифов.Faqat shu tarif uchun. Maydonsiz — barcha pullik tariflar uchun.
perUserOncebooleanОдин раз на человека, по умолчанию true.Bir kishiga bir marta, standart qiymati true.
  • Цена любого тарифа после скидки должна остаться не меньше 10 сум, иначе 400.Chegirmadan keyin har qanday tarif narxi kamida 10 soʻm qolishi kerak, aks holda 400.
  • Код должен быть уникальным. Успешный ответ — HTTP 201.Kod takrorlanmas boʻlishi kerak. Muvaffaqiyatli javob — HTTP 201.
ЗапросSoʻrov
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"discountType":"percent","discountValue":30,"maxUses":100,"validUntil":"2026-10-31T18:59:59Z","code":"STORY30"}' \
  'https://prod-api.joinpoint.uz/api/promo'
ОтветJavob
{
  "data": {
    "id": 3,
    "code": "STORY30",
    "discount_type": "percent",
    "discount_value": 30,
    "scope": "bot",
    "bot_id": 42,
    "plan_id": null,
    "max_uses": 100,
    "used_count": 0,
    "per_user_once": true,
    "valid_from": null,
    "valid_until": "2026-10-31T18:59:59.000Z",
    "is_active": true,
    "created_at": "2026-09-20T08:00:00.000Z",
    "updated_at": "2026-09-20T08:00:00.000Z"
  },
  "meta": {
    "message": "Promo code created",
    "statusCode": 201
  }
}
PATCH/promo/{id}

Изменить промокодPromokodni oʻzgartirish

Включает или выключает код, меняет лимит и срок. Передайте хотя бы одно поле.

Kodni faollashtiradi yoki faolsizlantiradi, limit va muddatni oʻzgartiradi. Kamida bitta maydon yuboring.

Параметры путиYoʻl parametrlari

ИмяNomiТипTuriОписаниеTavsif
idобязательныйmajburiyintegerID промокода.Promokod ID si.

Тело запроса (JSON)Soʻrov tanasi (JSON)

ПолеMaydonТипTuriОписаниеTavsif
isActivebooleanfalse — выключить код.false — kodni faolsizlantirish.
maxUsesintegerНовый лимит, не меньше уже использованного.Yangi limit, allaqachon foydalanilganidan kam boʻlmasligi kerak.
validUntilstringНовый срок, ISO 8601.Yangi muddat, ISO 8601.
ЗапросSoʻrov
curl -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"isActive":false}' \
  'https://prod-api.joinpoint.uz/api/promo/3'
ОтветJavob
{
  "data": {
    "id": 3,
    "code": "STORY30",
    "discount_type": "percent",
    "discount_value": 30,
    "scope": "bot",
    "bot_id": 42,
    "plan_id": null,
    "max_uses": 100,
    "used_count": 7,
    "per_user_once": true,
    "valid_from": null,
    "valid_until": "2026-10-31T18:59:59.000Z",
    "is_active": false,
    "created_at": "2026-09-20T08:00:00.000Z",
    "updated_at": "2026-09-20T08:00:00.000Z",
    "bot_name": "Premium kanal",
    "plan_name": null,
    "redemption_count": 7,
    "discount_given_tiyin": "105000000"
  },
  "meta": {
    "message": "Promo code updated",
    "statusCode": 200
  }
}
DELETE/promo/{id}

Удалить промокодPromokodni oʻchirib tashlash

Удаляет код, который ни разу не применяли. Использованный код можно только выключить.

Hech qachon qoʻllanmagan kodni oʻchirib tashlaydi. Foydalanilgan kodni faqat faolsizlantirish mumkin.

Параметры путиYoʻl parametrlari

ИмяNomiТипTuriОписаниеTavsif
idобязательныйmajburiyintegerID промокода.Promokod ID si.
ЗапросSoʻrov
curl -X DELETE \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/promo/3'
ОтветJavob
{
  "data": null,
  "meta": {
    "message": "Promo code deleted",
    "statusCode": 200
  }
}

СтатистикаStatistika

GET/user-bot/today-statistics

Продажи за деньKunlik sotuvlar

Продажи и выручка за день или период. По умолчанию — за сегодня. Ответ — массив из одного объекта. Суммы в сумах, числа приходят строками.

Kun yoki davr uchun sotuvlar va tushum. Standart — bugungi kun. Javob — bitta obyektdan iborat massiv. Summalar soʻmda, sonlar satr koʻrinishida keladi.

Параметры запросаSoʻrov parametrlari

ИмяNomiТипTuriОписаниеTavsif
startDatestringНачало периода, YYYY-MM-DD.Davr boshi, YYYY-MM-DD.
endDatestringКонец периода, YYYY-MM-DD.Davr oxiri, YYYY-MM-DD.

Поля записи в datadata dagi yozuv maydonlari

ПолеMaydonТипTuriЧто означаетMaʼnosi
subscribers_in_channelstringПодписчиков в канале сейчас.Hozir kanaldagi obunachilar.
total_revenue_todaystringВыручка за период.Davr tushumi.
sales_todaystringЧисло продаж.Sotuvlar soni.
average_sale_price_todaystringСредний чек.Oʻrtacha chek.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/user-bot/today-statistics?startDate=2026-09-01&endDate=2026-09-29'
ОтветJavob
{
  "data": [
    {
      "subscribers_in_channel": "1238",
      "total_revenue_today": "61500000",
      "sales_today": "123",
      "average_sale_price_today": "500000"
    }
  ],
  "meta": {
    "message": "success",
    "statusCode": 200
  }
}
GET/user-bot/statistics/{botId}

Сводка по ботуBot boʻyicha umumiy koʻrsatkichlar

Общие показатели бота за всё время. Ответ — массив из одного объекта. Суммы в сумах.

Botning butun davr uchun umumiy koʻrsatkichlari. Javob — bitta obyektdan iborat massiv. Summalar soʻmda.

Параметры путиYoʻl parametrlari

ИмяNomiТипTuriОписаниеTavsif
botIdобязательныйmajburiyintegerЛюбое число: всегда используется бот из токена. Удобно передавать 0.Istalgan son: har doim tokendagi bot ishlatiladi. 0 yuborish qulay.

Поля записи в datadata dagi yozuv maydonlari

ПолеMaydonТипTuriЧто означаетMaʼnosi
subscribers_in_channelstringПодписчиков в канале.Kanaldagi obunachilar.
total_revenuestringВыручка за всё время.Butun davr tushumi.
all_users_countstringВсего запускали бота.Botni jami ishga tushirganlar.
average_checkstringСредний чек.Oʻrtacha chek.
subscribed / not_subscribedintegerС подпиской / никогда не оформляли.Obunasi borlar / hech qachon obuna boʻlmaganlar.
subscribed_ended_after_planintegerПодписка закончилась.Obunasi tugaganlar.
subscribed_ended_after_free_trialintegerПробный период закончился без оплаты.Sinov muddati toʻlovsiz tugaganlar.
subscriber_conversion_percentnumberКонверсия в подписку, %.Obunaga konversiya, %.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/user-bot/statistics/0'
ОтветJavob
{
  "data": [
    {
      "subscribers_in_channel": "1238",
      "total_revenue": "1832000000",
      "all_users_count": "69946",
      "starting_point_users_count": "30870",
      "average_check": "512340.55",
      "subscriber_conversion_percent": 5.2,
      "user_conversion_percent": 44.1,
      "subscribed_ended_after_free_trial": 139,
      "subscribed_ended_after_plan": 12083,
      "not_subscribed": 51210,
      "subscribed": 1238,
      "not_confirm_card": 3587
    }
  ],
  "meta": {
    "message": "success",
    "statusCode": 200
  }
}
GET/user-bot/period-statistics/{botId}

Воронка за периодDavr voronkasi

Новые пользователи, подписки и выручка за период. Ответ — массив из одного объекта. Суммы в сумах.

Davr uchun yangi foydalanuvchilar, obunalar va tushum. Javob — bitta obyektdan iborat massiv. Summalar soʻmda.

Параметры путиYoʻl parametrlari

ИмяNomiТипTuriОписаниеTavsif
botIdобязательныйmajburiyintegerЛюбое число: всегда используется бот из токена. Удобно передавать 0.Istalgan son: har doim tokendagi bot ishlatiladi. 0 yuborish qulay.

Параметры запросаSoʻrov parametrlari

ИмяNomiТипTuriОписаниеTavsif
fromDateобязательныйmajburiystringНачало периода, ISO 8601.Davr boshi, ISO 8601.
toDateобязательныйmajburiystringКонец периода, ISO 8601.Davr oxiri, ISO 8601.
ЗапросSoʻrov
curl \
  -H "Authorization: Bearer $TOKEN" \
  'https://prod-api.joinpoint.uz/api/user-bot/period-statistics/0?fromDate=2026-09-01T00:00:00Z&toDate=2026-09-30T23:59:59Z'
ОтветJavob
{
  "data": [
    {
      "starting_point_users_count": "1840",
      "all_users_count": "4120",
      "subscribed": "236",
      "subscribers_in_channel": "1238",
      "total_revenue": "118000000",
      "average_check": "500000.00",
      "user_conversion_percent": 44.6,
      "subscriber_conversion_percent": 5.7
    }
  ],
  "meta": {
    "message": "success",
    "statusCode": 200
  }
}

Справочник значенийQiymatlar maʼlumotnomasi

Статусы оплаты — status платежаToʻlov holatlari — toʻlovning status maydoni

ЗначениеQiymatЧто значитMaʼnosi
successДеньги списаны.Pul yechildi.
refundПлатёж возвращён.Toʻlov qaytarildi.
prepare_failedБанк отклонил списание (нет денег, карта заблокирована).Bank yechishni rad etdi (mablagʻ yetarli emas, karta bloklangan).
withdraw_failedСписание не прошло на последнем шаге.Yechish oxirgi bosqichda amalga oshmadi.
create_failed, confirm_failedПлатёж не удалось создать или подтвердить.Toʻlovni yaratib yoki tasdiqlab boʻlmadi.
created, preparedПлатёж в процессе или брошен.Toʻlov jarayonda yoki yakunlanmagan.

Статусы тарифаTarif holatlari

ЗначениеQiymatЧто значитMaʼnosi
acceptedОдобрен и продаётся.Maʼqullangan va sotuvda.
pendingНа модерации в JoinPoint.JoinPoint moderatsiyasida.
rejectedОтклонён модерацией.Moderatsiya tomonidan rad etilgan.
pausedПродажи на паузе, текущие подписчики продлеваются.Sotuv toʻxtatilgan, joriy obunachilar uzaytirilaveradi.
deletedУдалён.Oʻchirilgan.

Postman и OpenAPIPostman va OpenAPI

Коллекция Postman со всеми методами и примерами. Запрос «Вход» сам сохраняет токен в переменную коллекции.

Barcha metodlar va misollar jamlangan Postman kolleksiyasi. «Kirish» soʻrovi tokenni kolleksiya oʻzgaruvchisiga oʻzi saqlaydi.

  1. Скачайте коллекцию кнопкой ниже.Kolleksiyani quyidagi tugma orqali yuklab oling.
  2. В Postman: Import → выберите файл → Import.Postman’da: Import → faylni tanlang → Import.
  3. Откройте Variables коллекции, впишите phone и password и выполните запрос «Вход».Kolleksiyaning Variables boʻlimini oching, phone va password ni kiriting va «Kirish» soʻrovini bajaring.

OpenAPI 3.0 — для генерации клиента и импорта в Swagger UI, Insomnia и другие инструменты.

OpenAPI 3.0 — mijoz kodini yaratish va Swagger UI, Insomnia kabi vositalarga import qilish uchun.

Не сохраняйте пароль в коллекции, которой делитесь с коллегами: при экспорте Postman сохраняет значения переменных.

Hamkasblarga ulashadigan kolleksiyada parolni saqlamang: eksport paytida Postman oʻzgaruvchilar qiymatlarini ham saqlaydi.

ПоддержкаYordam

Вопросы по API — в Telegram @joinpoint_admin. Опишите метод, адрес и время запроса. Пароль и токен не присылайте.

API boʻyicha savollar — Telegram’da @joinpoint_admin. Metod, manzil va soʻrov vaqtini yozing. Parol va tokenni yubormang.

Версия документа от 29.09.2026.

Hujjat versiyasi: 29.09.2026.