← chatnova.mn EnglishМонгол

ChatNova API ба Webhook

Хөгжүүлэгчийн баримт · Хувилбар 2026-10-14 · Base URL https://api.chatnova.mn/v1

Товчхондоо: Бот Messenger, Instagram-аас захиалга авмагц ChatNova таны серверийн хаяг руу JSON илгээнэ (webhook). Таны систем REST API-аар захиалгыг уншиж, «баталгаажсан / хүргэлтэд гарсан / хүргэгдсэн» төлөв тавихад харилцагчид Messenger-ээр мэдэгдэл автоматаар очно. Бараа, үлдэгдлийг ч API-аар шинэчилнэ.

1. Эхлэх — 3 алхам

  1. Портал → Холболт · API → «Түлхүүр үүсгэх». Түлхүүр cn_live_… нэг л удаа харагдана — хуулж аваарай. Бизнес, Про багцад багтдаг.
  2. Мөн хуудаснаас Webhook нэмэх: таны серверийн https:// хаяг. Нууц түлхүүр whsec_… нэг удаа харагдана.
  3. «Тест» дарж ping үйл явдал авна. Дараа нь жинхэнэ захиалга бүр order.created-оор ирнэ.

Хялбар хувилбар хэрэгтэй юу? Google Sheets толь (Бараа · захиалга → Тохиргоо) захиалга бүрийг хүснэгтэд бичдэг — кодгүй. Zapier, Make, n8n-д webhook хаягаа «Catch hook» болгон ашиглаж болно.

2. Нэвтрэлт

Бүх REST хүсэлтэд толгой: Authorization: Bearer cn_live_… (эсвэл X-Api-Key). Түлхүүр нэг байгууллагад хамаарна — зөвхөн тэр байгууллагын захиалга, бараа харагдана. Түлхүүр алдагдвал порталаас цуцлаад шинээр үүсгэнэ.

curl https://api.chatnova.mn/v1/me \
  -H "Authorization: Bearer cn_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Хязгаар: нэг түлхүүрд минутад 120 хүсэлт (429 + Retry-After: 60). Түлхүүрийг хөтөч, мобайл апп дотор хэзээ ч тавихгүй — зөвхөн сервер талд.

3. Webhook — ChatNova → таны сервер

Үйл явдалХэзээ
order.createdБот захиалга (эсвэл цаг захиалгын хүсэлт) бүртгэмэгц
order.updatedТөлөв, төлбөр (QPay орсон), тэмдэглэл, мөшгөлт, гадаад дугаар солигдох бүрд — data.changes-д юу өөрчлөгдсөн нь
order.assignedЗахиалга жолооч эсвэл хүргэлтийн компанид оноогдох үед (data.order.courier_id; компани бол data.partner_id)
pingПорталын «Тест» товч — жишээ захиалгатай

Хүсэлт: POST, Content-Type: application/json, 10 секундын дотор 2xx хариу хүлээнэ. Хариуны биеийг уншихгүй. Redirect дагахгүй. Зөвхөн https://, нийтийн домэйн.

POST /webhooks/chatnova HTTP/1.1
Host: shop.mn
Content-Type: application/json
User-Agent: ChatNova-Webhooks/1.0
X-ChatNova-Event: order.created
X-ChatNova-Event-Id: evt_3f9c2a7d1b6e4a8f0c21e4d2
X-ChatNova-Delivery: 5b2c…            (илгээлт бүрийн id)
X-ChatNova-Attempt: 1
X-ChatNova-Signature: t=1760434212,v1=9b1e…64 hex…

{
  "id": "evt_3f9c2a7d1b6e4a8f0c21e4d2",
  "type": "order.created",
  "api_version": "2026-10-14",
  "created_at": "2026-10-14T09:30:12.418Z",
  "tenant_id": "af9be6a7-b582-4406-98a5-68478a4d4e35",
  "data": {
    "order": {
      "id": "7c1d9e3a-2b4f-4c8d-9e0f-1a2b3c4d5e6f",
      "number": "CN-000124",
      "status": "new",
      "kind": "order",
      "source": "ai",
      "created_at": "2026-10-14T09:30:12.001Z",
      "updated_at": "2026-10-14T09:30:12.001Z",
      "currency": "MNT",
      "total_mnt": 97800,
      "paid_mnt": 0,
      "payment_mode": "bank_after",
      "items": [
        { "id": "c0ff…", "name": "Витамин D3 5000", "qty": 2, "price_mnt": 45000, "total_mnt": 90000 },
        { "id": null, "name": "Хүргэлт", "qty": 1, "price_mnt": 7800, "total_mnt": 7800 }
      ],
      "customer": { "name": "Болд", "phone": "99112233" },
      "delivery": { "address": null, "district": "Хан-Уул", "khoroo": "11", "building": "Хотхон 5-р байр", "entrance": "2 орц 45 тоот", "note": null },
      "booking": null,
      "fields": { "phone": "99112233", "name": "Болд", "district": "Хан-Уул", "khoroo": "11", "building": "Хотхон 5-р байр", "entrance": "2 орц 45 тоот" },
      "note": null,
      "external_ref": null,
      "tracking": null,
      "courier_id": null,
      "shipped_at": null,
      "delivered_at": null,
      "channel": { "page_id": "104322281612245", "conversation_id": "9e2b…" }
    },
    "actor": { "kind": "bot" }
  }
}

order.updated дээр нэмэлт: "changes": { "status": { "from": "new", "to": "confirmed" }, "paid_mnt": { "from": 0, "to": 97800 } }. actor.kind: bot · portal (эзэн порталаас) · api (API түлхүүрээр — actor.key_id хамт; өөрийн хийсэн өөрчлөлтийг алгасахад) · payment (QPay) · staff · courier (жолоочийн хуудас) · partner (хүргэлтийн компани — actor.partner_id) · auto (шинэ захиалгыг автоматаар оноох).

Дахин оролдлого, давхардал

4. Гарын үсэг шалгах

X-ChatNova-Signature: t=<unix секунд>,v1=<hex>. v1 = HMAC-SHA256(secret, t + "." + хүсэлтийн бие). Биеийг яг ирсэн байт-аар (JSON-оо дахин угсрахгүй — re-serialize хийхгүй) ашиглана. t нь 5 минутаас хуучин бол татгалзана. Шалгалтгүй хүлээн авч болохгүй — хаяг нийтэд ил, гарын үсэг л ChatNova-гийнх гэж батална.

Node.js (Express)

const crypto = require('crypto');
function verify(secret, header, rawBody) {
  const m = /t=(\d+),v1=([0-9a-f]{64})/.exec(header || '');
  if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
  const want = crypto.createHmac('sha256', secret).update(m[1] + '.' + rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(want, 'hex'), Buffer.from(m[2], 'hex'));
}
app.post('/webhooks/chatnova', express.raw({ type: 'application/json' }), (req, res) => {
  if (!verify(process.env.CHATNOVA_WEBHOOK_SECRET, req.get('X-ChatNova-Signature'), req.body.toString('utf8'))) return res.sendStatus(401);
  const event = JSON.parse(req.body);
  if (seen(event.id)) return res.sendStatus(200);          // давхардал
  if (event.type === 'order.created') createOrderInMySystem(event.data.order);
  if (event.type === 'order.updated') updateStatus(event.data.order, event.data.changes);
  res.sendStatus(200);                                        // 10 секундын дотор; урт ажлыг дараалалд
});

PHP

$raw = file_get_contents('php://input');
$hdr = $_SERVER['HTTP_X_CHATNOVA_SIGNATURE'] ?? '';
if (!preg_match('/t=(\d+),v1=([0-9a-f]{64})/', $hdr, $m) || abs(time() - (int)$m[1]) > 300) { http_response_code(401); exit; }
$want = hash_hmac('sha256', $m[1] . '.' . $raw, $secret);
if (!hash_equals($want, $m[2])) { http_response_code(401); exit; }
$event = json_decode($raw, true);
// $event['type'], $event['data']['order']['number'], ['customer']['phone'], ['items'] …
http_response_code(200);

Python

import hmac, hashlib, time, re
def verify(secret: str, header: str, raw_body: bytes) -> bool:
    m = re.search(r't=(\d+),v1=([0-9a-f]{64})', header or '')
    if not m or abs(time.time() - int(m.group(1))) > 300:
        return False
    want = hmac.new(secret.encode(), m.group(1).encode() + b'.' + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(want, m.group(2))

4б. Хүргэлтийн компанид — Partner API (нэг удаа холбогдоод бүх дэлгүүр)

Та хүргэлтийн компани бол дэлгүүр бүртэй тусдаа түлхүүр солилцох шаардлагагүй. chatnova.mn/partners-д бүртгүүлнэ → ChatNova батална (1 ажлын өдөр) → самбарын линк имэйлээр ирнэ → дэлгүүрүүд порталаасаа танай компанийг нэг товчоор холбоно. Танд оноогдсон захиалга л харагдана.

ЗамЮу хийх
GET/v1/partner/meКомпани, холбогдсон дэлгүүрийн тоо
GET/v1/partner/shopsХолбогдсон дэлгүүрүүд (id, name, phone, active, pickup)
GET/v1/partner/ordersТанд оноогдсон захиалга, бүх дэлгүүрээс. Query: status (анхдагч бүгд; таслалаар олон), since, shop_id, limit, offset. Захиалга бүрд shop: {id, name, phone, pickup} нэмэгдэнэ — pickup {address, phone, note} = барааг авах газар (дэлгүүр порталаасаа тохируулна; хоосон бол null). Webhook-ийн data.shop ч ижил
GET/v1/partner/orders/{id}Нэг захиалга (uuid)
PATCH/v1/partner/orders/{id}status: shipped | delivered (цуцлалтыг дэлгүүр хийнэ), tracking, note, external_ref, notify. Харилцагчид Messenger мэдэгдэл автоматаар
curl "https://api.chatnova.mn/v1/partner/orders?status=new,confirmed,shipped" -H "Authorization: Bearer $PARTNER_KEY"
curl -X PATCH https://api.chatnova.mn/v1/partner/orders/7c1d9e3a-… -H "Authorization: Bearer $PARTNER_KEY" -H "Content-Type: application/json" \
  -d '{"status":"delivered","note":"Хаалган дээр хүлээлгэн өгсөн"}'

5. REST API — таны систем → ChatNova

ЗамЮу хийх
GET/v1/meТүлхүүр, байгууллага, багц, идэвхтэй webhook тоо
GET/v1/ordersЗахиалгын жагсаалт, сүүлийн эхэнд. Query: status (таслалаар олон), since, until (created_at), updated_since, limit (≤200, анхдагч 50), offset. Хариу { data, has_more, next_offset }
GET/v1/orders/{id}id нь uuid эсвэл дугаар CN-000124 (124 ч болно)
PATCH/v1/orders/{id}Бие: status (confirmed | shipped | delivered | cancelled), note, external_ref (таны системийн дугаар), tracking {carrier, number, url, eta, note}, notify (анхдагч true — харилцагчид Messenger мэдэгдэл). Хариу { data, notified }
GET/v1/productsБараа (идэвхтэй л; include_disabled=1 бүгд). Query: q, category, limit (≤500), offset
PATCH/v1/products/{id}id = uuid эсвэл external_id (таны SKU). Бие: stock (0 = дууссан, null = хязгааргүй), price_mnt, list_price_mnt, external_id, enabled
GET/v1/webhooksБүртгэлтэй webhook хаягууд (нууцгүй)
# Шинэ захиалгуудыг татах
curl "https://api.chatnova.mn/v1/orders?status=new,confirmed&since=2026-10-14T00:00:00Z&limit=100" \
  -H "Authorization: Bearer $CHATNOVA_KEY"

# Хүргэлтэд гарсан гэж тэмдэглэх — харилцагч «хүргэлтэд гарлаа 🚚 Ээлж · дугаар EE123» мэдэгдэл авна
curl -X PATCH https://api.chatnova.mn/v1/orders/CN-000124 \
  -H "Authorization: Bearer $CHATNOVA_KEY" -H "Content-Type: application/json" \
  -d '{"status":"shipped","external_ref":"DLV-7781","tracking":{"carrier":"Ээлж хүргэлт","number":"EE123","url":"https://eelj.mn/t/EE123"}}'

# Бараа дууссан — бот үүнийг зарахаа больж, хүлээлгийн жагсаалтад бүртгэнэ
curl -X PATCH https://api.chatnova.mn/v1/products/SKU-1 \
  -H "Authorization: Bearer $CHATNOVA_KEY" -H "Content-Type: application/json" -d '{"stock":0}'

Бүх хариунд X-ChatNova-Version толгой. Цаг ISO 8601 (UTC). Мөнгө бүхэл төгрөг.

6. Захиалгын объект

ТалбарУтга
id, numberuuid; хүнд харагдах дугаар CN-000124 (байгууллага бүрд дараалсан)
statusnew | confirmed | shipped | delivered | cancelled, цаг захиалгад arrived | no_show ч бий (7-р хэсэг)
kindorder (бараа) · booking (цаг захиалга, хүсэлт — booking талбартай)
sourceai (бот) · slots · manual (ажилтан гараар) · n8n
total_mnt, paid_mnt, payment_modeНийт, төлсөн дүн (QPay орвол), төлбөрийн горим (none | prepay | full | bank_after …)
items[]id (ChatNova барааны uuid — /v1/products-оор external_id/SKU-тай тааруулна), name, qty, price_mnt, total_mnt
customername, phone (8 орон, +976-гүй; цифр биш бол бичсэн чигээрээ)
deliveryaddress, district, khoroo, building, entrance, note — бот асуусан талбаруудаас; байхгүй нь null
booking{ service, date, time } эсвэл null
fieldsБотын асуусан бүх талбар түүхийгээр (phone, name, district … + таны урсгалын өөрийн талбарууд)
note, external_ref, trackingЭзний/таны тэмдэглэл; таны системийн дугаар; {carrier, number, url, eta, note, updated_at}
courier_id, shipped_at, delivered_atОноосон жолооч/компанийн courier id; хүргэлтэд анх гарсан, хүргэгдсэн цаг (ISO). Оноогдоогүй бол null
channelpage_id (Facebook Page), conversation_id

7. Төлөв ба харилцагчийн мэдэгдэл

ТөлөвУтгаХарилцагчид (Messenger)
newБот бүртгэсэн—
confirmedБаталгаажсан (QPay орсон, эзэн/таны систем батласан)«… захиалга БАТАЛГААЖЛАА ✅ Нийт …₮»
shippedХүргэлтэд гарсан«… ХҮРГЭЛТЭД ГАРЛАА 🚚 Хүргэлт: {carrier} · дугаар {number}»
deliveredХүргэгдсэн«… ХҮРГЭГДЛЭЭ 🚚✅» + 1–5 үнэлгээний товч
cancelledЦуцлагдсан (үлдэгдэл буцна)«… цуцлагдлаа»
arrived, no_showЦаг захиалга: ирсэн / ирээгүй (зөвхөн портал)—

Мэдэгдэл Meta-гийн 24 цагийн цонх нээлттэй бол шууд, хаалттай бол зөвшөөрөгдсөн загвараар явна; Instagram-д цонх хаалттай бол чимээгүй. Байгууллага «харилцагчид SMS» асаасан бол SMS ч очно. Мэдэгдэл хэрэггүй бол "notify": false. Ижил төлөвийг дахин тавьвал мэдэгдэл давтагдахгүй.

8. Барааны объект

id, external_id (таны SKU — PATCH-аар тавина, дараа нь үүгээр хандана), name, emoji, price_mnt, list_price_mnt (хямдралын өмнөх), stock (null хязгааргүй · 0 дууссан), category, featured, enabled, image_url, aliases[], description, pre_order, updated_at. Үлдэгдэл 0 болоход бот тэр барааг зарахгүй, нэр үнийг хэлж хүлээлгийн жагсаалтад бүртгэнэ; дахин ирэхэд мэдэгдэнэ.

9. Алдаа, хязгаар

HTTPerrorШалтгаан
400bad_requestТалбар буруу — message-д тайлбар, allowed-д зөвшөөрөгдөх утга
401unauthorized, invalid_keyТолгой алга / түлхүүр буруу, цуцлагдсан
402plan_requiredБагцад API алга — Бизнес/Про руу ахиулна
404not_foundЗахиалга, бараа, зам олдсонгүй (өөр байгууллагынх ч 404)
409conflictexternal_id давхардсан
429rate_limitedМинутад 120 хүсэлт — Retry-After
503not_readyСервер талын шинэчлэл хүлээгдэж байна — дахин оролдоно

Хязгаар: байгууллага бүрд 5 идэвхтэй түлхүүр, 3 webhook хаяг. Webhook биеийн хэмжээ захиалгаас хамаарна (ихэвчлэн <10 KB). Илгээлтийн лог 30 хоног хадгалагдана.

Аюулгүй байдал

Хувилбар, дэмжлэг

Талбар нэмэгдэж болно (хуучин нэр, утга өөрчлөгдөхгүй). Том өөрчлөлт шинэ api_version-той ирж, хуучин нь үргэлжилнэ. Асуулт: hello@chatnova.mn · 7607 3333.

© 2026 ChatNova · Үйлчилгээний нөхцөл · Нууцлал

ChatNova API & Webhooks

Developer documentation · Version 2026-10-14 · Base URL https://api.chatnova.mn/v1

In short: the moment the bot takes an order on Messenger or Instagram, ChatNova POSTs JSON to your server (webhook). Your system reads orders over REST and sets “confirmed / shipped / delivered”; the customer is told on Messenger automatically. Products and stock can be updated over the API as well.

1. Start — three steps

  1. Portal → Integrations · API → “Create key”. The key cn_live_… is shown once — copy it. Included in Business and Pro.
  2. On the same page Add webhook: your server’s https:// URL. The signing secret whsec_… is shown once.
  3. Press “Test” to receive a ping. From then on every real order arrives as order.created.

Need something simpler? The Google Sheets mirror (Products · orders → Settings) writes every order to a spreadsheet, no code. Zapier, Make or n8n can use the webhook URL as a “catch hook”.

2. Authentication

Every REST request carries Authorization: Bearer cn_live_… (or X-Api-Key). A key belongs to one business — only its orders and products are visible. If a key leaks, revoke it in the portal and create a new one.

curl https://api.chatnova.mn/v1/me \
  -H "Authorization: Bearer cn_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Limit: 120 requests per minute per key (429 with Retry-After: 60). Never ship the key inside a browser or mobile app — server side only.

3. Webhooks — ChatNova → your server

EventWhen
order.createdAs soon as the bot records an order (or a booking request)
order.updatedWhenever status, payment (QPay received), note, tracking or external reference changes — data.changes says what
order.assignedWhen an order is handed to a courier or a delivery partner (data.order.courier_id; for partners data.partner_id)
pingThe portal “Test” button, with a sample order

Request: POST, Content-Type: application/json; a 2xx answer is expected within 10 seconds. The response body is ignored. Redirects are not followed. Only https:// on a public domain.

POST /webhooks/chatnova HTTP/1.1
Host: shop.mn
Content-Type: application/json
User-Agent: ChatNova-Webhooks/1.0
X-ChatNova-Event: order.created
X-ChatNova-Event-Id: evt_3f9c2a7d1b6e4a8f0c21e4d2
X-ChatNova-Delivery: 5b2c…            (id of this delivery attempt series)
X-ChatNova-Attempt: 1
X-ChatNova-Signature: t=1760434212,v1=9b1e…64 hex…

{
  "id": "evt_3f9c2a7d1b6e4a8f0c21e4d2",
  "type": "order.created",
  "api_version": "2026-10-14",
  "created_at": "2026-10-14T09:30:12.418Z",
  "tenant_id": "af9be6a7-b582-4406-98a5-68478a4d4e35",
  "data": {
    "order": {
      "id": "7c1d9e3a-2b4f-4c8d-9e0f-1a2b3c4d5e6f",
      "number": "CN-000124",
      "status": "new",
      "kind": "order",
      "source": "ai",
      "created_at": "2026-10-14T09:30:12.001Z",
      "updated_at": "2026-10-14T09:30:12.001Z",
      "currency": "MNT",
      "total_mnt": 97800,
      "paid_mnt": 0,
      "payment_mode": "bank_after",
      "items": [
        { "id": "c0ff…", "name": "Vitamin D3 5000", "qty": 2, "price_mnt": 45000, "total_mnt": 90000 },
        { "id": null, "name": "Delivery", "qty": 1, "price_mnt": 7800, "total_mnt": 7800 }
      ],
      "customer": { "name": "Bold", "phone": "99112233" },
      "delivery": { "address": null, "district": "Khan-Uul", "khoroo": "11", "building": "Block 5", "entrance": "Entrance 2, apt 45", "note": null },
      "booking": null,
      "fields": { "phone": "99112233", "name": "Bold", "district": "Khan-Uul", "khoroo": "11", "building": "Block 5", "entrance": "Entrance 2, apt 45" },
      "note": null,
      "external_ref": null,
      "tracking": null,
      "courier_id": null,
      "shipped_at": null,
      "delivered_at": null,
      "channel": { "page_id": "104322281612245", "conversation_id": "9e2b…" }
    },
    "actor": { "kind": "bot" }
  }
}

order.updated adds "changes": { "status": { "from": "new", "to": "confirmed" }, "paid_mnt": { "from": 0, "to": 97800 } }. actor.kind: bot · portal (owner in the portal) · api (an API key, with actor.key_id — skip your own changes) · payment (QPay) · staff · courier (courier page) · partner (delivery company — actor.partner_id) · auto (auto-assign of new orders).

Retries and duplicates

4. Verifying the signature

X-ChatNova-Signature: t=<unix seconds>,v1=<hex> where v1 = HMAC-SHA256(secret, t + "." + raw request body). Use the body exactly as received (do not re-serialise the JSON). Reject if t is older than 5 minutes. Never accept unverified requests — the URL is public; only the signature proves it came from ChatNova.

Node.js (Express)

const crypto = require('crypto');
function verify(secret, header, rawBody) {
  const m = /t=(\d+),v1=([0-9a-f]{64})/.exec(header || '');
  if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
  const want = crypto.createHmac('sha256', secret).update(m[1] + '.' + rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(want, 'hex'), Buffer.from(m[2], 'hex'));
}
app.post('/webhooks/chatnova', express.raw({ type: 'application/json' }), (req, res) => {
  if (!verify(process.env.CHATNOVA_WEBHOOK_SECRET, req.get('X-ChatNova-Signature'), req.body.toString('utf8'))) return res.sendStatus(401);
  const event = JSON.parse(req.body);
  if (seen(event.id)) return res.sendStatus(200);          // duplicate
  if (event.type === 'order.created') createOrderInMySystem(event.data.order);
  if (event.type === 'order.updated') updateStatus(event.data.order, event.data.changes);
  res.sendStatus(200);                                        // within 10 s; queue long work
});

PHP

$raw = file_get_contents('php://input');
$hdr = $_SERVER['HTTP_X_CHATNOVA_SIGNATURE'] ?? '';
if (!preg_match('/t=(\d+),v1=([0-9a-f]{64})/', $hdr, $m) || abs(time() - (int)$m[1]) > 300) { http_response_code(401); exit; }
$want = hash_hmac('sha256', $m[1] . '.' . $raw, $secret);
if (!hash_equals($want, $m[2])) { http_response_code(401); exit; }
$event = json_decode($raw, true);
// $event['type'], $event['data']['order']['number'], ['customer']['phone'], ['items'] …
http_response_code(200);

Python

import hmac, hashlib, time, re
def verify(secret: str, header: str, raw_body: bytes) -> bool:
    m = re.search(r't=(\d+),v1=([0-9a-f]{64})', header or '')
    if not m or abs(time.time() - int(m.group(1))) > 300:
        return False
    want = hmac.new(secret.encode(), m.group(1).encode() + b'.' + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(want, m.group(2))

4b. For delivery companies — Partner API (connect once, serve every shop)

A delivery company does not need a separate key per shop. Register at chatnova.mn/partners → ChatNova approves (one business day) → the dashboard link arrives by email → shops connect your company from their portal with one click. You see only orders assigned to you.

RouteWhat it does
GET/v1/partner/meCompany and number of connected shops
GET/v1/partner/shopsConnected shops (id, name, phone, active, pickup)
GET/v1/partner/ordersOrders assigned to you, across shops. Query: status (default all; comma list), since, shop_id, limit, offset. Each order carries shop: {id, name, phone, pickup} — pickup {address, phone, note} is where to collect the parcel (set by the shop in its portal; null if unset). Webhook data.shop is the same object
GET/v1/partner/orders/{id}One order (uuid)
PATCH/v1/partner/orders/{id}status: shipped | delivered (cancellation is the shop’s), tracking, note, external_ref, notify. The customer is told on Messenger automatically
curl "https://api.chatnova.mn/v1/partner/orders?status=new,confirmed,shipped" -H "Authorization: Bearer $PARTNER_KEY"
curl -X PATCH https://api.chatnova.mn/v1/partner/orders/7c1d9e3a-… -H "Authorization: Bearer $PARTNER_KEY" -H "Content-Type: application/json" \
  -d '{"status":"delivered","note":"Handed over at the door"}'

5. REST API — your system → ChatNova

RouteWhat it does
GET/v1/meKey, business, plan, number of active webhooks
GET/v1/ordersOrders, newest first. Query: status (comma list), since, until (created_at), updated_since, limit (≤200, default 50), offset. Returns { data, has_more, next_offset }
GET/v1/orders/{id}id is the uuid or the number CN-000124 (124 works too)
PATCH/v1/orders/{id}Body: status (confirmed | shipped | delivered | cancelled), note, external_ref (your own id), tracking {carrier, number, url, eta, note}, notify (default true — Messenger message to the customer). Returns { data, notified }
GET/v1/productsProducts (enabled only; include_disabled=1 for all). Query: q, category, limit (≤500), offset
PATCH/v1/products/{id}id = uuid or external_id (your SKU). Body: stock (0 = sold out, null = unlimited), price_mnt, list_price_mnt, external_id, enabled
GET/v1/webhooksRegistered webhook endpoints (without secrets)
# Pull new orders
curl "https://api.chatnova.mn/v1/orders?status=new,confirmed&since=2026-10-14T00:00:00Z&limit=100" \
  -H "Authorization: Bearer $CHATNOVA_KEY"

# Mark as shipped — the customer gets “out for delivery 🚚 Eelj · EE123” on Messenger
curl -X PATCH https://api.chatnova.mn/v1/orders/CN-000124 \
  -H "Authorization: Bearer $CHATNOVA_KEY" -H "Content-Type: application/json" \
  -d '{"status":"shipped","external_ref":"DLV-7781","tracking":{"carrier":"Eelj delivery","number":"EE123","url":"https://eelj.mn/t/EE123"}}'

# Sold out — the bot stops selling it and offers a waitlist instead
curl -X PATCH https://api.chatnova.mn/v1/products/SKU-1 \
  -H "Authorization: Bearer $CHATNOVA_KEY" -H "Content-Type: application/json" -d '{"stock":0}'

Every response carries X-ChatNova-Version. Times are ISO 8601 (UTC). Money is whole tugrik (MNT).

6. The order object

FieldMeaning
id, numberuuid; human-readable number CN-000124 (sequential per business)
statusnew | confirmed | shipped | delivered | cancelled; bookings also arrived | no_show (section 7)
kindorder (goods) · booking (appointment or request — has a booking field)
sourceai (bot) · slots · manual (staff) · n8n
total_mnt, paid_mnt, payment_modeTotal, amount paid (QPay), payment mode (none | prepay | full | bank_after …)
items[]id (ChatNova product uuid — map to your SKU via /v1/products external_id), name, qty, price_mnt, total_mnt
customername, phone (8 digits, no +976; left as typed if not numeric)
deliveryaddress, district, khoroo, building, entrance, note — from the fields the bot asked; missing ones are null
booking{ service, date, time } or null
fieldsEvery field the bot collected, raw (phone, name, district … plus your flow’s custom fields)
note, external_ref, trackingOwner/your note; your system’s id; {carrier, number, url, eta, note, updated_at}
courier_id, shipped_at, delivered_atAssigned courier / partner courier id; first shipped and delivered timestamps (ISO). null when unassigned
channelpage_id (Facebook Page), conversation_id

7. Statuses and customer notifications

StatusMeaningCustomer (Messenger)
newRecorded by the bot—
confirmedConfirmed (QPay received, owner or your system confirmed)“… order CONFIRMED ✅ Total …₮”
shippedOut for delivery“… OUT FOR DELIVERY 🚚 Carrier: {carrier} · no. {number}”
deliveredDelivered“… DELIVERED 🚚✅” + 1–5 rating buttons
cancelledCancelled (stock is returned)“… was cancelled”
arrived, no_showBookings: showed up / did not (portal only)—

Messages go out immediately while Meta’s 24-hour window is open, otherwise through an approved template; on Instagram with a closed window nothing is sent. If the business enabled “customer SMS”, an SMS goes too. Pass "notify": false to stay silent. Setting the same status again does not repeat the message.

8. The product object

id, external_id (your SKU — set it via PATCH, then address products by it), name, emoji, price_mnt, list_price_mnt (before discount), stock (null unlimited · 0 sold out), category, featured, enabled, image_url, aliases[], description, pre_order, updated_at. At stock 0 the bot stops selling the item, still quotes name and price, and offers a waitlist; customers are told when it is back.

9. Errors and limits

HTTPerrorWhy
400bad_requestInvalid field — see message, allowed values in allowed
401unauthorized, invalid_keyMissing header / wrong or revoked key
402plan_requiredAPI not in the plan — upgrade to Business/Pro
404not_foundOrder, product or route not found (another business’s records are 404 too)
409conflictDuplicate external_id
429rate_limited120 requests per minute — see Retry-After
503not_readyServer-side update pending — retry later

Limits: 5 active keys and 3 webhook endpoints per business. Webhook bodies are usually under 10 KB. The delivery log is kept for 30 days.

Security

Versioning and support

Fields may be added (existing names and meanings do not change). Breaking changes arrive under a new api_version while the old one keeps working. Questions: hello@chatnova.mn · +976 7607 3333.

© 2026 ChatNova · Terms · Privacy