ASL RAQAM Connect: hamkorlar uchun qo‘llanma

API versiyasi: v1 · Hujjat versiyasi: 0.9.2, 14.10.2026 (dastlabki)

Bu hujjat onlayn-kassalar (E-POS), TSD va hisob tizimlari dasturchilari uchun. Ular markirovka kodlarini tekshirishni ASL RAQAM Connect orqali ulaydi. To‘liq spetsifikatsiya OpenAPI 3.1 formatida: openapi.yaml. Endpoint va maydon nomlari, xato kodlari — ruscha qo‘llanma bilan bir xil.

Holat. API v1 tayyor va ASL BELGISI emulyatorida avtomatik testlardan o‘tadi. Ishchi va test manzillari ulanishda beriladi: hujjatda ishchi nom https://connect.aslraqam.uz ko‘rsatilgan. Hali ishlab chiqilayotgan imkoniyatlar «Keyinroq qo‘shiladi» bo‘limida.

Mundarija

  1. Connect nima qiladi
  2. 5 qadamda boshlash
  3. API ning umumiy qoidalari
  4. Merchantni ulash
  5. Kodlarni tekshirish: POST /check
  6. Verdiktlar
  7. Kassa hodisalari: POST /events
  8. Qoldiqlar, kodlar, nomuvofiqliklar
  9. Sinxronlash
  10. Inventarizatsiya
  11. Vebhuklar
  12. Foydalanish va tariflash
  13. Xatolar va limitlar
  14. Sinov muhiti: test kodlari
  15. Kod misollari
  16. Keyinroq qo‘shiladi
  17. O‘zgarishlar jurnali

1. Connect nima qiladi

Kassa markirovka kodini skanerlaydi, Connect esa soniyaning bir qismida tovarni sotish mumkinmi yoki yo‘qmi va nima uchunligini aytadi.

Kassa ASL BELGISI bilan bevosita ishlamaydi: kalitlar, limitlar, qayta urinishlar va ASL nosozliklarini Connect o‘z zimmasiga oladi.

Kassa / TSD ──HTTPS──▶  ASL RAQAM Connect  ──▶  ASL BELGISI (do‘kon kaliti)
      ▲                        │
      └──── vebhuklar ◀────────┘

Asosiy qoida: kassa Connect sababli savdoni hech qachon to‘xtatmaydi. Agar Connect 3 soniyada javob bermasa yoki 5xx qaytarsa, kassa sotadi va sotuv hodisasini keyinroq yuboradi (3.6).


2. 5 qadamda boshlash

Misollarda sinov muhiti va test kaliti ck_test_… ishlatiladi. Sinov muhiti oldindan tayyorlangan kodlari bor ASL emulyatorida ishlaydi (14-bo‘lim).

export CONNECT=https://sandbox.connect.aslraqam.uz/api/v1   # manzil ulanishda beriladi
export KEY=ck_test_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

1-qadam. Kirishni tekshiring.

curl -s $CONNECT/health
# {"status":"ok"}

2-qadam. Do‘konni (merchantni) STIR bo‘yicha ro‘yxatdan o‘tkazing.

curl -s -X POST $CONNECT/merchants \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"tin": "300000001", "name": "«Baraka» do‘koni"}'

3-qadam. Markirovkalanadigan tovarlar katalogini (GTIN) yuboring.

curl -s -X PUT $CONNECT/merchants/300000001/catalog \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"mode": "replace", "items": [{"gtin": "04780012345677", "name": "Suv 0,5 l"}]}'

4-qadam. ASL BELGISI ni ulang: do‘konning API kalitini va roziligini yuboring.

curl -s -X PUT $CONNECT/merchants/300000001/asl-key \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"key": "<do‘konning ASL API kaliti>",
       "consent": {"accepted": true, "version": "2026-10-v1", "user": "Direktor A. Karimov"}}'
# {"status":"active","organization":"…","product_groups":["14"],"expires_on":"2027-06-30T23:59:59+00:00","key_last4":"0001"}

Shundan so‘ng Connect balansni birinchi marta sinxronlashni boshlaydi. U tugagach, sync.completed vebhuki keladi.

5-qadam. Kodni kassada tekshiring.

curl -s -X POST $CONNECT/check \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  --max-time 3 \
  -d '{"merchant_tin": "300000001", "store_id": "store-01", "context": "SALE",
       "codes": ["010478001234567721OKOKOK00001"]}'
{
  "request_id": "01a13a69-0dcb-793f-9de1-319ece312fb9",
  "results": [{
    "index": 0,
    "ki": "010478001234567721OKOKOK00001",
    "verdict": "OK", "color": "green", "can_sell": true,
    "served_from": "ledger", "stale": false,
    "message": {"ru": "Можно продавать", "uz": "Sotish mumkin"},
    "hint": {"ru": "", "uz": ""},
    "product": {"gtin": "04780012345677"},
    "package": null,
    "asl": {"status": "INTRODUCED"},
    "details": {},
    "billable": false
  }],
  "summary": {"total": 1, "green": 1, "yellow": 0, "red": 0, "grey": 0, "can_sell_all": true},
  "connection": {"status": "active"}
}

Sotuvdan keyin SALE hodisasini yuboring (7-bo‘lim). Shu bilan eng kichik integratsiya tayyor.


3. API ning umumiy qoidalari

3.1. Manzil va protokol

Ishchi https://connect.aslraqam.uz/api/v1 (ishchi nom)
Sinov muhiti https://sandbox.connect.aslraqam.uz/api/v1 (ishchi nom)
Protokol faqat HTTPS, TLS 1.2+
Format JSON, UTF-8
Vaqt ISO 8601, vaqt zonasi bilan; UTC tavsiya etiladi: 2026-10-14T09:15:00Z
Pul tiyinda, butun son (1 so‘m = 100 tiyin)

3.2. Avtorizatsiya

Authorization: Bearer ck_live_…    # ishchi kalit
Authorization: Bearer ck_test_…    # test kalit
Huquq (scope) Nimaga ruxsat beradi
merchants:write merchantlar, nuqtalar, katalog, ASL kalitini ro‘yxatga olish va o‘zgartirish; nomuvofiqliklarni yopish
checks:write POST /check
events:write POST /events, hodisalarni bekor qilish
reports:read merchantlar, qoldiqlar, kodlar, nomuvofiqliklar, sinxronlash va inventarizatsiyani o‘qish
sync:write sinxronlashni qo‘lda boshlash
inventory:write inventarizatsiya
webhooks:write vebhuklarni boshqarish
usage:read foydalanish statistikasi

3.3. Merchant va nuqtalar

3.4. Idempotentlik

Kassa hodisalari uchun yaxshi amaliyot — kalitni chek ma’lumotlaridan yasash, masalan sale-{terminal_id}-{external_ref}. Shunda oflayn navbatdan qayta yuborilganda dublikat paydo bo‘lmaydi.

3.5. Kuzatuv, til, moslik

3.6. Taymautlar va fail-open (majburiy)

Qoida Qiymat
/check javobini kutish 3 soniya
Taymaut, 5xx yoki tarmoq yo‘q bo‘lsa sotishga ruxsat bering va hodisani mahalliy navbatga saqlang
Navbatdagi hodisani qachon yuborish aloqa tiklanganda, o‘sha Idempotency-Key bilan
Qancha eski hodisalar qabul qilinadi 30 kungacha; 7 kundan eskisi late belgisi bilan qabul qilinadi

ASL BELGISI nosozliklari /check da xatoga olib kelmaydi. ASL ishlamasa, Connect 200 bilan UNKNOWN verdiktini (⚪, can_sell: true) yoki stale: true belgili leder javobini qaytaradi. 5xx xatolari faqat Connect ning o‘zi nosoz bo‘lganda bo‘lishi mumkin.

3.7. Sahifalash

Ro‘yxatlar {"items": [...], "next_cursor": "…"} qaytaradi. Keyingi sahifa ?cursor=<next_cursor> bilan so‘raladi; limit 1000 dan oshmaydi (sukut bo‘yicha 100). next_cursor: null — ro‘yxat oxiri.


4. Merchantni ulash

4.1. Tartib

  1. POST /merchants merchantni ro‘yxatga oladi, holati pending.
  2. PUT /merchants/{tin}/catalog do‘kon sotadigan markirovkalanadigan GTIN lar ro‘yxatini yuboradi. Katalogni ulangandan keyin ham yuborish mumkin: yangi GTIN lar avtomatik yuklanadi.
  3. PUT /merchants/{tin}/asl-key do‘konning ASL API kalitini va roziligini yuboradi. Connect kalitni tekshiradi (10 soniyagacha), shifrlangan holda saqlaydi va birinchi sinxronlashni boshlaydi.
  4. merchant.connected vebhuki darhol keladi, sync.completed esa balans yuklangandan keyin.

4.2. Do‘konning ASL kaliti

Do‘kon API kalitini ASL BELGISI shaxsiy kabinetida yaratadi. Kalit foydalanuvchisida «Kuzatuvchi» roli «Markirovka kodlari» imtiyozi bilan bo‘lishi kerak.

PUT /merchants/300000001/asl-key
{
  "key": "<ASL API kaliti>",
  "rotation_mode": "manual",
  "consent": {"accepted": true, "version": "2026-10-v1", "user": "Direktor A. Karimov"}
}
Maydon Majb. Tavsif
key ha ASL BELGISI API kaliti. Bir marta yuboriladi; uni o‘zingizda saqlamang
consent.accepted ha true: do‘kon Connect uning nomidan ASL ga murojaat qilishiga rozi
consent.version ha do‘konga ko‘rsatilgan rozilik matni versiyasi
consent.user yo‘q rozilikni kim bergan
rotation_mode yo‘q manual (sukut): yangi kalitni hamkor yuboradi. auto va resign ERI orqali kirish ishga tushganda kerak bo‘ladi (16-bo‘lim)

Connect nimani tekshiradi: kalit formati, merchant STIR iga tegishliligi, rollar (ASL ga sinov so‘rovi), tashkilot va tovar guruhlari. Javob:

{"status": "active", "organization": "«Baraka» MChJ", "product_groups": ["14"],
 "expires_on": "2027-06-30T23:59:59+00:00", "key_last4": "0001"}

Ulanish xatolari (HTTP 422):

Kod Do‘konga nima deyish kerak
ASL_KEY_INVALID kalit noto‘g‘ri, bekor qilingan yoki muddati o‘tgan: ASL kabinetida yangisini yarating
ASL_KEY_WRONG_TIN kalit boshqa tashkilotga tegishli
ASL_INSUFFICIENT_ROLES «Kuzatuvchi» roli («Markirovka kodlari» imtiyozi bilan) yetishmaydi
ASL_UNAVAILABLE (503) ASL BELGISI vaqtincha ishlamayapti, keyinroq urinib ko‘ring
RATE_LIMITED (429) bir sutkada 10 tadan ko‘p ulanish urinishi

Ishlab turgan merchantning yangi kaliti tekshiruvdan o‘tmasa, Connect eski kalit bilan ishlashda davom etadi.

4.3. Ulanish holati

GET /merchants/{tin}/connection:

{"status": "active", "method": "manual", "key_last4": "0001",
 "expires_on": "2027-06-30T23:59:59+00:00", "key_expires_in_days": 259,
 "last_checked_at": "2026-10-14T12:34:57Z", "check_status": "ok", "missing_roles": [],
 "rotation_mode": "manual", "product_groups": ["14"], "consent_version": "2026-10-v1",
 "edo_status": null}
status Ma’nosi
pending ro‘yxatdan o‘tgan, kalit hali yuborilmagan
active ishlayapti
key_expiring kalit muddati 14 kun ichida tugaydi: do‘kondan yangisini yaratishni so‘rang
key_invalid kalit bekor qilingan yoki muddati o‘tgan, tekshiruv faqat leder bo‘yicha ishlaydi
wrong_tin, insufficient_roles kalit to‘g‘ri kelmaydi (4.2 ga qarang)
suspended operator tomonidan to‘xtatilgan
disconnected merchant uzilgan

Kalit muddati tugashi haqidagi eslatmalar merchant.connection.expiring vebhuki bilan 14, 7, 3 va 1 kun oldin keladi.

4.4. Merchant sozlamalari

PATCH /merchants/{tin}:

{"name": "«Baraka» do‘koni", "policy": "strict",
 "policy_overrides": {"NOT_INTRODUCED": "block", "PACKAGE_CODE": "warn"}}

4.5. Uzish

DELETE /merchants/{tin}: ASL kaliti darhol o‘chiriladi, leder ma’lumotlari hisobotlar uchun 90 kun saqlanadi.

4.6. Merchant uchun vidjet: sessiya

Ulash, qoldiqlar, nomuvofiqliklar va inventarizatsiya ekranlarini kassa interfeysiga vidjet sifatida joylash mumkin (vidjetning o‘zi ishlab chiqilmoqda, sessiyalar API si allaqachon ishlaydi).

  1. Sizning serveringiz bir martalik token so‘raydi (widget:issue huquqi):
POST /widget/sessions
{"merchant_tin": "300000001", "store_id": "store-01", "locale": "uz",
 "user": {"id": "u-17", "name": "Aziz", "role": "owner"},
 "scopes": ["connect", "reports", "inventory", "settings"]}
→ 201 {"token": "wt_…", "url": "https://connect.aslraqam.uz/widget/", "expires_at": "…"}
  1. Token 15 daqiqa yashaydi va bir marta almashtiriladi. Uni iframe ga sahifa manzilida emas, postMessage orqali bering: manzillar loglarga tushadi.
  2. Vidjet tokenni o‘zi sessiyaga almashtiradi (POST /widget/exchange) va uni faqat xotirada saqlaydi. Sessiya bitta merchant bilan cheklangan: begona STIR — 404.
scopes Nimani ochadi Kimga
connect ASL ni ulash faqat owner
settings rejim, override lar, uzish faqat owner
reports umumiy ko‘rinish, qoldiqlar, kodlar, nomuvofiqliklar, sinxronlash; nomuvofiqlikni faqat owner yopa oladi hammaga
inventory inventarizatsiya hammaga
invoices ESF (Didox ulangandan keyin) hammaga

Kod tekshiruvi vidjetda doim ochiq. Hamkor kaliti brauzerga hech qachon tushmaydi.


5. Kodlarni tekshirish: POST /check

5.1. So‘rov

{
  "merchant_tin": "300000001",
  "store_id": "store-01",
  "context": "SALE",
  "receipt_draft_id": "draft-1001",
  "codes": ["010478001234567721OKOKOK00001"],
  "options": {"verify_authenticity": "off"}
}
Maydon Majb. Tavsif
merchant_tin ha merchant STIR i
store_id ha nuqtaning sizning tizimingizdagi ID si
context ha SALE, RETURN, RECEIVE, INVENTORY, INFO
codes ha 1–100 ta kod, istalgan ko‘rinishda
receipt_draft_id yo‘q chek qoralamasi ID si: bir chekda bitta kod qayta skanerlanishini ushlaydi
options.verify_authenticity yo‘q off (sukut), async, sync: kripto-dum bo‘yicha haqiqiylik tekshiruvi

Kodlarni skanerdan kelganicha yuborish mumkin: GS belgilari (\u001d), qavslar (01)…(21)…, ]d2 prefiksi, kripto-dum bilan. Connect kodni o‘zi KI ga (GTIN va seriya raqami) keltiradi. Kripto-dum faqat haqiqiylikni tekshirish uchun ishlatiladi, hech qayerda saqlanmaydi va hech qachon qaytarilmaydi.

5.2. Kontekstlar

context Qachon Xususiyatlari
SALE tovarni chekka urish asosiy kontekst
RETURN xaridordan qaytarish «shu do‘kon sotgan» — OK; sotilmagan kod — RETURN_NOT_SOLD
RECEIVE tovarni qabul qilish qadoq kodi tarkibiga ochiladi (package.children), ichidagilar «mavjud» deb belgilanadi
INVENTORY inventarizatsiya qadoq tarkibini qaytaradi
INFO kod haqida ma’lumot, masalan tovar kartochkasida hech narsani o‘zgartirmaydi

5.3. Javob

Har bir kirish kodiga results[] da bitta element mos keladi, tartib o‘sha.

Maydon Tavsif
index kodning kirish massividagi o‘rni
ki normallashtirilgan KI yoki kod tanilmasa null
verdict verdikt (6-bo‘lim)
color green / yellow / red / grey
can_sell rejim va override larni hisobga olgan tavsiya
served_from ledger — lederdan, live — ASL ga jonli so‘rov, cache, fallback — ASL vaqtida javob bermadi, input — kirish ma’lumotida xato
stale true: ASL ishlamagani sababli eskirgan ma’lumot bo‘yicha javob
message {"ru", "uz"} — kassir ekrani uchun qisqa matn, 40 belgigacha
hint {"ru", "uz"} — nima qilish kerakligi haqida maslahat
product {"gtin"}
package qadoq kodi uchun: type, children_count; children[] faqat RECEIVE, INVENTORY, INFO da
asl {"status"} — kodning ASL dagi holati (INTRODUCED, WITHDRAWN…)
details aniqlashtirishlar: withdrawal_reason, sold_elsewhere, problem (kod nega tanilmadi), reason (NOT_ON_BALANCE uchun)
billable shu kod tariflanganmi
summary total, green, yellow, red, grey, can_sell_all
connection.status merchantning ulanish holati: kassa ogohlantirish ko‘rsatishi mumkin, masalan «kalit muddati tugayapti»

Misol: RECEIVE kontekstida qadoq kodi.

{
  "index": 0, "ki": "00467800123456BOX00001",
  "verdict": "OK", "color": "green", "can_sell": true, "served_from": "live",
  "package": {"type": "BOX_LV_1", "children_count": 3,
              "children": ["010478001234567721CHILD000001", "010478001234567721CHILD000002",
                           "010478001234567721CHILD000003"]},
  "asl": {"status": "INTRODUCED"}
}

5.4. Kassada qanday ko‘rsatish kerak

5.5. Qancha kutish kerak

Lederdan javob o‘nlab millisekundda keladi. ASL ga jonli so‘rov 1,5 soniya bilan cheklangan. ASL ulgurmasa, Connect leder bo‘yicha javob (stale) yoki UNKNOWN qaytaradi va tekshiruvni fonda tugatadi. Fonda kod 🔴 bo‘lib chiqsa, check.updated vebhuki keladi.


6. Verdiktlar

Verdikt Rang can_sell yumshoq / qat’iy Qachon Kassirga matn (UZ)
OK 🟢 ha / ha kod do‘kon balansida, muomalada, sotilmagan Sotish mumkin
NOT_ON_BALANCE 🟡 ha / yo‘q kod muomalada, lekin boshqa ishtirokchida: yetkazib beruvchi kodlarni o‘tkazmagan Kod balansingizda emas
NOT_INTRODUCED 🟡 ha / yo‘q do‘kon kodi, lekin muomalaga kiritilmagan Kod muomalada emas
PACKAGE_CODE 🟡 ha / yo‘q tovar birligi emas, qadoq kodi skanerlangan Bu qadoq kodi
IN_OUTGOING_INVOICE 🟡 ha / yo‘q kod xaridorga chiquvchi ESF da (Didox ulangandan keyin) Kod chiquvchi ESFda
RETURN_NOT_SOLD 🟡 ha / yo‘q faqat RETURN: kod sotilmagan Kod sotilmagan
SOLD_LOCALLY 🔴 yo‘q / yo‘q kassa hodisalari bo‘yicha shu do‘konda allaqachon sotilgan Sizda allaqachon sotilgan
ALREADY_SOLD 🔴 yo‘q / yo‘q ASL da sotuv bilan muomaladan chiqarilgan Kod avval sotilgan
WITHDRAWN 🔴 yo‘q / yo‘q boshqa sabab bilan muomaladan chiqarilgan Muomaladan chiqarilgan
WRITTEN_OFF 🔴 yo‘q / yo‘q hisobdan chiqarilgan Kod hisobdan chiqarilgan
NOT_FOUND 🔴 yo‘q / yo‘q kod ASL da yo‘q Kod topilmadi
NOT_AUTHENTIC 🔴 yo‘q / yo‘q haqiqiylik tekshiruvidan o‘tmadi Kod haqiqiy emas
INVALID_FORMAT 🔴 yo‘q / yo‘q kod shikastlangan yoki noto‘g‘ri o‘qilgan Kod noto‘g‘ri o‘qildi
DUPLICATE_IN_REQUEST 🔴 yo‘q / yo‘q kod so‘rovda yoki chek qoralamasida allaqachon bor Chekda allaqachon bor
UNKNOWN ⚪ ha / ha tekshirib bo‘lmadi: ASL ishlamayapti, taymaut Tekshiruv mavjud emas
NOT_CONNECTED ⚪ ha / ha merchant ulanmagan yoki kalit yaroqsiz, lederda ma’lumot yo‘q Tekshiruv ulanmagan
SERVICE_SUSPENDED ⚪ ha / ha hamkor kirishi to‘xtatilgan Tekshiruv to‘xtatilgan

Ikkala tildagi to‘liq matnlar va maslahatlar /check javobida (message va hint) keladi, ularni o‘zingizda saqlash shart emas.

NOT_ON_BALANCE sabablari (details.reason) Didox ulangandan keyin paydo bo‘ladi: INVOICE_NOT_SIGNED, INVOICE_SIGNED_PENDING, INVOICE_SIGNED_STUCK, INVOICE_REJECTED, NO_INVOICE. Didox siz bu maydon bo‘lmaydi.


7. Kassa hodisalari: POST /events

Kassa markirovkalangan tovar bilan har bir amal haqida xabar beradi. Shu ma’lumotlar bo‘yicha Connect qoldiqni yuritadi va nomuvofiqliklarni topadi.

{
  "merchant_tin": "300000001",
  "store_id": "store-01",
  "type": "SALE",
  "external_ref": "CHK-000123",
  "fiscal_sign": "123456789012",
  "terminal_id": "POS-1",
  "occurred_at": "2026-10-14T09:15:00Z",
  "items": [{"code": "010478001234567721OKOKOK00001", "price_tiyin": 450000}]
}
Maydon Majb. Tavsif
type ha SALE, RETURN, RECEIVE, WRITE_OFF, MOVE, INVENTORY_ADJUST
external_ref ha sizdagi chek yoki hujjat raqami
occurred_at ha kassadagi amal vaqti, vaqt zonasi bilan; 30 kundan eski va kelajakda bo‘lmasin
fiscal_sign, terminal_id yo‘q fiskal belgi va kassa raqami
to_store_id MOVE uchun qabul qiluvchi nuqta
reason WRITE_OFF uchun DAMAGE, EXPIRED, LOSS, OTHER — faqat mahalliy hisob uchun, ASL ga yuborilmaydi
items[] ha 1–1000 ta pozitsiya
items[].code ha istalgan ko‘rinishdagi kod
items[].quantity, items[].unit yo‘q sukut 1 va pcs; vaznli tovarlar uchun kg, l
items[].price_tiyin yo‘q birlik narxi
items[].override yo‘q verdiktga qarshi sotilgan: {"verdict", "reason", "approved_by"}

Javob 201:

{"event_id": 2, "accepted_items": 1, "rejected_items": [],
 "warnings": [{"index": 0, "warning": "SOLD_WITH_RED_VERDICT", "verdict": "ALREADY_SOLD"}],
 "late": false}

Hodisani bekor qilish (bekor qilingan chek): POST /events/{event_id}/reverse. Takroriy bekor qilish xato bermaydi va o‘sha natijani qaytaradi.

{"event_id": 1, "reversed": true, "reversed_at": "2026-10-14T12:34:57Z", "restored": 1}

8. Qoldiqlar, kodlar, nomuvofiqliklar

Metod Nima qaytaradi
GET /merchants/{tin}/stock?store_id=&gtin= har bir GTIN bo‘yicha: on_balance (ASL balansida va muomalada), in_stock_local (hodisalar bo‘yicha mavjud), sold_30d, open_discrepancies, last_sync_at
GET /merchants/{tin}/codes?gtin=&owned=&state=&store_id= lederdagi kodlar
GET /merchants/{tin}/codes/{kod} kod kartochkasi: ASL ma’lumotlari, mahalliy holat, oxirgi 20 hodisa, ochiq nomuvofiqliklar
GET /merchants/{tin}/discrepancies?type=&status=&severity=&store_id= nomuvofiqliklar
PATCH /merchants/{tin}/discrepancies/{id} yopish: {"status": "resolved" \| "ignored", "comment": "…"}

Faylga yuklab olish. stock, codes va discrepancies da format=csv|xlsx parametri bor: filtrlar hisobga olingan barcha sahifalar bitta faylda keladi (100 000 qatorgacha; ko‘p bo‘lsa — 422 EXPORT_TOO_LARGE, filtrni toraytiring). CSV — BOM li UTF-8 va ; ajratgich, Excel da sozlashsiz ochiladi.

curl -s -H "Authorization: Bearer $KEY" -o stock.xlsx "$CONNECT/merchants/300000001/stock?format=xlsx"

Qoldiqlar misoli:

{"items": [{"gtin": "04780012345677", "name": "Suv 0,5 l", "on_balance": 5, "in_stock_local": 4,
            "sold_30d": 1, "open_discrepancies": 0, "last_sync_at": "2026-10-14T12:34:57Z"}],
 "next_cursor": null}

Nomuvofiqlik turlari

Kod Nomi Muhimlik Do‘kon nima qilishi kerak
D1 O‘z balansidan sotilmagan yuqori yetkazib beruvchidan kodli ESF so‘rash; jarima xavfi bor
D2 Balansda 180 kundan ortiq harakatsiz turibdi past inventarizatsiya o‘tkazish
D3 Kassada sotuvsiz balansdan chiqib ketgan o‘rta tekshirish: boshqa kassada sotilgan, berilgan, hisobdan chiqarilgan
D4 Ikki marta sotilgan yuqori cheklarni tekshirish
D5 Sotuv 72 soatda ASL ga yetib bormagan yuqori chekning OFD ga yuborilishini tekshirish
D6 Inventarizatsiyada kamomad o‘rta tovarni topish yoki hisobdan chiqarish
D7 Javonda begona kod yuqori yetkazib beruvchidan kodlarni o‘tkazishni so‘rash

Sharti yo‘qolganda nomuvofiqlik avtomatik yopiladi, masalan yetkazib beruvchi kodlarni o‘tkazganda. Yuqori muhimlikdagi yangi nomuvofiqlik discrepancy.created vebhuki bilan keladi.


9. Sinxronlash

Connect do‘kon balansini ASL dan o‘zi yuklaydi: ulanganda to‘liq, keyin har kecha (harakatli GTIN lar har kuni, qolganlari haftada bir). Katalogdagi yangi GTIN lar kunduzi yuklanadi.

Qo‘lda ishga tushirish — merchant uchun soatiga 1 martadan ko‘p emas:

POST /merchants/{tin}/sync          {"gtins": ["04780012345677"]}   ← ixtiyoriy; maydonsiz — barcha GTIN lar
→ 202 {"sync_job_id": "01a13a68-…"}

GET /sync-jobs/{id}
→ {"id": "…", "kind": "manual", "status": "done", "gtins_total": 1, "gtins_done": 1,
   "codes_upserted": 6, "codes_left_balance": 3, "discrepancies_found": 2, "error": null}

status: queued, running, done, partial (GTIN larning bir qismi yuklanmadi), failed. Bir soatdan oldin qayta ishga tushirish details.retry_at bilan 429 qaytaradi. Tugagach sync.completed (birinchi va qo‘lda sinxronlash uchun) yoki sync.failed (har qanday turi uchun) vebhuki keladi.


10. Inventarizatsiya

1. POST /merchants/{tin}/inventory-sessions   {"store_id": "store-01", "scope": "all"}
                                              (yoki "scope": {"gtins": ["04780012345677"]})
   → 201 {"id": "<session_id>", "status": "open"}

2. POST /inventory-sessions/{id}/scans        {"codes": [...1000 tagacha...], "device_id": "TSD-7"}
   skanni bekor qilish: {"void": ["<ki>", ...]}

3. POST /inventory-sessions/{id}/finish       {"apply": false}

4. GET  /inventory-sessions/{id}               hisobot istalgan vaqtda
{"session_id": "…", "applied": false, "found_on_balance": 3,
 "shortage": ["…"], "shortage_count": 2,
 "foreign": ["010478001234567721FOREIGN0001"], "foreign_count": 1,
 "found_but_sold": [], "unknown_store_codes": 1,
 "by_gtin": [{"gtin": "04780012345677", "expected": 5, "found": 3}]}

11. Vebhuklar

11.1. Obuna

POST /webhooks  {"url": "https://pos.example.uz/hooks/connect",
                 "events": ["merchant.connected", "sync.completed", "discrepancy.created", "check.updated"]}
→ 201 {"id": "…", "secret": "…"}          ← sir bir marta ko‘rsatiladi (so‘rov takrorlansa — secret: null)
GET    /webhooks
DELETE /webhooks/{id}
POST   /webhooks/{id}/test                ← webhook.test sinov hodisasi

Manzil HTTPS bo‘lishi shart.

11.2. Hodisalar

Hodisa Qachon
merchant.connected ASL kaliti tekshirildi, merchant ulandi
merchant.connection.expiring ASL kaliti tugashiga 14, 7, 3, 1 kun qoldi
merchant.connection.failed kalit muddati o‘tgan yoki bekor qilingan, begona STIR, rollar yetishmaydi
sync.completed / sync.failed sinxronlash tugadi
discrepancy.created yuqori muhimlikdagi yangi nomuvofiqlik
discrepancy.resolved nomuvofiqlik yopildi
check.updated kassaga javobdan keyin fondagi tekshiruv kod verdiktini 🔴 ga o‘zgartirdi
inventory.finished inventarizatsiya tugadi
billing.period.closed oylik hisob tuzildi
edo.*, invoice.* Didox va ESF hodisalari (Didox ulangandan keyin)

11.3. Format

POST /hooks/connect HTTP/1.1
Content-Type: application/json
X-Connect-Signature: t=1760445325,v1=5f2b…
X-Connect-Event: merchant.connected
X-Connect-Delivery: 01a13a69-…

{"id": "evt_01a13a690cf578b8", "type": "merchant.connected",
 "created_at": "2026-10-14T12:35:25Z", "api_version": "v1", "merchant_tin": "300000001",
 "data": {"organization": "«Baraka» MChJ", "product_groups": ["14"], "expires_on": "2027-06-30T23:59:59+00:00"}}

11.4. Imzoni tekshirish (majburiy)

v1 = HMAC-SHA256(secret, "<t>." + so‘rovning xom tanasi), o‘n oltilik ko‘rinishda. 5 daqiqadan eski xabarlarni rad eting. Imzoni qayta seriyalangan JSON bo‘yicha emas, xom tana bo‘yicha hisoblang.

import hashlib, hmac, time

def verify(secret: str, header: str, body: bytes, tolerance: int = 300) -> bool:
    try:
        parts = dict(p.split("=", 1) for p in header.split(","))
        ts = int(parts["t"])
    except (ValueError, KeyError):
        return False
    if abs(time.time() - ts) > tolerance:
        return False
    expected = hmac.new(secret.encode(), f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts.get("v1", ""))

PHP va Node.js misollari 15-bo‘limda.

11.5. Yetkazish


12. Foydalanish va tariflash

GET /usage?date_from=2026-10-01&date_to=2026-10-31 (davr 92 kungacha):

{"items": [{"day": "2026-10-14", "merchant_tin": "300000001", "store_id": "store-01",
            "checks_total": 14, "checks_billable": 9, "events_total": 1}],
 "totals": {"checks_total": 14, "checks_billable": 9, "events_total": 1, "active_stores": 1}}

Nima tariflanmaydi: - ck_test_ test kaliti bilan so‘rovlar; - INVALID_FORMAT, DUPLICATE_IN_REQUEST, UNKNOWN, NOT_CONNECTED, SERVICE_SUSPENDED verdiktlari; - o‘sha nuqtada o‘sha kodni 10 daqiqa ichida qayta tekshirish.

Tarif shartlari (faol nuqta uchun abonent to‘lovi, tekshiruvlar kvotasi, BHM) shartnomada belgilanadi. Joriy kun ma’lumotlari so‘rov paytida yangilanadi.


13. Xatolar va limitlar

13.1. Xato formati

{"error": {"code": "MERCHANT_NOT_FOUND", "message": "Мерчант не найден",
           "message_uz": "Merchant topilmadi",
           "request_id": "01a13a69-0f6e-78d2-b7b7-05a7e9b6c832", "details": {}}}
HTTP Kod Qachon
400 VALIDATION_ERROR maydonlar noto‘g‘ri; details.fields — aynan qaysilari
401 UNAUTHORIZED kalit yo‘q, noto‘g‘ri yoki bekor qilingan
403 FORBIDDEN_SCOPE kalitda kerakli huquq yo‘q (details.required)
403 PARTNER_SUSPENDED hamkor kirishi to‘xtatilgan; /check bunda ishlaydi va SERVICE_SUSPENDED qaytaradi
403 IP_NOT_ALLOWED ruxsat etilmagan IP dan so‘rov
404 NOT_FOUND, MERCHANT_NOT_FOUND
409 IDEMPOTENCY_CONFLICT idempotentlik kaliti boshqa tana bilan ishlatilgan
409 MERCHANT_EXISTS merchant allaqachon ro‘yxatdan o‘tgan
413 PAYLOAD_TOO_LARGE tana /check uchun 256 KB dan, qolganlari uchun 5 MB dan katta
422 TOO_MANY_CODES /check da 100 tadan ko‘p kod
422 MERCHANT_NOT_READY amal uchun ASL kaliti kerak
422 EXPORT_TOO_LARGE yuklab olishda 100 000 dan ortiq qator — filtrni toraytiring
422 ASL_KEY_INVALID, ASL_KEY_WRONG_TIN, ASL_INSUFFICIENT_ROLES 4.2 ga qarang
429 RATE_LIMITED limit oshdi; Retry-After soniya kuting
500 INTERNAL_ERROR Connect nosozligi: bizga request_id ni yuboring
503 ASL_UNAVAILABLE faqat kalit ulanayotganda

13.2. Limitlar

Nima Sukut bo‘yicha limit
Bitta kalitning barcha so‘rovlari soniyasiga 100 ta, qisqa muddatda 200 tagacha
Bitta merchant bo‘yicha /check soniyasiga 20 ta
Bitta /check dagi kodlar 100
Bitta hodisadagi pozitsiyalar 1000
Bitta inventarizatsiya so‘rovidagi skanlar 1000
Qo‘lda sinxronlash merchant uchun soatiga 1 marta
ASL kalitini ulash urinishlari merchant uchun sutkasiga 10 ta

Limitlar hamkor uchun alohida sozlanadi. Har bir javobda X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset sarlavhalari bor.


14. Sinov muhiti: test kodlari

Sinov muhitida Connect ASL BELGISI emulyatori bilan ishlaydi. Test merchanti — STIR 300000001, test GTIN — 04780012345677. Sinov muhiti uchun ASL API kaliti hamkor kaliti bilan birga beriladi.

SALE kontekstidagi verdiktlar:

Kod Verdikt
010478001234567721OKOKOK00001 OK 🟢
010478001234567721FOREIGN0001 NOT_ON_BALANCE 🟡
010478001234567721NOTINTR0001 NOT_INTRODUCED 🟡
00467800123456BOX00001 PACKAGE_CODE 🟡 (RECEIVE da — OK va 3 ta ichki kod)
010478001234567721SOLD0000001 ALREADY_SOLD 🔴, shu do‘kon sotgan
010478001234567721ELSEWH00001 ALREADY_SOLD 🔴, boshqa ishtirokchi sotgan (details.sold_elsewhere)
010478001234567721WDRAWN00001 WITHDRAWN 🔴
010478001234567721WOFF0000001 WRITTEN_OFF 🔴
010478001234567721MISSING0001 NOT_FOUND 🔴
not-a-code INVALID_FORMAT 🔴
bitta so‘rovda ikki marta kelgan istalgan kod ikkinchisi — DUPLICATE_IN_REQUEST 🔴

Jadval har safar hujjat yig‘ilganda avtomatik test bilan tekshiriladi.


15. Kod misollari

15.1. Python: fail-open bilan tekshiruv

import uuid
import httpx

CONNECT = "https://connect.aslraqam.uz/api/v1"
client = httpx.Client(base_url=CONNECT, headers={"Authorization": "Bearer ck_live_…"},
                      timeout=httpx.Timeout(3.0))

def check(tin: str, store: str, codes: list[str], draft_id: str) -> dict | None:
    """None — Connect ishlamayapti: sotamiz (fail-open)."""
    try:
        r = client.post("/check", json={"merchant_tin": tin, "store_id": store, "context": "SALE",
                                        "receipt_draft_id": draft_id, "codes": codes})
        if r.status_code == 200:
            return r.json()
        if r.status_code >= 500 or r.status_code == 429:
            return None
        r.raise_for_status()          # 4xx — integratsiya xatosi, uni tuzatish kerak
    except httpx.TransportError:      # taymaut, tarmoq yo‘q
        return None

def send_sale(tin: str, store: str, receipt_no: str, terminal: str, occurred_at: str, items: list[dict]):
    # Kalit chek ma’lumotlaridan: oflayn navbatdan qayta yuborish dublikat yaratmaydi
    key = f"sale-{terminal}-{receipt_no}"
    r = client.post("/events", headers={"Idempotency-Key": key}, json={
        "merchant_tin": tin, "store_id": store, "type": "SALE", "external_ref": receipt_no,
        "terminal_id": terminal, "occurred_at": occurred_at, "items": items}, timeout=10)
    r.raise_for_status()
    return r.json()

15.2. PHP: tekshiruv

<?php
function connect_check(string $tin, string $store, array $codes): ?array {
    $ch = curl_init('https://connect.aslraqam.uz/api/v1/check');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT_MS => 3000,                       // 3 soniyadan keyin fail-open
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . getenv('CONNECT_KEY'),
            'Content-Type: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode([
            'merchant_tin' => $tin, 'store_id' => $store, 'context' => 'SALE', 'codes' => $codes,
        ]),
    ]);
    $body = curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if ($body === false || $code >= 500 || $code == 429) {
        return null;                                      // sotamiz, hodisani keyin yuboramiz
    }
    return json_decode($body, true);
}

// Vebhuk imzosini tekshirish
function connect_verify(string $secret, string $header, string $rawBody, int $tolerance = 300): bool {
    $parts = [];
    foreach (explode(',', $header) as $p) {
        [$k, $v] = array_pad(explode('=', $p, 2), 2, '');
        $parts[$k] = $v;
    }
    if (!isset($parts['t'], $parts['v1']) || abs(time() - (int)$parts['t']) > $tolerance) {
        return false;
    }
    $expected = hash_hmac('sha256', $parts['t'] . '.' . $rawBody, $secret);
    return hash_equals($expected, $parts['v1']);
}
// $raw = file_get_contents('php://input');
// connect_verify($secret, $_SERVER['HTTP_X_CONNECT_SIGNATURE'] ?? '', $raw);

15.3. JavaScript (Node.js 18+)

const CONNECT = "https://connect.aslraqam.uz/api/v1";

export async function check(tin, store, codes) {
  try {
    const r = await fetch(`${CONNECT}/check`, {
      method: "POST",
      headers: { Authorization: `Bearer ${process.env.CONNECT_KEY}`, "Content-Type": "application/json" },
      body: JSON.stringify({ merchant_tin: tin, store_id: store, context: "SALE", codes }),
      signal: AbortSignal.timeout(3000),          // 3 soniyadan keyin fail-open
    });
    if (r.status >= 500 || r.status === 429) return null;
    if (!r.ok) throw new Error(`Connect ${r.status}: ${await r.text()}`);
    return await r.json();
  } catch (e) {
    if (e.name === "TimeoutError" || e.name === "TypeError") return null;   // taymaut / tarmoq
    throw e;
  }
}

// Vebhuk imzosini tekshirish (express: app.post(path, express.raw({type: "application/json"}), …))
import crypto from "node:crypto";
export function verify(secret, header, rawBody, tolerance = 300) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=", 2)));
  const ts = Number(parts.t);
  if (!ts || Math.abs(Date.now() / 1000 - ts) > tolerance) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${ts}.`).update(rawBody).digest("hex");
  const got = Buffer.from(parts.v1 || "", "utf8");
  const exp = Buffer.from(expected, "utf8");
  return got.length === exp.length && crypto.timingSafeEqual(got, exp);
}

15.4. Ishga tushirishdan oldingi tekshiruv ro‘yxati


16. Keyinroq qo‘shiladi

Imkoniyat Holat
Do‘konni qo‘lda kalitsiz, ERI (E-IMZO) bilan kirib ulash ishlab chiqilmoqda, ASL dan ma’lumot kutilmoqda
Didox: kiruvchi va chiquvchi ESF, NOT_ON_BALANCE sabablari, /edo va /invoices metodlari ishlab chiqilmoqda
Merchant uchun o‘rnatiladigan vidjet (interfeys; sessiyalar API si tayyor — 4.6) ishlab chiqilmoqda
Hamkor kabineti: kalitlar, vebhuklar jurnali, qayta yuborish ishlab chiqilmoqda

Bu jadvaldagi metodlar /v1 ga mavjudlarini o‘zgartirmasdan qo‘shiladi.


17. O‘zgarishlar jurnali

Sana Versiya O‘zgarishlar
14.10.2026 0.9.2 Vidjet sessiyalari: POST /widget/sessions, /widget/exchange (4.6)
14.10.2026 0.9.1 Qoldiqlar, kodlar, nomuvofiqliklar uchun format=csv\|xlsx; inventarizatsiya hisoboti XLSX da; o‘zbekcha qo‘llanma
14.10.2026 0.9 Hujjatning birinchi versiyasi: API v1 (merchantlar, ASL kaliti, /check, /events, hisobotlar, sinxronlash, inventarizatsiya, vebhuklar, foydalanish)

Qo‘llab-quvvatlash: murojaat qilganda javobdagi X-Request-Id ni ilova qiling. Texnik yordam kontaktlari ulanishda beriladi.