API Kết nối ISale

Tài liệu dành cho lập trình viên tích hợp ERP, website, POS và hệ thống bên thứ ba với iSale.

Cập nhật: tháng 6/2026 /ext/v1

Tổng quan

External API cho phép hệ thống bên thứ ba (ERP, website, POS, chatbot…) đồng bộ dữ liệu với iSale qua API key, không dùng OAuth/Bearer nội bộ.

  • Namespace: /ext/v1/* — tách khỏi API app (/data/*, Bearer token).
  • Mỗi mã kết nối gắn với một shop (tenantUserId); quyền theo danh sách permission gán trên mã.
  • Phase 1: quyền truy cập dữ liệu ở mức full shop (chưa áp OWD/row-scope CRM như staff).
[Hệ thống ngoài] --Authorization: Apikey--> [https://api2.isale.online/ext/v1/...]
                                                                     ↓
                                                                     Services / DB (lọc theo shop)

Bắt đầu nhanh

  1. Đăng nhập iSale với tài khoản chủ shop hoặc nhân viên có quyền quản trị đầy đủ.
  2. Mở màn hình Kết nối phần mềm khác (#/external-api trong app).
  3. Nhấn Tạo mã mớipublicKey chỉ hiển thị một lần; lưu ngay nơi an toàn.
  4. Chọn quyền tối thiểu cần thiết (accordion theo nhóm CRM, Bán hàng, Danh mục…).
  5. Gọi thử API với header Authorization: Apikey <publicKey>.
Lưu ý: Không gửi mã kết nối qua email/chat công khai. Thu hồi ngay nếu nghi ngờ lộ.

Xác thực

Header bắt buộc
Authorization: Apikey <publicKey>

Mọi request tới /ext/v1/* phải có header trên. Key và client phải ở trạng thái active (status=1).

HMAC (tùy chọn — khuyến nghị production cho request ghi)

Áp dụng khi gửi ít nhất một header X-Timestamp, X-Nonce hoặc X-Signature trên POST/PUT/PATCH/DELETE:

  • X-Timestamp — unix ms, lệch tối đa ±5 phút
  • X-Nonce — UUID, không được trùng trong cửa sổ
  • X-Signature — HMAC-SHA256 hex (khóa hiện dùng publicKey)
Mã lỗi thường gặp
HTTPcodeÝ nghĩa
401unauthorizedThiếu/sai Apikey hoặc key đã thu hồi
403forbiddenThiếu permission (ví dụ crm.leads.read)
429rate_limit_exceededVượt giới hạn tần suất

Response có thể kèm header X-Request-Id để tra audit log phía shop.

Quy ước chung

Base URL: https://api2.isale.online (cấu hình production; không có dấu / cuối).

Versioning: prefix /ext/v1. Breaking change sẽ tăng version (/ext/v2).

Định dạng lỗi
{
  "error": {
    "code": "invalid_request",
    "message": "Missing required field: fullName",
    "details": { "field": "fullName" }
  }
}
Phân trang
  • limit — mặc định 50, tối đa 200 (áp dụng trên nhiều endpoint list).
  • Một số API hỗ trợ id để lọc/lấy từ bản ghi cụ thể (xem từng module).
Ví dụ kiểm tra kết nối
curl -s -H "Authorization: Apikey YOUR_PUBLIC_KEY" \
  "https://api2.isale.online/ext/v1/crm/leads?limit=5"

Phân quyền

Gán quyền trên app Kết nối phần mềm khác. Mỗi endpoint yêu cầu permission tương ứng; thiếu quyền trả 403.

CRM
crm.leads.readcrm.leads.write crm.contacts.readcrm.contacts.write crm.tasks.readcrm.tasks.write crm.deals.readcrm.deals.write crm.pipelines.read crm.flows.readcrm.flows.write
Bán hàng
sales.orders.readsales.orders.write
Danh mục
catalog.products.readcatalog.products.write catalog.attributes.read
Lịch
calendar.readcalendar.write
Shop
shop.stores.readshop.stores.write shop.staff.readshop.settings.read
Tài chính
finance.debts.readfinance.debts.write finance.quotes.readfinance.quotes.write finance.money-accounts.readfinance.money-accounts.write finance.trades.readfinance.trades.write finance.received-notes.readfinance.received-notes.write finance.transfer-notes.readfinance.transfer-notes.write
Dữ liệu / bảng
data.tables.readdata.tables.write data.notes.readdata.notes.write data.business-types.readdata.business-types.write data.sales-lines.readdata.sales-lines.write data.custom-tables.readdata.custom-tables.write
Bảng generic /ext/v1/data/tables/{table}/records dùng permission theo từng bảng hoặc umbrella data.tables.read / data.tables.write.

CRM

Leads
MethodPathPermissionQuery / body
GET/ext/v1/crm/leadscrm.leads.readq, ownerStaffId, status, limit, id
GET/ext/v1/crm/leads/{id}crm.leads.read
POST/ext/v1/crm/leadscrm.leads.writeJSON: fullName (bắt buộc), mobile, email, …
curl -X POST "https://api2.isale.online/ext/v1/crm/leads" \
  -H "Authorization: Apikey YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fullName":"Lead từ website","mobile":"0901234567","source":"website"}'
Contacts
MethodPathPermission
GET/ext/v1/crm/contactscrm.contacts.read
GET/ext/v1/crm/contacts/{id}crm.contacts.read
POST/ext/v1/crm/contactscrm.contacts.write
PATCH/ext/v1/crm/contacts/{id}crm.contacts.write

Query list: limit, q (tìm theo tên, SĐT, email, mã).

Flows (automation)
MethodPathPermission
GET/ext/v1/crm/flowscrm.flows.read
GET/ext/v1/crm/flows/{id}crm.flows.read
POST/ext/v1/crm/flowscrm.flows.write
GET/ext/v1/crm/flows/{flowId}/runscrm.flows.read
GET/ext/v1/crm/flow-runs/{runId}crm.flows.read

Bán hàng

MethodPathPermissionGhi chú
GET/ext/v1/sales/orderssales.orders.readdateFrom, dateTo, contactId, staffId, storeId, status
GET/ext/v1/sales/orders/{id}sales.orders.read
POST/ext/v1/sales/orderssales.orders.writeTạo đơn
PATCH/ext/v1/sales/orders/{id}sales.orders.writeCập nhật đơn
curl -s -H "Authorization: Apikey YOUR_KEY" \
  "https://api2.isale.online/ext/v1/sales/orders?dateFrom=2026-06-01&dateTo=2026-06-30"

Danh mục sản phẩm

MethodPathPermissionQuery
GET/ext/v1/catalog/productscatalog.products.readstoreId, categoryId, isMaterial
GET/ext/v1/catalog/products/{id}catalog.products.readstoreId
POST/ext/v1/catalog/productscatalog.products.write
PATCH/ext/v1/catalog/products/{id}catalog.products.write

Lịch

MethodPathPermissionQuery
GET/ext/v1/calendar/eventscalendar.readstaffId, contactId, id, limit
GET/ext/v1/calendar/events/{id}calendar.read
POST/ext/v1/calendar/eventscalendar.write
PATCH/ext/v1/calendar/events/{id}calendar.write

Bảng dữ liệu (generic)

API đọc/ghi các bảng standard_table trong whitelist. Không thay thế API chuyên biệt cho contact, product, order, calendar, lead, flow.

MethodPathPermission
GET/ext/v1/data/tablesQuyền đọc ít nhất một bảng / data.tables.read
GET/ext/v1/data/tables/{table}/recordsĐọc theo bảng
GET/ext/v1/data/tables/{table}/records/{id}Đọc theo bảng
POST/ext/v1/data/tables/{table}/recordsGhi theo bảng (nếu bảng cho phép write)

Query: limit, id. Mọi bản ghi lọc theo userId của shop.

Bảng đọc được (whitelist)

store, staff, note, debt, quote, trade, trade_category, sales_line, business_type, money_account, transfer_note, received_note, level_config, shift_log, product_attribute, product_type, product_attribute_quantity, custom_table, custom_table_data, crm_task, crm_deal, crm_deal_item, crm_deal_stage, crm_pipeline

Bảng ghi được

store, note, debt, quote, trade, sales_line, business_type, money_account, transfer_note, received_note, custom_table_data

Các bảng contact, product, order, calendar, crm_lead, crm_flow… dùng API chuyên biệt ở các mục trên.

Rate limit

Áp dụng cho mọi request /ext/*. Vượt ngưỡng trả 429 kèm Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining.

Giới hạnMặc định (production)Cửa sổ
Theo IP120 request60 giây
Theo API key300 request60 giây
Ghi (POST/PUT/PATCH/DELETE) / key60 request60 giây
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "...",
    "retryAfterSeconds": 42
  }
}

Đếm theo từng instance API (memory). Môi trường dev thường tắt rate limit.

Bảo mật & vận hành

  • Chỉ cấp quyền tối thiểu cho từng đối tác tích hợp.
  • Thu hồi mã ngay khi nghi ngờ lộ — trên app Kết nối phần mềm khác.
  • Không log publicKey trong log ứng dụng phía bạn.
  • Production: khuyến nghị bật HMAC cho mọi request ghi.
  • Dữ liệu luôn scoped theo shop của mã — không truy cập chéo tenant.

Chủ shop xem audit log qua API nội bộ (Bearer): GET /external-integration/audit-logs?limit= — không dùng External API key.

OpenAPI / Swagger

Trang này là tài liệu tham khảo nhanh. Nếu cần schema chi tiết (model, field), mở Swagger document ext-v1:

Mở Swagger External API

https://api2.isale.online/swagger/index.html?urls.primaryName=ISale%20External%20API%20ext-v1