API orqali bitta xabar yuborish: WhatsApp, Telegram va botlar

API orqali bitta xabar yuborish WhatsApp va Telegram'da: bitta so'rov, o'z matni va ilovasi, rassilkasiz. Tasdiqlash kodlari va eslatmalar uchun.

WSENDER API orqali WhatsApp va Telegram'da bitta xabar yuborish
Tizimingizda hodisa yuz berdi, bir necha soniyadan keyin xabar mijozda

Ba'zi xabarlarni kechki rassilkagacha kechiktirib bo'lmaydi. Mijoz buyurtma uchun to'lov qildi. Qabulga yozildi. Operator bilan telefonda gaplashib turib, tasdiqlash kodini so'radi.

Bunday xabar bitta odamga mo'ljallangan, bir necha daqiqa ichida kerak bo'ladi va qayta takrorlanmaydi. Uning uchun rassilka yig'ish g'alati: auditoriya bitta raqamdan iborat, matn bitta holat uchun yozilgan va bularning hammasi bitta xabar uchun.

Endi buning uchun alohida metod bor. Bitta HTTP so'rov aniq bir odamga o'z matni va ilovasi bilan bitta xabar yuboradi. Bu yerda gap faqat bitta xabar yuborish haqida, rassilkalar haqida esa rassilka API haqidagi maqolada yozilgan.

API orqali yuborish qanday ko'rinadi

Sxema oddiy: tizimingizdagi hodisa → API'ga so'rov → xabar mijozda.

Butun metod bitta POST /v1/message so'rovidan iborat va unda uchta narsa bor: qaysi akkauntdan, kimga va nima yuborish. Kalit rassilkalar uchun ishlatiladigan kalitning o'zi, u kabinetning "API" bo'limida olinadi:

bash
curl -X POST https://api.wsender.io/v1/message \
  -H "Authorization: key SIZNING_TOKENINGIZ" \
  -H "Content-Type: application/json" \
  -d '{
    "channelId": "AKKAUNT_ID",
    "phone": "+998 90 123-45-67",
    "message": { "kind": "text", "text": "84421-buyurtma to'landi, ertaga soat 12:00 da kutamiz." },
    "idempotencyKey": "order-84421-paid"
  }'

Javobda xabarning o'zi keladi, uning identifikatori va holati bilan:

json
{
  "id": "0f3c9a6e-4b12-4d8a-9f31-6c5a71e08d42",
  "mid": null,
  "status": "Queued",
  "channelId": "AKKAUNT_ID",
  "target": "Phone",
  "phone": "998901234567",
  "dialogId": null,
  "errorReason": null,
  "sendDate": null,
  "failDate": null,
  "wait": null,
  "expiresAt": "2026-09-07T21:15:04Z",
  "idempotencyKey": "order-84421-paid"
}

Akkaunt identifikatori ulangan akkauntlar ro'yxatidan olinadi (GET /v1/channel), idempotencyKey esa so'rovning siz o'zingiz beradigan kaliti, u haqda quyida gaplashamiz. dialogId maydoni xizmat shu odam bilan yozishmani topganda to'ldiriladi: keyin shu identifikator orqali o'sha dialogga javob berish mumkin. Agar bu odamga avval yozgan bo'lsangiz, maydon darhol, shu javobning o'zida to'ldirilgan bo'ladi. mid xabar yuborilgandan keyin paydo bo'ladi, bu xabarning yozishmadagi identifikatori. wait xabarni navbatda nima ushlab turganini tushuntiradi, expiresAt esa yuborilmagan xabar qachongacha kutishini ko'rsatadi: shu vaqtdan keyin u Expired sababi bilan yakunlanadi.

So'rovga javob darhol keladi va u faqat "navbatga qabul qilindi" degani. Xabarni ulangan akkauntingiz haqiqiy messenjer ilovasi orqali yuboradi. Buning uchun bir necha soniya kerak, notanish raqamga esa bir-ikki daqiqagacha: messenjerlar raqamlarni bir zumda tekshirishni yoqtirmaydi. Bot orqali tezroq: u xabarni jonli ilovasiz, to'g'ridan-to'g'ri Bot API orqali yuboradi.

Bu farq mijoz bilan telefonda gaplashayotgan operator uchun muhim. U "xabar allaqachon keldi" demaydi, "sizga xabar yuboryapman" deydi.

WhatsApp, Telegram va botlarda qabul qiluvchini qanday ko'rsatish

Qabul qiluvchi bir necha usulning biri bilan ko'rsatiladi va raqam umuman kerakmi-yo'qmi, aynan shunga bog'liq:

  • Telefon raqami istalgan odatiy ko'rinishda. Eng ko'p uchraydigan holat: raqam mijoz kartochkasida allaqachon bor.
  • Akkaunt nomi Telegram'da, agar akkauntingiz uni oldingi yozishmadan bilsa.
  • Dialog API'dan olingan identifikator yoki messenjerning o'zidagi dialog manzili bo'yicha. Bunda dialog akkauntingizga allaqachon ma'lum bo'lishi kerak: notanish manzil bilan so'rov rad etiladi, xizmat "tavakkal" urinib ko'rmaydi.

Xizmat kimga yozmoqchi bo'lganingizni taxmin qilmaydi, shuning uchun so'rovdagi to'rtta maydondan faqat bittasi to'ldiriladi:

text
"phone": "+998 90 123-45-67"
"username": "@aziz_karimov"
"dialogId": "API_DAGI_DIALOG_ID"
"dialogMid": "123456789"

Oxirgi variant messenjerning o'zidagi dialog manzili, Telegram botlarida bu chat_id. Tizimingiz messenjer manzillarini allaqachon saqlasa va bizning identifikatorlarimizni qo'shishni istamasa, u qulay.

Botlar uchun faqat dialog orqali manzillash ishlaydi. Sababi xizmatda emas: bot obunachisida raqam ham, akkaunt nomi ham bo'lmasligi mumkin, dialog esa doim bor. Bot baribir birinchi bo'lib yoza olmaydi, bu platforma cheklovi.

API orqali nima yuborish mumkin

Matn, rasm, video, audio, hujjat yoki kontakt kartochkasi. Matnda kvadrat qavs ichida bir nechta variant yozish mumkin: [Assalomu alaykum|Xayrli kun] ikkisidan biriga aylanadi, shunda xabarlar bir qolipdan chiqqandek ko'rinmaydi.

Bu yerda bir tuzoq bor, u haqda birinchi so'rovdan oldin bilgan ma'qul: kvadrat qavslar variantlarsiz ham spintaks deb hisoblanadi. [Muhim] kodingiz 1234 matni mijozga qavslarsiz, Muhim kodingiz 1234 bo'lib boradi. Shablonlaringizda qavslar bezak sifatida ishlatilsa, ularni boshqa belgi bilan almashtiring.

Fayl alohida so'rov bilan bir marta yuklanadi, keyin istalgan miqdordagi xabarlarga identifikatori orqali qo'shiladi. Yuzta mijozga yuborilgan bitta narxlar ro'yxati bitta fayl joyini egallaydi. Cheklovlar oddiy: fayl hajmi 10 MB gacha, ishlatilmagan fayl bir sutka saqlanadi va o'zi o'chadi.

Fayl oddiy forma orqali yuklanadi, javobdagi asosiy maydon id:

bash
curl -X POST https://api.wsender.io/v1/file \
  -H "Authorization: key SIZNING_TOKENINGIZ" \
  -F "file=@narxlar-2026.pdf"

Fayl ochiq havolada turgan bo'lsa, forma o'rniga url maydonli POST /v1/file/url bor: server uni o'zi yuklab oladi. So'ng identifikator xabarga qo'yiladi, turi esa kind maydonida beriladi: text, image, video, audio, file yoki contact. Rasm, video va hujjatga caption izohini qo'shish mumkin, har qanday ilovada esa qabul qiluvchi ko'radigan fileName nomi bor:

json
{
  "channelId": "AKKAUNT_ID",
  "phone": "+998 90 123-45-67",
  "message": {
    "kind": "file",
    "fileId": "YUKLANGAN_FAYL_ID",
    "fileName": "Kuzgi narxlar ro'yxati",
    "caption": "Assalomu alaykum! Gaplashganimizdek, narxlar ro'yxati. Narxlar oy oxirigacha amal qiladi."
  },
  "idempotencyKey": "price-request-1187"
}

Nom majburiy emas: u bo'lmasa, yuklangan faylning nomi olinadi. Kengaytma esa har qanday holatda qo'shiladi, uni uzatish shart emas. Rasm ham xuddi shunday, "kind": "image" bilan yuboriladi, kontakt kartochkasiga esa fayl kerak emas: { "kind": "contact", "phone": "+998 90 000-00-00" }.

Yagona istisno: kontakt kartochkasini botdan yuborib bo'lmaydi, xizmat uni faqat messenjer akkauntidan yuboradi. Bunday so'rov yuborish paytida jimgina yo'qolib ketmaydi, darhol rad etiladi.

Xabar yetib borganini qanday bilish mumkin

So'rovga kelgan javob faqat "qabul qilindi" degan edi. Natija qanday bo'lganini xizmat keyin o'zi uchta vebhuk hodisasi orqali xabar qiladi:

  • message.sent. Xabar messenjerga jo'natildi.
  • message.failed. Yuborib bo'lmadi, hodisada sababi bor: qabul qiluvchi akkauntni bloklagan, unga birinchi bo'lib yozish mumkin emas, yuboruvchi akkaunt uzilib qolgan. Yoki messenjerdagi vaqtinchalik nosozlik tufayli bir necha daqiqa davomida yuborib bo'lmadi va urinishlar tugadi: bunday xabarni shunchaki qaytadan navbatga qo'yish mumkin.
  • message.notfound. Messenjerda bunday qabul qiluvchi yo'q: na bunday raqam, na bunday akkaunt. Bu xato hisoblanmaydi, shuning uchun hodisa alohida: tuzatadigan narsa yo'q, lekin kontaktni o'z bazangizda belgilab qo'ygan ma'qul.

Bu hodisalarga alohida obuna bo'lish kerak. Vebhuk manzilini kiriting va shu hodisalarni uning filtrida sanab o'ting: busiz ular kelmaydi, hatto vebhuk rassilka hodisalariga allaqachon sozlangan bo'lsa ham. Bu ataylab qilingan. Kuniga yuzta xabar yuboradiganga har bir xabar bo'yicha hodisalar oqimi foydali, o'n minglab qabul qiluvchiga rassilka qiladigan esa uni tasodifan olmasligi kerak.

Hodisada nima keladi: xabar identifikatori, yuboruvchi akkaunt, siz qanday ko'rsatgan bo'lsangiz, o'sha ko'rinishdagi qabul qiluvchi, holat, muvaffaqiyatsizlik sababi va sanalar. Eng muhimi, so'rov bilan uzatgan o'z kalitingiz. U orqali tizimingizdagi so'rovni topasiz va bizning identifikatorlarimizni umuman saqlashingiz shart emas.

Muvaffaqiyatsizlik hodisasi shunday ko'rinadi, bu misolda qabul qiluvchi akkauntingizni bloklagan:

json
{
  "id": "7d1e0b58-3a44-4f2c-9c81-15b0f7a9d6e3",
  "type": "message.failed",
  "date": "2026-09-07T09:15:42Z",
  "payload": {
    "message": {
      "id": "0f3c9a6e-4b12-4d8a-9f31-6c5a71e08d42",
      "channelId": "AKKAUNT_ID",
      "phone": "998901234567",
      "status": "Failed",
      "errorReason": "Blocked",
      "failDate": "2026-09-07T09:15:41Z",
      "idempotencyKey": "order-84421-paid"
    }
  }
}

Sabab nima qilish kerakligini aytadi. Blocked va RestrictedSend: bu odamga shu akkauntdan yozib bo'lmaydi. ChannelDisconnected: akkaunt uzilgan, uni qayta ulang va xabarni yana yuboring. Expired va Unavailable: ajratilgan muddatda yuborib bo'lmadi, xabarni yangi kalit bilan qaytadan navbatga qo'yish mumkin.

Hodisalarni qabul qiladigan ishlov beruvchini yozishda uchta narsani hisobga oling:

  1. Bitta hodisa qayta kelishi mumkin. Masalan, serveringiz uni allaqachon qabul qilgan, lekin javob yo'lda yo'qolgan. Hodisaning id maydonini tekshiring va tizimingizdagi amalni ikkinchi marta bajarmang.
  2. O'zingiz bekor qilgan xabar uchun hodisa kelmaydi. Xabarni o'zingiz bekor qildingiz va shu so'rovga javob oldingiz: o'z amalingiz haqida sizga ikkinchi marta xabar berishning hojati yo'q.
  3. Natijani API orqali tekshirish mumkin. Yuborishdagi vaqtinchalik nosozliklarni xizmat o'zi hal qiladi. Xabarni ajratilgan muddatda yuborib bo'lmasa, u Failed holatini oladi, sozlangan faol vebhuk uchun esa sababi ko'rsatilgan message.failed hodisasi yaratiladi. Serveringiz javob bermasa, hodisa yetib bormasligi mumkin, joriy natijani esa baribir GET /v1/message/{id} orqali bilish mumkin.

Vebhuk hodisalarini yetkazish urinishlari tobora uzayib boradigan pauzalar bilan takrorlanadi, lekin har bir hodisa ko'pi bilan bir sutka saqlanadi. Bir sutka davomida faqat xatolar bo'lib, birorta muvaffaqiyatli yetkazish bo'lmasa, vebhuk to'xtatib qo'yiladi va yangi hodisalar to'planmaydi.

GET /v1/webhook javobidagi health maydonini tekshiring, serveringizdagi muammoni tuzating va POST /v1/webhook/resume ni chaqiring. Tekshiruv muvaffaqiyatli o'tsa, saqlanib qolgan hodisalarni yetkazish qayta boshlanadi; pauza paytida o'tkazib yuborilgan va muddati o'tgan hodisalar tiklanmaydi.

Vebhuk sozlashni istamasangiz, xabar holatini identifikatori bo'yicha so'rash mumkin: GET /v1/message/{id} yuborishga javob bilan bir xil tuzilmani joriy status bilan qaytaradi. Bu Queued, Sending, Sent, Failed yoki NotFound bo'ladi. Lekin ochig'ini aytsak, so'rovdan keyin darhol holat "navbatda" bo'ladi va natijani bitta murojaat bilan bilib bo'lmaydi, qayta so'rashga to'g'ri keladi. Metodda "yuborilguncha kut" rejimi ataylab yo'q: HTTP so'rovingizni bir daqiqa ochiq ushlab turish hodisa yuborishdan yomonroq. Shuning uchun bu yerda vebhuklar afzal yo'l.

Kiruvchi xabarga javob ham shu metod bilan

Metod faqat chiquvchi xabarlar uchun emas. Mijozdan kelgan yangi xabar haqida xizmat message.received hodisasi bilan xabar beradi: unda matn, yuboruvchi va dialog bor. Keyin siz o'sha yuborish so'rovi bilan, qabul qiluvchi sifatida hodisadagi dialogni ko'rsatib, javob berasiz. Shu tariqa bitta metod ustida ikki tomonlama yozishma quriladi: o'z inboksingiz, chat-bot yoki CRM bilan integratsiya. O'z inboksingizni yozishga hojat bo'lmasa, operatorlarga kabinetdan ochiladigan Dialogs yetadi: u yerda o'sha yozishma ko'rinadi, API orqali yuborilgan javoblar esa "API" deb belgilanadi.

Javobda aniq bir xabarni iqtibos qilish mumkin, xuddi messenjerning o'zida suhbat o'rtasidagi gapga javob berganingizdek. Buning uchun so'rovda iqtibos qilinayotgan xabarning identifikatori uzatiladi: u kiruvchi xabar hodisasida ham, API beradigan dialog tarixida ham bor.

O'sha POST /v1/message, faqat qabul qiluvchi dialog bo'ladi va replyToMid maydoni qo'shiladi:

json
{
  "channelId": "AKKAUNT_ID",
  "dialogId": "HODISADAGI_DIALOG_ID",
  "replyToMid": "MIJOZ_XABARI_MID",
  "message": { "kind": "text", "text": "Ha, bor. Kechgacha siz uchun band qilib qo'yaymi?" },
  "idempotencyKey": "reply-5c2e-1"
}

Ikkala identifikator ham kiruvchi xabar hodisasida keladi: dialog payload.dialog.id maydonida, xabarning o'zi payload.message.mid maydonida. Faqat shu dialogdagi xabarni iqtibos qilish mumkin. Boshqa dialogdagi xabarni xizmat qabul qilmaydi: tekshiruv so'rov paytida bo'ladi, shuning uchun xato yuborish vaqtida jimgina yo'qolib ketmaydi. Iqtibos qilinadigan xabarning turi ahamiyatga ega emas.

Asl xabar so'rovingizdan keyin o'chirilishi mumkin. Unda messenjer akkaunti xabarni iqtibossiz, oddiy xabar sifatida yuboradi: bezak tufayli matnni yo'qotishning ma'nosi yo'q. Bot bunday qila olmaydi: xabar xato bilan yakunlanadi, sababidan esa nima qilish kerakligi tushunarli bo'ladi, ya'ni xabarni iqtibossiz qaytadan yuborish kerak.

Takroriy so'rov ikkinchi xabarni yaratmaydi

Tranzaksion xabarlarning alohida muammosi bor: javob kelayotgan paytda tarmoq uzildi, kodingiz so'rovni takrorladi, mijoz ikkita bir xil xabar oldi.

So'rov bilan o'zingizning noyob kalitingizni uzating: shu kalit bilan takroriy so'rov ikkinchi xabarni yubormaydi, o'sha xabarning o'zini joriy holati bilan qaytaradi. Bu idempotentlikning standart mexanizmi, bu yerda u xabarning o'zi darajasida ishlaydi.

Xabar navbatda kutib turganda uni alohida so'rov bilan bekor qilish mumkin: DELETE /v1/message/{id}. Yuboruvchi akkaunt uni ishga olgach, bekor qilishga kech: 409 kodi va tanasida joriy holat keladi, natijani esa yuborishning o'zi hal qiladi. Bekor qilingan xabar keyin so'ralganda Failed holatida, Canceled sababi bilan qaytadi, alohida "bekor qilingan" holati yo'q.

API orqali yuborishda xizmat nimaga yo'l qo'ymaydi

Ortiqcha narsani loyihalamasligingiz uchun chegaralar haqida ochiq aytamiz.

  • Taqiqlangan mavzularni tekshirish bu yerda ham ishlaydi. Xabar so'rov paytida tekshiriladi, rad etilgan xabar navbatga tushmaydi, javobda esa sababi ko'rsatiladi. To'g'ridan-to'g'ri yuborish moderatsiyani chetlab o'tish yo'li emas.
  • Kunlik tarif limiti rassilkalar bilan umumiy. To'g'ridan-to'g'ri xabarlar uni rassilkalar bilan teng sarflaydi: bitta yuborilgan xabar tarifdagi bitta xabarga teng, metodning o'z limiti yo'q. Limitdan oshgani uchun qo'shimcha to'lov bu yerda nazarda tutilmagan: limit tugasa, so'rov rad etiladi, pullik yuborishga o'tilmaydi. Qolgan limit loyiha navbatida turgan xabarlar hisobiga ham kamayadi.
  • Bitta akkauntdan yuborishlar orasida pauza bor, bir necha soniyalik. U akkauntni kod siklidan keladigan xabarlar oqimidan himoya qiladi: mijoz bilan jonli suhbatga bu pauza xalaqit bermaydi, shu metod orqali ming xabar tarqatishga urinish esa aynan unga tiqilib qoladi.
  • Xizmat o'z raqamlarini bermaydi. Xabar sizning ulangan akkauntingiz yoki botingizdan ketadi: raqam obro'si sizniki bo'lib qoladi, mijozlarning javoblari esa odatdagi messenjer ilovangizga keladi.

Keyingi qadamlar

Metod oddiy tariflarda ishlaydi va hozir sinovdan o'tmoqda: uning alohida narxi hozircha yo'q, xabarlar tarifdagi oddiy xabarlar sifatida hisoblanadi. Bepul tarifda kuniga 15 ta xabar bor, integratsiyani yig'ish uchun bu yetarli.

O'z raqamingizga bitta so'rovdan boshlang: akkauntni ulang, kabinetning "API" bo'limida kalit oling va o'zingizga sinov xabarini yuboring. Keyin hodisalarga obuna qo'shing va chaqiruvni tizimingizda hodisa paydo bo'ladigan joyga qo'ying.

Metodlarning to'liq tavsifi va so'rovni to'g'ridan-to'g'ri brauzerdan bajarish imkoniyati API hujjatlarida bor, klientni generatsiya qilish uchun spetsifikatsiya esa OpenAPI faylida.