General Information Information exchange with the SBP server is realized via RESTful API. All requests to the server must be executed via HTTPS using GET||POST||PUT||DELETE requests to the given ROOT address. Body of requests must be in JSON format. All not public requests must be signed by the client and the public key must be sent to the server for client identification and sign checking. Header: “Authorization”: {JSON WITH KEY AND PARTNERID} “X-Region” : Moscow | Yerevan | ST. Petersburg “X-Language” : RU | AM | EN “WebSessionID” : f02fe5d6-c6ae-4b2e-9b4d-687534e11b01 “Currency” :RUB | AMD | USD Root: API.dexarmarket.ru General Information Check if server is available Get Marketplaces Set Marketplaces Get Item Delete Item New Item New Callback New Question Get random Items Get items in category Get searched items Get Categories Delete Category New Category Create new websession Check websession status Delete websession status Add to cart Create New QR code for cart checkout Check QR code item structure category structure Check if server is available Client needs to periodically check if the server is available by sending “ping” to the client. On error corresponding message must be shown. Protocol: https Type: GET Path: /ping Request Parameters: { } Response (Error): { "message": "pong", "status": "Wrong Header" } Response (OK): { "message": "pong", "status": "Correct Header" } ________________ Get Marketplaces Get Available Marketplaces Protocol: https Type: GET Path: /marketplaces Request Parameters: { } Response !=200(Error): { "error": "wrong header" } Response =200(OK): { [{“brand” : “dexar”, “api”:”dexar.market”, “bot”:”dexarmarket_bot”, “languagies”:[“”am,”ru”,”en”], “regions”:[“Mosocw - Russia”, ”St Petersburg - Russia”, ”Yerevan - Armenia”] “currency”:[“RUB, ”AMD”, ”USD”] “icon”:”./dexar.market.png”}, {“brand” : “store”, “api”:”dexarmarket.store”, “bot”:”dexarstore_bot”, “languagies”:[“”am,”ru”,”en”], “regions”:[“Mosocw - Russia”,”St Petersburg - Russia”,”Yerevan - Armenia”] “currency”:[“”RUB,”AMD”,”USD”] “icon”:”./dexarmarket.store.png”}, {“brand” : “Novo”, “api”:”novo.market”, “bot”:”novomarket_bot”, “languagies”:[“”am,”ru”,”en”], “regions”:[“Mosocw - Russia”, ”St Petersburg - Russia”,”Yerevan - Armenia”] “currency”:[“”RUB,”AMD”,”USD”] “icon”:”./novo.market.png”}] } ________________ Set Marketplaces Get Available Marketplaces Protocol: https Type: PUT Path: /marketplaces Request Parameters: { [{“brand” : “dexar”, “api”:”dexar.market”, “languagies”:[“”am,”ru”,”en”], “regions”:[“Mosocw - Russia”,”St Petersburg - Russia”,”Yerevan - Armenia”] “currency”:[“”RUB,”AMD”,”USD”] “icon”:”./dexar.market.png”}, {“brand” : “store”, “api”:”dexarmarket.store”, “languagies”:[“”am,”ru”,”en”], “regions”:[“Mosocw - Russia”,”St Petersburg - Russia”,”Yerevan - Armenia”] “currency”:[“”RUB,”AMD”,”USD”] “icon”:”./dexarmarket.store.png”}, {“brand” : “Novo”, “api”:”novo.market”, “languagies”:[“”am,”ru”,”en”], “regions”:[“Mosocw - Russia”, ”St Petersburg - Russia”,”Yerevan - Armenia”] “currency”:[“”RUB,”AMD”,”USD”] “icon”:”./novo.market.png”}] } Response !=200(Error): { "error": "wrong header" } Response =200(OK): { “status”:”Marketplace updated” } ________________ Get Item Get Item by ID Protocol: https Type: GET Path: /items/:itemID Request Parameters: { } Response !=200(Error): { "error": "wrong header" } Response =200(OK): { “itemID”:... } ________________ Delete Item Delete the item Protocol: https Type: Delete Path: /items/:itemID Request Parameters: { } Response !=200(Error): { "error": "wrong header" } Response =200(OK): { “status”:”Item was deleted” } ________________ New Item Create new Item Protocol: https Type: POST Path: /items/:itemID Request Parameters: { “itemID”:... } Response !=200(Error): { "error": "wrong header" } Response =200(OK): { “itemID”:... } ________________ Update Item Update the item Protocol: https Type: PUT Path: /items/:itemID Request Parameters: { “itemID”:... } Response !=200(Error): { "error": "wrong header" } Response =200(OK): { “status”:”Item updated” } ________________ New Callback Update the item Protocol: https Type: POST Path: /items/:itemID/callback Request Parameters: { "rating": 5, "comment": "Отличный товар!", "sessionID": “ f02fe5d6-c6ae-4b2e-9b4d-687534e11b01” "timestamp": "2026-02-28T12:00:00Z" } Response !=200(Error): { "error": "wrong item" } Response =200(OK): { “status”:”Callback added” } ________________ New Question Update the item Protocol: https Type: POST Path: /items/:itemID/questiion Request Parameters: { "question": "some question!", "sessionID": “ f02fe5d6-c6ae-4b2e-9b4d-687534e11b01” "timestamp": "2026-02-28T12:00:00Z" } Response !=200(Error): { "error": "wrong item" } Response =200(OK): { “status”:”Questiion added” } ________________ Get random Items Get given number of items from random categorues Protocol: https Type: GET Path: /items/randomitems?count=15 // 20 is the default Request Parameters: { } Response !=200(Error): { "error": "wrong header" } Response =200(OK): { [“itemID”:...] } ________________ Get items in category Get all items in category and in all subcategories inside the category Protocol: https Type: GET Path: /category/:categoryID?count=30, skip=60 // default skip=0, default count=20 Request Parameters: { } Response !=200(Error): { "error": "wrong header" } Response =200(OK): { [“itemID”:...] } ________________ Get searched items Get all items in category and in all subcategories inside the category Protocol: https Type: GET Path: /searchitems Parameters: { search (string) — query text categoryIDs (string) — e.g., 1,2,5 (includes all subcategories) minPrice / maxPrice (float) — price range tag (string) — e.g., sale sort (string) — relevance (default), price_asc, price_desc, popular, rating skip / count — default 0 / 20 } Examples: * ?search=iphone&sort=popular * ?categoryIDs=1,5&minPrice=100&maxPrice=500 * ?tag=new&sort=price_asc&count=10 Request Parameters: { } Response !=200(Error): { "error": "wrong header" } Response =200(OK): { "total": 12, "skip": 0, "count": 12, "isGlobal": false, "items": [ { "itemID": 101, "name": "..." } ] } ________________ Get Categories Get all available categories Protocol: https Type: GET Path: /category Request Parameters: { } Response !=200(Error): { "error": "wrong header" } Response =200(OK): { “categoryID”:... } ________________ Delete Category Delete EMPTY category, no items and no subcategories must present Protocol: https Type: Delete Path: /category/:categoryID Request Parameters: { } Response !=200(Error): { "error": "wrong header" } Response =200(OK): { “status”:”Category was deleted” } ________________ New Category Create new category Protocol: https Type: POST Path: /category/ Request Parameters: { “CategoryID”:... } Response !=200(Error): { "error": "wrong header" } Response =200(OK): { “CategoryID”:... } ________________ Update Category Update existing category Protocol: https Type: PUT Path: /category/:categoryID Request Parameters: { “itemID”:... } Response !=200(Error): { "error": "wrong header" } Response =200(OK): { “status”:”Category was updated” } ________________ Create new websession Creates a new websession for qr generation. By timeout a new websession must be requested, after the user shows some activity (click on qr). Protocol: https Type POST Path /websession Request Parameters: { } Response (OK): { "sessionId": “1AF3781BF6B94604B771AEA1D44FA63A”, "userId" : "", "expires" : "sessionId", "userSessionId": "", "status": false } ________________ Check websession status Check if the user is already logged in. a new websession for qr generation. By timeout a new websession must be requested, after the user shows some activity (click on qr). Protocol: https Type GET Path /websession/:webSessionID Request Parameters: { } Response (OK): { "sessionId": “1AF3781BF6B94604B771AEA1D44FA63A”, "userId" : "kHaAe9roaC2uq63AKGE/8+Ti/t/iFro68QhEZ1dRGLo", "expires" : "sessionId", "userSessionId": "8A94EFEFD003426A9B456C48CAC99BE6", "x-Region" : "Moscow", "x-Language" : "RU", "currency" : "RUB", "Status": true, "cart": [ { "itemID": 12, "quantity": 1, “colour”:”black”, “size”:”42”,"priice":230.50 }, { "itemID": 13, "quantity": 2, “colour”:”dark”, “size”:”L”,"priice":250.50 }, { "itemID": 14, "quantity": 3, “colour”:”blue”, “size”:”50”,"priice":290.50 }, ] } ________________ Delete websession status Delete the session to log out from the system. Protocol: https Type DELETE Path /websession/:webSessionID Request Parameters: { } Response (OK): { “status”:”User logged out” } ________________ Add to cart Add a all item to users (session) cart Protocol: https Type Post Path /websession/:webSessionID Request Parameters: { [ { "itemID": 12, "quantity": 1, “colour”:”black”, “size”:”42”,"priice":230.50 }, { "itemID": 13, "quantity": 2, “colour”:”dark”, “size”:”L”,"priice":250.50 }, { "itemID": 14, "quantity": 3, “colour”:”blue”, “size”:”50”,"priice":290.50 }, ] } Response (OK): { "sessionId": “1AF3781BF6B94604B771AEA1D44FA63A”, "userId" : "kHaAe9roaC2uq63AKGE/8+Ti/t/iFro68QhEZ1dRGLo", "expires" : "sessionId", "userSessionId": "8A94EFEFD003426A9B456C48CAC99BE6", "Status": true, "cart": [ { "itemID": 12, "quantity": 1, “colour”:”black”, “size”:”42”,"priice":230.50 }, { "itemID": 13, "quantity": 2, “colour”:”dark”, “size”:”L”,"priice":250.50 }, { "itemID": 14, "quantity": 3, “colour”:”blue”, “size”:”50”,"priice":290.50 }, ] } ________________ Create New QR code for cart checkout Create New QR for payment via SBP Protocol: https Type POST Path /websession/:webSessionID/qr Request Parameters: { } Response !=200(Error): { "error": "wrong key" } Response =200(OK): { "qrId": "BD10002CI1V3JP1T8QR8TIQ8K35RBVQB", "qrStatus": "NEW", "qrExpirationDate": "2025-11-20T10:10:44Z", "Payload": "https://qr.nspk.ru/BD10002CI1V3JP1T8QR8TIQ8K35RBVQB?type=02&bank=100000000007&sum=1000&cur=RUB&crc=8ACC", "qrUrl": "https://e-commerce.raiffeisen.ru/api/sbp/v1/qr/BD10002CI1V3JP1T8QR8TIQ8K35RBVQB/image" } ________________ Check QR code Check QR status Protocol: https Type GET Path /websession/:webSessionID/:qrID Request Parameters: { } Response !=200(Error): { "error": "Error from the bank " } Response =200(OK): { "additionalInfo": "", "paymentPurpose": "", "amount": 10, "code": "SUCCESS", "createDate": "2025-11-20T13:17:20.453884+03:00", "currency": "RUB", "order": "102_540", "paymentStatus": "NO_INFO", //check for SUCCESS "qrId": "BD1000263VS7G81D8JCP5FHFTFEH38MT", "transactionDate": "", "transactionId": 0, "qrExpirationDate": "2025-11-20T13:32:20+03:00" } ## 8. Авторизация (вход через Telegram) Авторизация **через Telegram** с **cookie-сессиями** (HttpOnly, Secure, SameSite=None). Все auth-эндпоинты должны поддерживать CORS с `credentials: true`. ### Процесс авторизации ``` 1. Пользователь нажимает «Оформить заказ» → не авторизован → показывается диалог входа 2. Нажимает «Войти через Telegram» → открывается https://t.me/{bot}?start=auth_{callback} 3. Пользователь запускает бота в Telegram 4. Бот отправляет данные пользователя → бэкенд /auth/telegram/callback 5. Бэкенд создаёт сессию → устанавливает Set-Cookie 6. Фронтенд опрашивает GET /auth/session каждые 3 секунды 7. Сессия обнаружена → диалог закрывается → оформление заказа продолжается ``` --- ### `GET /auth/session` — Проверить текущую сессию **Запрос:** Только cookie (сессионная cookie, установленная бэкендом). **Ответ `200`** (авторизован): ```json { "sessionId": "sess_abc123", "telegramUserId": 123456789, "username": "john_doe", "displayName": "John Doe", "active": true, "expiresAt": "2026-03-01T12:00:00Z" } ``` **Ответ `200`** (сессия истекла): ```json { "sessionId": "sess_abc123", "telegramUserId": 123456789, "username": "john_doe", "displayName": "John Doe", "active": false, "expiresAt": "2026-02-27T12:00:00Z" } ``` **Ответ `401`** (нет сессии): ```json { "error": "No active session" } ``` **Объект AuthSession:** | Поле | Тип | Обязат. | Описание | |------------------|---------|---------|-------------------------------------------| | `sessionId` | string | да | Уникальный ID сессии | | `telegramUserId` | number | да | ID пользователя в Telegram | | `username` | string? | нет | @username в Telegram (может быть null) | | `displayName` | string | да | Отображаемое имя (имя + фамилия) | | `active` | boolean | да | Действительна ли сессия | | `expiresAt` | string | да | Дата истечения в формате ISO 8601 | --- ### `GET /auth/telegram/callback` — Callback авторизации Telegram-бота Вызывается Telegram-ботом после авторизации пользователя. **Тело запроса (от бота):** ```json { "id": 123456789, "first_name": "John", "last_name": "Doe", "username": "john_doe", "photo_url": "https://t.me/i/userpic/...", "auth_date": 1709100000, "hash": "abc123def456..." } ``` Бот должен: 1. Слушать команду `/start auth_{callbackUrl}` 2. Извлечь callback URL 3. Отправить данные пользователя (`id`, `first_name`, `username` и т.д.) на этот callback URL 4. Callback URL: `{apiUrl}/auth/telegram/callback` --- ## Полный справочник эндпоинтов ### Новые эндпоинты | Метод | Путь | Описание | Авторизация | |--------|---------------------------|---------------------------------|-------------| | `GET` | `/regions` | Список доступных регионов | Нет | | `GET` | `/auth/session` | Проверка текущей сессии | Cookie | | `GET` | `/auth/telegram/callback` | Callback авторизации через бота | Нет (бот) | | `POST` | `/auth/logout` | Завершение сессии | Cookie | ________________ item structure CategoryID uint64 `json:"categoryID" binding:"required"` ItemID uint64 `json:"itemID" binding:"required"` Name string `json:"name" binding:"required"` Description string `json:"description"` Discount float32 `json:"discount" ` Rating float32 `json:"rating" binding:"required"` Visible bool `json:"rating"` Priority uint64 `json:"priority"` Tags []string `json:"tags"` Badges []string `json:"badges"` Details []itemdetail `json:"itemdetails"` Colour string `json:"colour" binding:"required"` Size string `json:"size" binding:"required"` Price float32 `json:"price" binding:"required"` Currency string `json:"currency" binding:"required"` Remaining uint64 `json:"remaining" binding:"required"` Names []itemname `json:"names"` Language string `json:"language"` Value string `json:"value"` Descriptions []itemdescription `json:"descriptions" ` Language string `json:"language"` Value string `json:"value"` Attributes []attribute `json:"attributes" binding:"required"` Key string `json:"key"` Value string `json:"value"` Photos []photo `json:"photos"` Type string `json:"type" binding:"required"` //video || photo URL string `json:"url" binding:"required"` Questions []question `json:"questions"` Question string `json:"question" ` Answer string `json:"answer" ` Like uint64 `json:"like" ` Dislike uint64 `json:"dislike" ` Visits uint64 `json:"visits"` Callbacks []callback `json:"callbacks" binding:"required"` Rating float32 `json:"rating,omitempty"` Content string `json:"content,omitempty"` Userid string `json:"userID"` Answer string `json:"answer"` Timestamp string `json:"timestamp"` PartnerID []string `json:"partnerID" binding:"required"` category structure CategoryID uint64 `json:"categoryID" binding:"required"` ParentID uint64 `json:"parentID" binding:"required"` Name string `json:"name" binding:"required"` Visible bool `json:"visible" ` Priority uint64 `json:"priority" ` Icon string `json:"icon"` WideIcon string `json:"wideicon"` ItemsCount uint64 CategoriesCount uint64 Names []itemname `json:"names"` Language string `json:"language"` Value string `json:"value"`