Хөгжүүлэгчид · v1.0.0

OpenShop Open API

Дэлгүүрийн каталог, захиалга, төлбөрийн холбоос — REST /v1, API түлхүүр, гарын үсэгтэй webhook, Google/Meta формат барааны feed. Гэрээ = OpenAPI 3.1, CI-д хамгаалагдсан. Сүүлд шинэчилсэн: 2026-09-22.

Нэвтрэлт

Дэлгүүр тус бүрийн API түлхүүр

Мерчант консолын Тохиргоо → Интеграц табаас түлхүүр үүсгэнэ. Түлхүүр нэг л удаа харагдана; алдагдвал консолоос шууд хүчингүй болгоно.

GET https://{slug}.openshop.mn/api/v1/shop/orders?limit=20
Authorization: Bearer osk_live_<43 тэмдэгт>
  • Хост: https://{slug}.openshop.mn/api/v1/shop/* эсвэл https://api.openshop.mn/v1/shop/* (түлхүүр өөрөө дэлгүүрээ нэрлэдэг). Өөр дэлгүүрийн хост дээр 401 invalid_api_key.
  • Scope = консолын эрхийн slug, тусдаа нэршил байхгүй: product:read product:write product:delete order:read order:write. Эрх дутвал 403 insufficient_scope + required_scope.
  • Каталог унших (GET /products*, /categories*, /bundles/public/*) баPOST /checkout нь токенгүй нээлттэй; product:write түлхүүртэй бол ноорог ч харагдана.
  • cost_mnt ямар ч түлхүүрт хэзээ ч буцахгүй. Хүсэлт бүр дэлгүүрийн RLS дор ажиллана.
  • POST /shop/checkout-д сонголттой Idempotency-Key: 24 цаг ижил хариу (Idempotent-Replayed: true), өөр биетэй бол 422 idempotency_key_reuse.

Webhook

Гарын үсэгтэй, at-least-once

Консолоос HTTPS endpoint бүртгэж үйл явдлаа сонгоно. Бие нь PII-гүй нимгэн дугтуй — дэлгэрэнгүйг түлхүүрээрээ GET /shop/orders/{id}-ээс татна.

order.createdorder.paidorder.expiredorder.fulfilledorder.unfulfilledproduct.createdproduct.updatedproduct.deleted
POST https://your.app/openshop-webhook
X-OpenShop-Event-Id: <outbox event id — дедупц энэ дээр>
X-OpenShop-Delivery-Id: <оролдлого бүрд шинэ>
X-OpenShop-Event-Type: order.paid
X-OpenShop-Signature: t=1750000000,v1=06f35f44b88e…
User-Agent: OpenShop-Webhooks/1.0

{"id":"evt_1","type":"order.paid","created_at":"…","shop":{"slug":"demo"},
 "data":{"order_id":"…","status":"paid","total_mnt":50000,"discount_mnt":0,"paid_at":"…"}}
  • Гарын үсэг: v1 = HMAC-SHA256(secret, t + "." + rawBody), hex. Түүхий биеийг задлахаас ӨМНӨ шалга; t-г ±300 секундээр хязгаарла. Нууц солих 24 цагт толгойд хоёр v1 — аль нэг таарвал хүчинтэй. Тест вектор: secret s3cr3t, body {"id":"evt_1","type":"order.paid"}, t 1750000000 06f35f44b88eceb2f2df6696c68710a8265597b7ca7d225a71d588159757f0d9.
  • At-least-once, дараалалгүй. Нэг үйл явдал давхар ирж болно → X-OpenShop-Event-Id-ээр дедупц заавал; order.expired-ийн дараа order.paid ирж болно — эцсийн үнэн нь GET /shop/orders/{id}.
  • Хариу: 2xx-ыг шууд буцаа (10 секунд timeout, хариунаас 64KB л уншина). 5xx · 408 · 429 · timeout → дахин оролдоно: 1м · 5м · 30м · 2ц · 6ц · 12ц · 24ц (±20% jitter), нийт 8 оролдлого ≈ 45 цаг. Бусад 4xx → шууд dead; 410 Gone → endpoint автоматаар унтарна; дараалсан 50 алдаа → мөн унтарна.
  • Endpoint = https заавал, нийтийн хаяг (дотоод/loopback IP татгалзана), redirect дагахгүй.

Барааны feed

Google Merchant · Meta Commerce Manager

Дэлгүүр бүр өөрийн хост дээр токенгүй feed-тэй. Facebook Commerce Manager «Data feed → Scheduled», Google Merchant Center «Scheduled fetch»-д холбоосыг нь л өгнө.

GET https://{slug}.openshop.mn/api/v1/shop/feed.csv   → text/csv (UTF-8 BOM, RFC 4180)
GET https://{slug}.openshop.mn/api/v1/shop/feed.xml   → RSS 2.0 + xmlns:g (Google Merchant)
  • Мөр = идэвхтэй бараа бүр (Нээх-ээс нуусан ч орно — энэ мерчантын өөрийн каталог); ноорог хэзээ ч орохгүй. Нэг хувилбартай бараа = нэг мөр, id = барааны UUID (Facebook каталогийн retailer_id, Pixel-ийн content_ids-тэй ижил). 2+ хувилбар → хувилбар бүр мөр, id = хувилбарын UUID, item_group_id = барааны UUID.
  • Багана: id · item_group_id · title · description · availability · condition · price · sale_price · sale_price_effective_date · link · image_link · additional_image_link · brand · product_type · google_product_category. Үнэ "50000 MNT"; sale_price зөвхөн хямдрал идэвхтэй үед, storefront-той яг ижил тооцоо. Өртөг, үлдэгдлийн тоо хэзээ ч гарахгүй.
  • Кэш 5 минут (Cache-Control: public, max-age=300), ETag If-None-Match = 304. Зочны IP тус бүрд 30 хүсэлт/мин.

Rate limit

Хувин ба 429

ГадаргууХязгаарХувин
API түлхүүртэй унших хүсэлт600 / минтүлхүүр бүрд
API түлхүүртэй бичих хүсэлт120 / минтүлхүүр бүрд
POST /shop/checkout (токенгүй)30 / минзочны IP
GET /shop/feed.csv · feed.xml30 / минзочны IP
GET /shop/suggest120 / минзочны IP
POST /shop/orders/lookup10 / минзочны IP

Түлхүүртэй хүсэлт X-RateLimit-Limit / Remaining / Reset толгойтой; хэтэрвэл 429 rate_limited + Retry-After. Токенгүй хувин зочин тус бүрд — нэг интегратор бусдыг хаахгүй.

Алдааны дугтуй

{error, code} — текст биш, code-оор салаална

HTTP 409
{"error": "Нөөц хүрэлцэхгүй байна.", "code": "insufficient_stock", "remaining": 2}

error = хэрэглэгчид харуулах Монгол текст (өөрчлөгдөж болно). code = гэрээ: нэмэгдэнэ, нэр солигдохгүй. Танихгүй код гарвал HTTP статусынх нь ангиар нь ханд.

out_of_stockinsufficient_stockpayments_not_readypayable_closedrate_limitedunauthorizedinvalid_api_keyinsufficient_scopeapi_key_scope_invalidapi_key_limit_reachedwebhook_url_invalidwebhook_events_invalidwebhook_limit_reachednot_foundvalidation_erroridempotency_key_invalididempotency_in_progressidempotency_key_reuseendpoint_sunsetinvalid_signatureconnector_requiredconnector_not_linked

Хасах/эвдэх өөрчлөлт = Deprecation (RFC 9745) + Sunset (RFC 8594) толгой, дор хаяж 6 сарын мэдэгдэл, дараа нь 410 endpoint_sunset. Одоогоор deprecated route байхгүй.

Өөрчлөлтүүд

v1 дотор нэмэгдсэн зүйлс

  1. 2026-09-22

    Барааны feed (CSV · XML)

    • GET /shop/feed.csv, GET /shop/feed.xml — Google Merchant / Meta Commerce Manager формат, токенгүй.
    • Дэлгүүр, формат тус бүрд 5 минутын кэш, ETag / If-None-Match → 304, 30 хүсэлт/мин.
  2. 2026-09-16

    API түлхүүр, webhook, Idempotency-Key, машин уншдаг гэрээ

    • Authorization: Bearer osk_live_… — дэлгүүр тус бүрийн түлхүүр, scope = эрхийн slug (product:read/write/delete, order:read/write).
    • Webhook OUT: order.* · product.* үйл явдал, X-OpenShop-Signature (HMAC-SHA256), 8 оролдлого ≈ 45 цаг.
    • POST /shop/checkout дээр Idempotency-Key (24 цаг replay, идэвхтэй үед 409, өөр биетэй 422).
    • Deprecation / Sunset бодлого (RFC 9745 / 8594, ≥6 сар); OpenAPI 3.1 гэрээ CI-д spectral + oasdiff-ээр хамгаалагдсан.
  3. 2026-09-08

    Нийтийн дэлгүүрийн API — 5 засвар

    • Public хариунд cost_mnt орохоо болив.
    • Rate-limit хувин зочин тус бүрд (нэг дундын хувин биш).
    • GET /shop/checkout/{id} төлөгдсөн үед paid_at буцаана.
    • CORS: зөвхөн PUBLIC_API_CORS_ORIGINS-д нэрлэсэн origin, унших route-уудад л.
    • Алдааны дугтуйд машин уншдаг code (out_of_stock · insufficient_stock + remaining …).

API лавлагаа

OpenAPI 3.1 — бүх endpoint

Доорх лавлагаа openshop-v1.yaml-аас шууд рендэрлэгдэнэ — файл нь эх сурвалж, энэ хуудас түүний хураангуй.

API лавлагаа ачаалж байна…