Tashqi to'lov API
O'zingizning saytingiz yoki ilovangizdan mijozlardan to'lov qabul qiling — Telegram bot yoki kanalga bog'liq bo'lmagan holda. Karta ma'lumotlari hech qachon sizning serveringizga tegmaydi.
API kalit oling
Admin panel → Sotuv → Tashqi API → Kalit yaratish.
Buyurtma yarating
POST /orders — summasi va callbackUrl bilan.
Mijozni yo'naltiring
Javobdagi checkoutUrlga redirect qiling.
Natijani oling
To'lovdan keyin callbackUrlga webhook keladi.
Kirish
Bu — Stripe Checkout / Payme kabi "hosted checkout" modeli: karta ma'lumotlarini siz emas, Subo qabul qiladi va saqlaydi (Atmos tanlanganda), yoki mijoz Click/Payme'ning o'z sahifasida to'laydi (o'sha provayderlar tanlanganda). Ikkala holatda ham sizning integratsiya kodingiz bir xil qoladi.
https://subo.uz/api/external/v1/ manzili ostida joylashgan.
Javoblar va xato xabarlari JSON formatida.
Autentifikatsiya
API kalitingizni Subo admin panelida — Sotuv → Tashqi API bo'limida yaratasiz. Kalit faqat yaratilgan paytda bir marta to'liq ko'rsatiladi, shuning uchun darhol xavfsiz joyga saqlab qo'ying — keyinroq faqat qayta yaratish (eskisini bekor qilib) mumkin.
Har bir so'rovga Authorization headerini qo'shing.
POST /api/external/v1/orders HTTP/1.1
Host: subo.uz
Authorization: Bearer sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
Ishlash oqimi
- Serveringiz
POST /ordersso'rovini API kaliti bilan yuboradi. - Subo buyurtmani yaratadi va javobda
checkoutUrlqaytaradi. - Mijozni shu
checkoutUrlga yo'naltirasiz. - Mijoz to'lovni amalga oshiradi — Subo checkout sahifasida (Atmos) yoki Click/Payme sahifasida.
- Subo to'lov natijasini
callbackUrlingizga webhook orqali yuboradi. - Serveringiz
GET /orders/:orderIdbilan holatni yakuniy tasdiqlaydi.
Click yoki Payme tanlanganda 3- va 4-qadamlar orasida qo'shimcha bir bosqich bor: mijoz Click/Payme'ning o'z sahifasida to'laydi, ular esa to'g'ridan-to'g'ri Subo bilan (sizdan mustaqil ravishda) gaplashib, natijani tasdiqlaydi. Bu qism butunlay Subo tomonidan boshqariladi — sizga hech qanday qo'shimcha kod yozish shart emas.
To'lov provayderlari
Subo 3 ta to'lov tizimini qo'llab-quvvatlaydi: Atmos, Click va Payme. Har birini admin panelda — Sotuv → Tashqi API → To'lov provayderlari bo'limida alohida sozlaysiz. Bir nechta provayder bir vaqtda faol bo'lishi mumkin.
Buyurtma yaratishda provider maydoni orqali qaysi tizim ishlatilishini
tanlaysiz. Ko'rsatilmasa, sozlangan birinchi provayder avtomatik ishlatiladi. Sizning
integratsiyangiz kodi provayderdan qat'i nazar o'zgarmaydi.
| Provayder | Karta kiritiladigan joy | Saqlangan karta |
|---|---|---|
| Atmos | Subo'ning o'z checkout sahifasida | Qo'llab-quvvatlanadi (batafsil) |
| Click | Click'ning o'z sahifasida (my.click.uz) | Click o'zi boshqaradi |
| Payme | Payme'ning o'z sahifasida (checkout.paycom.uz) | Payme o'zi boshqaradi |
Buyurtma yaratish
/external/v1/ordersSo'rov maydonlari
| Maydon | Turi | Tavsif | |
|---|---|---|---|
amountTiyin | integer | majburiy | Summa tiyinda (1 so'm = 100 tiyin). Min 1000, maks 500 000 000. |
provider | enum | ixtiyoriy | "ATMOS" / "CLICK" / "PAYME". Ko'rsatilmasa sozlangan birinchi provayder ishlatiladi. |
description | string | ixtiyoriy | Mijozga ko'rsatiladigan tavsif. |
externalReference | string | ixtiyoriy | Sizning buyurtma ID'ingiz. Qayta yuborilsa, mavjud buyurtma qaytariladi (idempotentlik). |
customerId | string | ixtiyoriy | Mijoz ID'ingiz. Faqat Atmos: karta shu ID'ga saqlanadi (batafsil). |
customerName | string | ixtiyoriy | Checkout sahifasida ko'rsatiladi. |
customerContact | string | ixtiyoriy | Faqat ma'lumot uchun. |
callbackUrl | URL | ixtiyoriy | To'lov yakunlangach webhook shu manzilga yuboriladi. |
returnUrl | URL | ixtiyoriy | To'lovdan keyin qaytariladigan manzil. |
checkoutUrlga yo'naltiring. Havola 30 daqiqa amal qiladi.POST /api/external/v1/orders HTTP/1.1
Host: subo.uz
Authorization: Bearer sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
// so'rov tanasi
{
"amountTiyin": 5000000,
"provider": "CLICK",
"description": "Frontend kursi — 1-oy",
"externalReference": "order-1234",
"customerId": "user-777",
"customerName": "Alisher Vali",
"callbackUrl": "https://sizning-saytingiz.uz/webhooks/subo",
"returnUrl": "https://sizning-saytingiz.uz/thank-you?order=1234"
}
// javob 201
{
"orderId": "b1e2c3d4-...",
"status": "PENDING",
"provider": "CLICK",
"checkoutUrl": "https://subo.uz/pay/9f8e7d6c5b4a...",
"externalReference": "order-1234",
"customerId": "user-777",
"amountTiyin": "5000000",
"description": "Frontend kursi — 1-oy",
"customerName": "Alisher Vali",
"atmosTransactionId": null,
"providerTransactionId": null,
"failureReason": null,
"paidAt": null,
"createdAt": "2026-09-12T12:00:00.000Z",
"expiresAt": "2026-09-12T12:30:00.000Z"
}
curl -X POST https://subo.uz/api/external/v1/orders \
-H "Authorization: Bearer sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"amountTiyin": 5000000,
"provider": "CLICK",
"description": "Frontend kursi — 1-oy",
"externalReference": "order-1234",
"customerId": "user-777",
"customerName": "Alisher Vali",
"callbackUrl": "https://sizning-saytingiz.uz/webhooks/subo",
"returnUrl": "https://sizning-saytingiz.uz/thank-you?order=1234"
}'
const res = await fetch('https://subo.uz/api/external/v1/orders', {
method: 'POST',
headers: {
Authorization: 'Bearer sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
amountTiyin: 5000000,
provider: 'CLICK',
description: 'Frontend kursi — 1-oy',
externalReference: 'order-1234',
customerId: 'user-777',
customerName: 'Alisher Vali',
callbackUrl: 'https://sizning-saytingiz.uz/webhooks/subo',
returnUrl: 'https://sizning-saytingiz.uz/thank-you?order=1234',
}),
});
const order = await res.json();
// mijozni order.checkoutUrl'ga yo'naltiring
Buyurtma holatini olish
/external/v1/orders/:orderId
Javob yuqoridagi bilan bir xil shaklda, joriy status bilan
(PENDING / PAID / FAILED / EXPIRED).
To'langanda providerTransactionId to'ldiriladi. Webhook kelgach,
holatni shu endpoint orqali qayta tekshirish tavsiya etiladi.
GET /api/external/v1/orders/b1e2c3d4-... HTTP/1.1
Host: subo.uz
Authorization: Bearer sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
curl https://subo.uz/api/external/v1/orders/b1e2c3d4-... \
-H "Authorization: Bearer sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Checkout sahifasi
checkoutUrl — Subo domenida joylashgan, mustaqil to'lov sahifasi
(https://subo.uz/pay/<token>). Uni brauzerda yangi oynada oching yoki
to'g'ridan-to'g'ri shu manzilga redirect qiling. Sahifa login talab qilmaydi.
Atmos tanlangan bo'lsa: mijoz summani va tavsifni ko'radi → karta raqami + amal qilish muddatini kiritadi → SMS kodni kiritadi → to'lov yakunlanadi.
Click yoki Payme tanlangan bo'lsa: sahifa mijozni darhol o'sha provayderning o'z to'lov sahifasiga yo'naltiradi.
Saqlangan karta (takroriy mijoz)
Faqat Atmos provayderi uchun. Agar buyurtma yaratishda customerId
yuborsangiz va mijoz to'lovni muvaffaqiyatli yakunlasa, uning kartasi (Atmos token
sifatida, shifrlangan holda) shu customerIdga bog'lab saqlanadi.
Keyingi safar bir xil customerId bilan yangi buyurtma
yaratsangiz, checkout sahifasi kartani qayta kiritishni so'ramaydi — mijozga saqlangan
karta ko'rsatiladi va u faqat bitta tugma bosib to'laydi.
Webhook
Buyurtma yakunlangach (muvaffaqiyatli yoki muvaffaqiyatsiz), agar
callbackUrl berilgan bo'lsa, o'sha manzilga POST
so'rovi yuboriladi — provayderdan qat'i nazar bir xil shaklda.
event qiymati order.paid yoki order.failed
bo'ladi.
GET /orders/:orderIdni chaqirib holatni
rasmiy manbadan tasdiqlang. Yetkazib berish 5 marta (eksponensial kutish bilan)
qayta urinadi.
POST https://sizning-saytingiz.uz/webhooks/subo HTTP/1.1
Content-Type: application/json
{
"event": "order.paid",
"orderId": "b1e2c3d4-...",
"externalReference": "order-1234",
"amountTiyin": "5000000",
"status": "PAID",
"paidAt": "2026-09-12T12:05:32.000Z",
"sandbox": false
}
app.post('/webhooks/subo', async (req, res) => {
const { orderId } = req.body;
// Ishonchli manbadan tasdiqlang — tanaga to'g'ridan-to'g'ri ishonmang.
const order = await fetch(
`https://subo.uz/api/external/v1/orders/${orderId}`,
{ headers: { Authorization: 'Bearer sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' } }
).then((r) => r.json());
if (order.status === 'PAID') {
// ... obunani faollashtiring / buyurtmani yakunlang ...
}
res.sendStatus(200); // muhim: aks holda qayta urinib turadi
});
Xatoliklar
| Kod | Sabab |
|---|---|
401 | API kaliti berilmagan, noto'g'ri yoki bekor qilingan. |
400 | So'rov ma'lumotlari noto'g'ri, yoki to'lov jarayonida xatolik (message maydonida o'zbek tilida tushuntirish). |
404 | Buyurtma yoki checkout havolasi topilmadi. |
{
"statusCode": 400,
"message": "Karta balansida mablag' yetarli emas",
"error": "Bad Request"
}
Sandbox muhiti
Integratsiyani haqiqiy to'lovlarsiz sinash uchun sotuvchidan Sandbox
turidagi API kaliti so'rang — u sk_test_ bilan boshlanadi. Bu kalit bilan
yaratilgan buyurtmalar hech qanday to'lov tizimiga (Click, Payme, Atmos) bormaydi,
haqiqiy pul yechilmaydi va ular sotuvchining daromad statistikasiga kirmaydi.
So'rovlar, javoblar va webhook'lar production bilan bir xil — faqat checkout sahifasida karta formasi o'rniga natijani o'zingiz tanlaydigan ikki tugma chiqadi:
- To'lov muvaffaqiyatli (test) — buyurtma
PAIDholatiga o'tadi vaorder.paidwebhooki yuboriladi. - To'lov xato (test) — buyurtma
FAILEDholatiga o'tadi vaorder.failedwebhooki yuboriladi.
"sandbox": true keladi.
Production ishlovchingiz shu maydon bo'yicha test hodisalarini ajratib tashlashi
mumkin. Tayyor bo'lgach sotuvchidan production kaliti (sk_) so'raysiz —
kodingizda faqat kalitni almashtirasiz, boshqa hech narsa o'zgarmaydi.
POST https://sizning-saytingiz.uz/webhooks/subo HTTP/1.1
Content-Type: application/json
{
"event": "order.paid",
"orderId": "b1e2c3d4-...",
"externalReference": "order-1234",
"amountTiyin": "4900000",
"status": "PAID",
"paidAt": "2026-09-25T13:40:11.000Z",
"sandbox": true
}
Atmos test kartalari
Atmos test rejimida quyidagi test kartalaridan foydalaning (SMS kodi hammasi uchun 111111):
| Karta raqami | Amal qilish muddati |
|---|---|
8600 4907 4431 3347 | 10/24 |
8600 3329 1424 9390 | 09/25 |
8600 4929 9340 7481 | 10/24 |
9860 0901 0143 1907 | 05/25 |
Click va Payme uchun test kartalar o'sha tizimlarning o'z hujjatlarida beriladi.
Cheklovlar
- Checkout havolasi yaratilgandan keyin 30 daqiqa amal qiladi.
- Summa: minimal 1 000 tiyin (10 so'm), maksimal 500 000 000 tiyin (5 000 000 so'm).
- Har bir admin hisobida bir vaqtning o'zida 3 tagacha faol API kaliti bo'lishi mumkin (masalan alohida Sandbox va Production kalitlari).
Savol-javob
Click/Payme'ning callback'larini o'zim yozishim kerakmi?
Yo'q. Bularning barchasi Subo tomonida avtomatik boshqariladi. Siz faqat POST /orders chaqirasiz va o'z callbackUrlingizda oddiy JSON qabul qilasiz.
Bir vaqtning o'zida Atmos, Click va Payme'dan barchasini ishlata olamanmi?
Ha. Har birini alohida sozlaysiz, so'ng har bir buyurtmada provider maydoni orqali tanlaysiz.
Webhook kelmasa nima qilishim kerak?
GET /orders/:orderIdni davriy ravishda chaqirib, "kutilayotgan" buyurtmalar holatini o'zingiz tekshirib turishingiz mumkin.
Test qanday amalga oshiriladi?
Atmos uchun — sandbox rejimda yuqoridagi test kartalar bilan. Click/Payme uchun — ularning o'zlaridan test hisob so'rab, shu ma'lumotlar bilan sozlang.