MirPay API hujjatlari
Virtual kassangizga to‘lovlarni qabul qilishni ulash uchun to‘liq qo‘llanma. Barcha so‘rovlar HTTPS orqali, javoblar JSON formatida.
Kirish
MirPay API orqali siz o‘z saytingiz yoki ilovangizdan to‘lov yaratasiz, mijozni to‘lov sahifasiga yo‘naltirasiz va natijani callback orqali olasiz.
Kassa ID va API kalit
- Ro‘yxatdan o‘ting va emailingizni tasdiqlang.
- Identifikatsiya hujjatlarini yuklang va tasdiqlanishini kuting.
- Virtual kassa oching — do‘kon ma’lumotlari va webhook manzilini kiriting.
- Kassa tasdiqlangach Kassalarim → Batafsil oynasida Kassa ID, API kalit va Callback sirini ko‘rasiz.
To‘lov oqimi
Invoice yaratasiz
Serveringiz /api/v2/pay ga so‘rov yuboradi va payid hamda redirect_url oladi.
Mijozni yo‘naltirasiz
Mijoz redirect_url bo‘yicha MirPay to‘lov sahifasida kartasini kiritadi va SMS kodni tasdiqlaydi.
Natijani olasiz
MirPay sizning webhook manzilingizga imzolangan POST yuboradi. Qo‘shimcha ravishda holatni so‘rab ham olishingiz mumkin.
success_url ga qaytishi to‘lov dalili emas.
Avtorizatsiya
Barcha himoyalangan endpointlar Bearer token talab qiladi.
Token kassaid va api_key juftligi orqali olinadi va
faqat o‘sha kassa nomidan amal qiladi.
Authorization: Bearer <access_token> Content-Type: application/json Accept: application/json
Token olish
| Parametr | Turi | Tavsif |
|---|---|---|
| kassaid majburiy | integer | Kassangiz raqami |
| api_key majburiy | string | Kassa API kaliti |
curl -X POST https://mirpay.uz/api/v2/kassa/token \
-H "Content-Type: application/json" \
-d '{"kassaid": 1408, "api_key": "sizning_api_kalitingiz"}'
{
"success": true,
"message": "Muvaffaqiyatli!",
"data": {
"token_type": "Bearer",
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs..."
}
}
{
"success": false,
"message": "Parametrlar yaroqsiz!"
}
Bu endpoint daqiqasiga 10 marta chaqirilishi mumkin. Tokenni har so‘rovda emas, keshda saqlab ishlating.
Kassa ma’lumoti
Token qaysi kassaga tegishli ekanini tekshirish uchun.
{
"success": true,
"message": "OK",
"data": {
"kassa_id": 1408,
"owner_user_id": "3"
}
}
Invoice yaratish
| Parametr | Turi | Tavsif |
|---|---|---|
| summa majburiy | numeric | To‘lov summasi so‘mda. 1 000 — 100 000 000 oralig‘ida. |
| info_pay majburiy | string(255) | Buyurtma tavsifi. Mijozga to‘lov sahifasida ko‘rinadi. |
curl -X POST https://mirpay.uz/api/v2/pay \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"summa": 250000, "info_pay": "Buyurtma #1042"}'
{
"success": true,
"message": "Muvaffaqiyatli",
"data": {
"payid": "3d86e36e-d91a-4258-9e36-8f09366c6c13",
"payinfo": {
"status": "Jarayonda",
"order_info": "Buyurtma #1042",
"summa": 250000,
"yaratilgan": "2026-08-11T10:15:00.000000Z",
"redirect_url": "https://mirpay.uz/pay/3d86e36e-d91a-4258-9e36-8f09366c6c13"
}
}
}
payid ni o‘z bazangizda buyurtmaga bog‘lab saqlang —
callback aynan shu qiymat bilan keladi.
To‘lov holati
Faqat o‘z kassangizga tegishli to‘lovni ko‘ra olasiz — boshqa kassaning
payid siga 403 qaytadi.
{
"success": true,
"message": "OK",
"data": {
"payinfo": {
"payid": "3d86e36e-d91a-4258-9e36-8f09366c6c13",
"summa": 250000,
"comment": "Buyurtma #1042",
"status": "Muvaffaqiyatli",
"sana": "2026-08-11T10:15:00.000000Z"
}
}
}
Invoice (muqobil endpoint)
/api/v2/pay bilan bir xil vazifani bajaradi, lekin
parametr nomlari boshqacha. Yangi loyihalarda /api/v2/pay ni tavsiya qilamiz.
| Parametr | Turi | Tavsif |
|---|---|---|
| amount majburiy | numeric | Summa (1 000 — 100 000 000) |
| comment | string(255) | Izoh |
{
"success": true,
"message": "Invoice yaratildi",
"data": {
"payid": "3d86e36e-d91a-4258-9e36-8f09366c6c13",
"status": "Jarayonda",
"amount": 250000,
"storeid": "1408"
}
}
{
"success": true,
"message": "OK",
"data": {
"payid": "3d86e36e-d91a-4258-9e36-8f09366c6c13",
"status": "Muvaffaqiyatli",
"amount": 250000,
"comment": "Buyurtma #1042",
"send": 1
}
}
Balans
{
"success": true,
"message": "OK",
"data": {
"kassa_id": 1408,
"balans": 1750000
}
}
Ping
Integratsiyani tekshirish uchun. Token talab qilmaydi.
{"success": true, "message": "V2 API OK", "data": []}
Callback va imzo tekshirish
To‘lov holati aniqlangach MirPay sizning kassangizda ko‘rsatilgan manzilga
application/x-www-form-urlencoded ko‘rinishida POST yuboradi.
| Maydon | Turi | Tavsif |
|---|---|---|
| payid | string | Invoice identifikatori |
| summa | string | Haqiqiy to‘langan summa |
| status | string | Muvaffaqiyatli! yoki Bekor qilindi! |
| comment | string | Buyurtma izohi (URL-kodlangan) |
| chek | string | Chek sahifasiga havola |
| fiskal | string | Fiskal chek havolasi |
| sana | string | Yaratilgan sana, d.m.Y H:i:s |
Sarlavhalar
X-MirPay-Kassa-Id: 1408 X-MirPay-Timestamp: 1786443365 X-MirPay-Signature: 5f2c9a1e... (HMAC-SHA256, hex)
Imzo quyidagicha hisoblanadi:
signature = HMAC_SHA256(timestamp + "." + raw_body, callback_secret)
Bu yerda raw_body — so‘rovning xom tanasi
(payid=...&summa=...), callback_secret —
Kassalarim sahifasidagi maxfiy kalit.
PHP
<?php
$secret = getenv('MIRPAY_CALLBACK_SECRET');
$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_MIRPAY_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_MIRPAY_SIGNATURE'] ?? '';
$expected = hash_hmac('sha256', $ts . '.' . $body, $secret);
if (!hash_equals($expected, $sig)) {
http_response_code(403);
exit('bad signature');
}
// Takroriy so'rovga qarshi: 5 daqiqadan eski bo'lmasin
if (abs(time() - (int) $ts) > 300) {
http_response_code(408);
exit('stale');
}
parse_str($body, $data);
// $data['payid'], $data['status'], $data['summa']
// Buyurtmani shu yerda tasdiqlang — idempotent bo'lsin!
http_response_code(200);
echo 'ok';
Node.js (Express)
const crypto = require('crypto');
const express = require('express');
const app = express();
app.post('/mirpay/callback',
express.raw({ type: 'application/x-www-form-urlencoded' }),
(req, res) => {
const body = req.body.toString('utf8');
const ts = req.get('X-MirPay-Timestamp') || '';
const sig = req.get('X-MirPay-Signature') || '';
const expected = crypto
.createHmac('sha256', process.env.MIRPAY_CALLBACK_SECRET)
.update(ts + '.' + body)
.digest('hex');
const ok = sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
if (!ok) return res.status(403).send('bad signature');
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
return res.status(408).send('stale');
}
const data = Object.fromEntries(new URLSearchParams(body));
// data.payid, data.status, data.summa
res.send('ok');
});
Python (Flask)
import hmac, hashlib, os, time
from urllib.parse import parse_qs
from flask import request, abort
SECRET = os.environ['MIRPAY_CALLBACK_SECRET'].encode()
@app.post('/mirpay/callback')
def callback():
body = request.get_data(as_text=True)
ts = request.headers.get('X-MirPay-Timestamp', '')
sig = request.headers.get('X-MirPay-Signature', '')
expected = hmac.new(SECRET, f'{ts}.{body}'.encode(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sig):
abort(403)
if abs(time.time() - int(ts or 0)) > 300:
abort(408)
data = {k: v[0] for k, v in parse_qs(body).items()}
# data['payid'], data['status'], data['summa']
return 'ok'
payid ikki marta kelsa, buyurtma ikki marta bajarilmasin.
Limitlar va cheklovlar
| Cheklov | Qiymat | Izoh |
|---|---|---|
| Eng kam summa | 1 000 so‘m | Global |
| Eng ko‘p summa | 100 000 000 so‘m | Global |
| Tranzaksiya limiti | kassa sozlamasi | Kassa tahrirlash sahifasida belgilanadi |
| Kunlik limit | kassa sozlamasi | Bir kunda qabul qilinadigan jami summa |
| IP oq ro‘yxati | kassa sozlamasi | To‘ldirilsa — API faqat shu IP’lardan ishlaydi |
| Token olish | 10 / daqiqa | IP bo‘yicha |
| Boshqa endpointlar | 120 / daqiqa | Token bo‘yicha |
Limitdan oshsangiz 429 Too Many Requests qaytadi.
Retry-After sarlavhasiga qarab kuting.
Statuslar va xatoliklar
To‘lov statuslari
| Javobdagi qiymat | Ma’nosi |
|---|---|
| Jarayonda | Invoice yaratilgan, hali to‘lanmagan |
| Muvaffaqiyatli | To‘lov o‘tdi, mablag‘ kassa balansiga qo‘shildi |
| Bekor qilingan! | Muddati tugagan yoki bekor qilingan |
HTTP kodlari
| Kod | Sabab |
|---|---|
| 200 / 201 | Muvaffaqiyatli |
| 401 | Token yo‘q, muddati tugagan yoki kalit noto‘g‘ri |
| 403 | Boshqa kassaning ma’lumoti, bloklangan kassa yoki ruxsat etilmagan IP |
| 404 | To‘lov topilmadi |
| 422 | Parametrlar noto‘g‘ri yoki limitdan oshgan |
| 429 | So‘rovlar chastotasi oshib ketdi |
{
"success": false,
"message": "To‘lov summasi juda katta. Ruxsat etilgan eng yuqori summa: 100 000 000 so‘m.",
"errors": {
"summa": ["The summa field must not be greater than 100000000."]
}
}
Eski v1 API
Avvalgi integratsiyalar uchun saqlanmoqda. Javob formatlari o‘zgarmagan.
POST /api/connect
{"kassaid": 1408, "api_key": "..."}
→ {"token": "eyJ0eXAi...", "natija": "Muvaffaqiyatli!"}
POST /api/create-pay
{"summa": 250000, "info_pay": "Buyurtma #1042"}
→ {
"id": "3d86e36e-...",
"payinfo": {
"status": "jarayonda",
"order_info": "Buyurtma #1042",
"summa": 250000,
"yaratilgan": "2026-08-11T10:15:00.000000Z",
"redicet_url": "https://mirpay.uz/pay/3d86e36e-..."
},
"natija": "Muvaffaqiyatli"
}
Diqqat: v1 da maydon nomi redicet_url (imlo xatosi bilan) —
moslik uchun o‘zgartirilmagan. v2 da u redirect_url.
POST /api/pay/invoice/
{"payid": "3d86e36e-..."}
→ {"payinfo": {
"payid": "3d86e36e-...",
"summa": "250000",
"comment": "Buyurtma #1042",
"status": "Muvaffaqiyatli",
"sana": "2026-08-11T10:15:00.000000Z"
}}
{"balans": 1750000}