API ສາທາລະນະ ຂອງ Happy ERP
ໃຫ້ລະບົບອື່ນ — ນັກບັນຊີ · ເວັບຂອງຮ້ານ · Google Sheet · n8n · ແອັບທີ່ເຈົ້າຂຽນເອງ — ດຶງອໍເດີ/ສິນຄ້າ/ສະຕັອກ ແລະ ສ້າງອໍເດີ ໄດ້ໂດຍກົງ ພ້ອມ webhook ທີ່ຍິງອອກທັນທີເມື່ອມີອໍເດີໃໝ່.
1 · ເອົາກະແຈ API
ເປີດແອັບ → ຕັ້ງຄ່າ → API & webhook → + ກະແຈອ່ານ ຫຼື + ກະແຈຂຽນ. ໃຊ້ໄດ້ສະເພາະ ເຈົ້າຂອງຮ້ານ.
- ກະແຈອ່ານ — ດຶງໄດ້ຢ່າງດຽວ. ໃຊ້ກັບ Google Sheet ຫຼື ລາຍງານ.
- ກະແຈຂຽນ — ດຶງ + ສ້າງອໍເດີໄດ້. ໃຫ້ສະເພາະລະບົບທີ່ຕ້ອງສ້າງອໍເດີແທ້ໆ.
2 · ເອີ້ນຄັ້ງທຳອິດ
curl -H "Authorization: Bearer hpk_ກະແຈຂອງເຈົ້າ" \
https://app.happyerp.la/api/v1/ping
{"ok":true,"api":"1.0","shop":{"id":12,"name":"ຮ້ານຂອງຂ້ອຍ"},"scope":"read"}
ໃສ່ກະແຈໃນ header ໄດ້ 2 ແບບ: Authorization: Bearer hpk_… (ມາດຕະຖານ)
ຫຼື X-Api-Key: hpk_… (ງ່າຍກວ່າສຳລັບ Google Sheet / n8n).
3 · ເສັ້ນທາງທີ່ມີ
ຖານ: https://app.happyerp.la/api/v1
GET /orders
ລາຍການອໍເດີ. ພາຣາມິເຕີ: status (wait · confirm · pack · ship · done · cancel · rto) ·
since (ເວລາເປັນ ມິນລິວິນາທີ) · limit (ສູງສຸດ 200) · cursor · sort=asc.
curl -H "X-Api-Key: $KEY" \
"https://app.happyerp.la/api/v1/orders?status=ship&limit=50"
{"orders":[{"id":1042,"created":1756000000000,"status":"ship","pay":"cod",
"customer":{"name":"ນາງ ດາວ","phone":"020 5555 1234"},
"address":{"village":"ບ້ານ ໂພນ","district":"ຈັນທະບູລີ","province":"ວຽງຈັນ","districtId":"101","provinceId":"1"},
"items":[{"code":"A1","variant":"M","qty":2,"price":79000}],
"goods":158000,"ship":20000,"discount":0,"total":178000,
"courier":"ANS","trackNo":"ANS12345","track":"transit"}],
"next":"50","total":312}
ອໍເດີຕົວແທນ (10/9/2026): ອໍເດີທີ່ຂາຍຜ່ານ ຕົວແທນກາງ ມີ "pay":"agent" ແລະ ຊ່ອງ
"agent":{"code":"KAI","mode":"prepay","paid":true,"total":60000} — items[].price/goods/total ຄືລາຄາທີ່ຮ້ານຂາຍໃຫ້ຕົວແທນ (ລາຍຮັບຈິງ)
ບໍ່ແມ່ນລາຄາທີ່ລູກຄ້າປາຍທາງເຫັນ. ລະບົບບັນຊີນອກ ຄິດລາຍຮັບຈາກ total ໄດ້ຕາມປົກກະຕິ. ບໍ່ມີຊ່ອງນີ້ = ອໍເດີປົກກະຕິ (ບໍ່ breaking).
ແບ່ງໜ້າ: ເອົາຄ່າ next ໄປໃສ່ cursor ຂອງຄັ້ງຕໍ່ໄປ. ຫວ່າງ = ໝົດແລ້ວ.
next ຄື ເລກອໍເດີສຸດທ້າຍຂອງໜ້ານັ້ນ ບໍ່ແມ່ນຕຳແໜ່ງ — ມີອໍເດີໃໝ່ເຂົ້າມາລະຫວ່າງດຶງ ກໍ່ບໍ່ມີແຖວໃດຫຼຸດ.
?updatedSince=<ms> ໃຫ້ອໍເດີທີ່ຖືກແຕະຫຼັງເວລານັ້ນ
(ລວມການປ່ຽນສະຖານະຂອງອໍເດີເກົ່າ). ທຸກອໍເດີມີຊ່ອງ updated ບອກເວລາແຕະຫຼ້າສຸດ —
?since= ອີງ created ຢ່າງດຽວ ຈຶ່ງບໍ່ເຫັນການປ່ຽນສະຖານະ.GET /orders/{id}
ອໍເດີດຽວ + note · staff · history (ທຸກຂັ້ນຕອນທີ່ເກີດຂຶ້ນ ພ້ອມເວລາ ແລະ ຄົນເຮັດ).
GET /products
ສິນຄ້າ + ຈຳນວນຄົງເຫຼືອຈິງ. ພາຣາມິເຕີ: q (ຄົ້ນຫາ) · limit · cursor.
{"products":[{"code":"A1","name":"ເສື້ອຢືດ","price":79000,"cat":"ເສື້ອ",
"barcode":"8851001","variants":["M","L"],"off":false,
"stock":{"M":5,"L":2},"stockTotal":7}],
"next":"","total":38}
ສິນຄ້າທີ່ບໍ່ມີໄຊສ໌ ໃຊ້ກະແຈ "-" (ເຊັ່ນ {"-":20}) · ຮຽງຕາມລະຫັດສິນຄ້າ ແລະ next ຄືລະຫັດສຸດທ້າຍ.
stock ມາຈາກ ບັນຊີການເຄື່ອນໄຫວສາງຢູ່ເຊີບເວີ ບໍ່ແມ່ນຕົວເລກທີ່ເຄື່ອງໃດເຄື່ອງໜຶ່ງສົ່ງມາ —
ຈຶ່ງກົງກັບທີ່ແອັບເຫັນສະເໝີ. ຕົ້ນທຶນ ແລະ ກຳໄລ ບໍ່ຖືກສົ່ງອອກທາງ API.GET /stock
{"levels":[{"code":"A1","variant":"M","onHand":5,"reserved":2,"available":3}]}
reserved = ຖືກຈອງໄວ້ໃນອໍເດີທີ່ຍັງບໍ່ໄດ້ສົ່ງ. ຂາຍໄດ້ຈິງ = available.
POST /orders (ຕ້ອງເປັນກະແຈຂຽນ)
curl -X POST -H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
https://app.happyerp.la/api/v1/orders -d '{
"customer": {"name":"ນາງ ດາວ","phone":"020 5555 1234"},
"address": {"village":"ບ້ານ ໂພນ","districtId":"101","provinceId":"1"},
"items": [{"code":"A1","variant":"M","qty":2}],
"pay": "cod",
"note": "ສົ່ງຕອນແລງ"
}'
{"ok":true,"id":1043,"total":178000,"ship":20000,"pay":"cod","status":"wait"}
Idempotency-Key: <ຂໍ້ຄວາມບໍ່ຊ້ຳ>
(ເຊັ່ນ ເລກອໍເດີຂອງລະບົບເຈົ້າ). ຍິງຊ້ຳດ້ວຍກະແຈເກົ່າພາຍໃນ 1 ມື້ = ໄດ້ຄຳຕອບອັນເກົ່າພ້ອມ
"duplicate":true ບໍ່ແມ່ນສ້າງອໍເດີໃໝ່. ຄຳຮ້ອງທີ່ຕົກ (ຂອງບໍ່ພໍ) ບໍ່ຖືກຈື່ໄວ້ —
ເຕີມຂອງແລ້ວຍິງກະແຈເກົ່າຄືນໄດ້ເລີຍ. ສອງຄຳຮ້ອງກະແຈດຽວກັນພ້ອມກັນ = ອັນທີສອງໄດ້ 409 in_progress.- ອໍເດີເຂົ້າເປັນ “ລໍຢືນຢັນ” ແລະ ຈອງສະຕັອກທັນທີ — ຄືກັນກັບໜ້າສັ່ງຊື້ຂອງຮ້ານ.
- ຂອງບໍ່ພໍ =
409 insufficientພ້ອມລາຍການທີ່ຂາດ — ບໍ່ເຄີຍຂາຍເກີນ. - ຄ່າສົ່ງຄິດຢູ່ເຊີບເວີ ຈາກ
districtId/provinceId— ສົ່ງລາຄາມາເອງບໍ່ໄດ້. - ສິນຄ້າທີ່ມີໄຊສ໌ ຕ້ອງໃສ່
variantບໍ່ດັ່ງນັ້ນ400 need_variant.
4 · webhook — ໃຫ້ເຮົາຍິງໄປຫາເຈົ້າ
ຕັ້ງຄ່າ → API & webhook → + ເພີ່ມລິ້ງ. ເມື່ອມີເຫດການ ເຮົາຈະ POST JSON ໄປຫາລິ້ງນັ້ນ.
| ເຫດການ | ເກີດເມື່ອໃດ |
|---|---|
order.created | ມີອໍເດີໃໝ່ (ຈາກແອັບ · ໜ້າສັ່ງຊື້ · ແຊັດ · API) |
order.status | ສະຖານະປ່ຽນ — ມີ was ບອກສະຖານະເກົ່າ |
order.deleted | ອໍເດີຖືກລຶບ — ໃຫ້ລຶບອອກຈາກລະບົບປາຍທາງນຳ |
ping | ເຈົ້າກົດ “ຍິງທົດລອງ” ໃນໜ້າຕັ້ງຄ່າ |
POST https://ລິ້ງຂອງເຈົ້າ
X-Happy-Event: order.created
X-Happy-Timestamp: 1756100000
X-Happy-Signature: sha256=91f0…
{"event":"order.created","at":1756100000123,"shop":12,"api":"1.0",
"data":{"id":1043,"status":"wait","total":178000, …}}
ກວດລາຍເຊັນ (ສຳຄັນ)
ລາຍເຊັນ = HMAC-SHA256(ລະຫັດລັບ, "<timestamp>." + ເນື້ອໃນດິບ).
ຄິດຈາກ ເນື້ອໃນດິບ ກ່ອນແປງເປັນ object.
# Python
import hmac, hashlib
expect = "sha256=" + hmac.new(SECRET.encode(),
(ts + ".").encode() + raw_body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expect, sig): reject()
if abs(time.time() - int(ts)) > 300: reject() # ກັນເອົາຂອງເກົ່າມາຍິງຊ້ຳ
- ຕອບ 2xx ພາຍໃນ 8 ວິນາທີ. ບໍ່ຕອບ = ລອງໃໝ່ 3 ຄັ້ງ (ທັນທີ · 20 ວິ · 90 ວິ).
- ຕົກຕິດກັນ 20 ຄັ້ງ = ລິ້ງຖືກປິດເອງ ແລະ ສະແດງ “ປິດ” ໃນໜ້າຕັ້ງຄ່າ.
- ລິ້ງທີ່ຊີ້ໃສ່ວົງໃນ (127.0.0.1 · 10.x · 192.168.x · 169.254.x) ຮັບບໍ່ໄດ້.
- ອາດໄດ້ຮັບຊ້ຳ — ໃຫ້ຖືເອົາ
data.id+eventເປັນຕົວກັນຊ້ຳ. - ລະຫັດລາຍເຊັນເຮັດເສຍ ຫຼື ສົງໄສວ່າຮົ່ວ? ຕັ້ງຄ່າ → API & webhook → ລະຫັດໃໝ່ (ບໍ່ຕ້ອງລຶບລິ້ງ ຈຶ່ງບໍ່ເສຍປະຫວັດການສົ່ງ). ລະຫັດເກົ່າຢຸດໃຊ້ທັນທີ — ເອົາອັນໃໝ່ໄປໃສ່ປາຍທາງກ່ອນ.
5 · ຄວາມຜິດພາດ
| ລະຫັດ | error | ໝາຍຄວາມວ່າ |
|---|---|---|
| 401 | unauthorized | ບໍ່ມີກະແຈ · ກະແຈຜິດ · ຫຼື ຖືກຖອນແລ້ວ |
| 403 | read_only | ໃຊ້ກະແຈອ່ານ ໄປສ້າງອໍເດີ |
| 404 | not_found | ບໍ່ມີອໍເດີເລກນີ້ໃນຮ້ານຂອງກະແຈ |
| 400 | bad_items · need_variant · need_name_phone | ຂໍ້ມູນທີ່ສົ່ງມາບໍ່ຄົບ ຫຼື ຜິດຮູບແບບ |
| 409 | insufficient | ຂອງບໍ່ພໍ — ມີ short ບອກວ່າຂາດອັນໃດ |
| 429 | rate_limited | ເກີນ 120 ຄັ້ງ/ນາທີ/ກະແຈ — ລໍຕາມ header Retry-After |
| 409 | in_progress | ຄຳຮ້ອງ Idempotency-Key ດຽວກັນກຳລັງເຮັດຢູ່ |
ທຸກຄຳຕອບຜິດພາດເປັນຮູບແບບດຽວກັນ: {"error":"…","message":"…"}
6 · ກົດທີ່ຄວນຮູ້
- ຮ້ານໃຜຮ້ານມັນ — ກະແຈເຫັນໄດ້ສະເພາະຂໍ້ມູນຮ້ານຂອງຕົນເທົ່ານັ້ນ.
- 120 ຄັ້ງ/ນາທີ ຕໍ່ກະແຈ. ດຶງເປັນຮອບ ດີກວ່າຍິງຖີ່ — ຫຼື ໃຊ້ webhook ແທນການດຶງຊ້ຳ.
- ຮຸ່ນ — ຮູບຮ່າງໃນໜ້ານີ້ຄື
v1. ຖ້າຕ້ອງປ່ຽນແບບຫັກ ຈະເປັນ/v2ບໍ່ແມ່ນປ່ຽນອັນນີ້ງຽບໆ. ການ ເພີ່ມ ຊ່ອງໃໝ່ບໍ່ຖືວ່າຫັກ — ໂປຣແກຣມຂອງເຈົ້າຄວນຂ້າມຊ່ອງທີ່ບໍ່ຮູ້ຈັກ. - ຖອນກະແຈ ໄດ້ທຸກເວລາ — ມີຜົນທັນທີ.
ຄຳຖາມ ຫຼື ຢາກໃຫ້ເພີ່ມເສັ້ນທາງໃດ — ບອກໄດ້ຜ່ານ ຄູ່ມືນຳໃຊ້. ໜ້ານີ້ຄືສັນຍາທີ່ເຮົາຮັບຜິດຊອບ — ບໍ່ແມ່ນລາຍການສິ່ງທີ່ວາງແຜນຈະມີ.