API Đơn hàng
Tạo đơn hàng
| Method | POST |
|---|---|
| URL | /api/order/create-order |
Body request
{
"address_id": 2,
"consignee_name": "sarenda mcguire",
"consignee_phone": "",
"consignee_address": "6105 W Elmwood Dr",
"consignee_address_other": "",
"consignee_country": "US",
"consignee_city": "Wildomar",
"consignee_postal_code": "57718",
"consignee_state_code": "SD",
"order_number": "DEV123456789",
"product_name": "Metal",
"product_price": 5.5,
"length": 1.93,
"width": 108,
"height": 1.9,
"weight": 1.1,
"service_code": "EPK",
"service_add": "",
"money_collection": 0,
"order_code_upstream_partner": "partner_of_partner",
"package_option": "818",
"unit_type": "cm-g",
"label_sender": "WRIGLEYS Cool Air",
"mode": null
}
Giải thích
| No. | Field Name | Data Type | Description |
|---|---|---|---|
| 1 | address_id | Long | Mã kho hàng (3.1) |
| 2 | consignee_name | String | Họ tên người nhận |
| 3 | consignee_phone | String | Số điện thoại người nhận |
| 4 | consignee_address | String | Địa chỉ người nhận 1 |
| 5 | consignee_address_other | String | Địa chỉ người nhận 2 |
| 6 | consignee_country | String | Mã quốc gia (fix: US) |
| 7 | consignee_city | String | Tỉnh / thành phố (3.2) |
| 8 | consignee_postal_code | String | 5 chữ số (người dùng nhập) |
| 9 | consignee_state_code | String | State code (3.2) |
| 10 | order_number | String | Mã đơn hàng của đối tác |
| 11 | product_name | String | Nội dung hàng hóa |
| 12 | product_price | Decimal | Giá trị hàng hóa |
| 13 | length | Decimal | Chiều dài (cm) |
| 14 | width | Decimal | Chiều rộng (cm) |
| 15 | height | Decimal | Chiều cao (cm) |
| 16 | weight | Decimal | Trọng lượng (gram) |
| 17 | service_code | String | Dịch vụ chính (liên hệ) |
| 18 | service_add | String | Dịch vụ gia tăng |
| 19 | money_collection | Decimal | Số tiền thu hộ |
| 20 | order_code_upstream_partner | String | Mã đối tác của đối tác |
| 21 | package_option | String | Pin lithium: 818 (Marked), 820 (Unmarked). Với dịch vụ LBE6 dùng mã đầy đủ: 8181, 8182, 8201, 8202. Bỏ trống nếu không có PIN |
| 22 | unit_type | String | Đơn vị của các chiều và cân nặng. Mặc định không điền là cm-g (mm-g,cm-g,cm-kg,in-lb) |
| 23 | label_sender | String | Field này bổ sung tên đại lý người gửi, nếu không set thì lấy mặc định trong label_sender trong customer đã set |
| 24 | mode | String | Truyền "advanced" để dùng Advanced Mode (xem mục bên dưới). Bỏ trống hoặc null cho Simple Mode |
Validation Rules
service_code cần liên hệ để lấy danh sách dịch vụ khả dụng. Danh sách service phải tồn tại trong hệ thống BELL.
address_id
- Bắt buộc, kiểu số nguyên.
- Mỗi service chỉ chấp nhận một số address_id cụ thể (liên hệ để được cung cấp).
order_number
- Bắt buộc, tối đa 50 ký tự.
- Phải unique theo từng customer (không trùng mã đơn đã tạo trước đó).
- Với service
US_UPS_GROUNDvàUS_UNIUNI_D: chỉ cho phép ký tựa-z A-Z 0-9 _ ( ) - , # space.
consignee_name
- Bắt buộc, tối đa 100 ký tự.
- Với service
US_UPS_GROUND: phải bao gồm họ và tên đầy đủ (ít nhất 2 từ cách nhau bởi khoảng trắng).
consignee_phone
- Không bắt buộc.
- Nếu có, phải đúng 10 chữ số (ví dụ:
0123456789).
consignee_email
- Không bắt buộc.
- Nếu có, phải đúng format email, tối đa 50 ký tự.
consignee_country
- Bắt buộc, mã quốc gia 2 ký tự (ISO-2).
consignee_state_code
- Bắt buộc khi
consignee_country = US. - Không bắt buộc với các quốc gia khác.
- Tối đa 50 ký tự.
consignee_postal_code
- Bắt buộc, tối đa 20 ký tự.
- Format theo quốc gia:
- US: 5 chữ số hoặc 5+4 (ví dụ:
57718hoặc57718-1234). - GB/UK: format Royal Mail (ví dụ:
SW1A 1AA).
- US: 5 chữ số hoặc 5+4 (ví dụ:
- Với service
US_UNIUNIvàUS_UNIUNI_D: postal code phải nằm trong danh sách vùng phục vụ của UniUni.
consignee_address
- Bắt buộc, tối đa 200 ký tự.
consignee_address_other
- Không bắt buộc, tối đa 200 ký tự.
unit_type
- Không bắt buộc. Mặc định:
cm-g. - Giá trị cho phép:
mm-g,cm-g,cm-kg,in-lb.
length / width / height
- Bắt buộc, giá trị số > 0.
- Giới hạn tối đa: 150 cm (quy đổi theo unit_type).
weight
- Bắt buộc, giá trị số > 0.
product_name
- Không bắt buộc, tối đa 100 ký tự.
product_price
- Không bắt buộc, giá trị số ≥ 0.
service_add
- Không bắt buộc, tối đa 100 ký tự.
label_sender
- Không bắt buộc, tối đa 50 ký tự.
- Nếu không set, lấy mặc định từ cài đặt label_sender của customer.
package_option (Lithium Battery)
- Không bắt buộc.
- Chỉ được sử dụng với service:
EPK,LBE,LBE6. - Giá trị theo service:
| Service | Giá trị cho phép | Mô tả |
|---|---|---|
| EPK, LBE | 818, 820 | 818 = Marked, 820 = Unmarked |
| LBE6 | 8181, 8182, 8201, 8202 | Mã đầy đủ: 818x = Marked, 820x = Unmarked |
- Khi có
package_option, các kiện hàng (packages) phải thỏa mãn giới hạn:
| Service | Trọng lượng tối đa | Length + 2×Width + 2×Height |
|---|---|---|
| EPK | ≤ 11 lbs | < 108 inch |
| LBE | ≤ 11 lbs | < 108 inch |
| LBE6 | ≤ 11 lbs | < 108 inch |
Nếu hàng hoá có PIN package_option cần nhập mã phù hợp theo service.
và cần dán mark
https://express.bellvn.com/UN-3091.jpg hoặc
https://express.bellvn.com/UN-3481.jpg
Response
{
"error": false,
"ref": null,
"message": "Tạo đơn thành công",
"data": "DEV123456789",
"warnings": []
}
Giải thích
| STT | Tên trường | Kiểu dữ liệu | Mô tả |
|---|---|---|---|
| 1 | error | boolean | Trạng thái lỗi |
| 2 | ref | String | Mã tham chiếu giao dịch |
| 3 | message | String | Thông báo |
| 4 | data | String | Mã đơn hàng của BELL |
| 5 | warnings | Array | Danh sách cảnh báo khi hệ thống tự động chuyển ký tự sang ASCII (dịch vụ US_UNIUNI_D, US_UPS_GROUND, LBE6) |
Mỗi phần tử trong warnings:
| Field | Mô tả |
|---|---|
| field | Tên trường bị chuyển đổi |
| label | Tên hiển thị của trường |
| original | Giá trị gốc trước khi chuyển đổi |
| sanitized | Giá trị sau khi chuyển sang ASCII |
| message | Mô tả hành động tự động |
Tạo đơn hàng nâng cao (Advanced Mode)
Dành cho các dịch vụ quốc tế yêu cầu khai báo chi tiết hàng hóa và hỗ trợ nhiều kiện hàng (multi-package).
| Method | POST |
|---|---|
| URL | /api/order/create-order |
Các service sau bắt buộc phải sử dụng mode advanced:
UPS_WW_SAVER2,UPS_WW_SAVERUPS_WW_EXPEDITED2,UPS_WW_EXPEDITEDUPS_WW_EXPRESS2,UPS_WW_EXPRESSFEDEX_IPE2,FEDEX_IPE,FEDEX_IP2,FEDEX_IPFEDEX_IE2,FEDEX_IE,FEDEX_ICP2,FEDEX_ICPFEDEX_IP_SBP,FEDEX_IP_SBP2
Nếu sử dụng các service trên mà không truyền mode: "advanced" hoặc thiếu thông tin goods, hệ thống sẽ trả lỗi validation.
Với các dịch vụ US_UNIUNI_D, US_UPS_GROUND, LBE6: hệ thống tự động chuyển các ký tự tiếng Việt có dấu sang ASCII (ví dụ: á → a, đ → d) cho các trường tên/địa chỉ. Response sẽ kèm mảng warnings liệt kê các trường đã được tự động chuyển đổi.
Body request
{
"mode": "advanced",
"address_id": 0,
"service_code": "UPS_WW_EXPRESS",
"order_number": "PARTNER-ADV-001",
"order_code_upstream_partner": "UPSTREAM-001",
"consignee_name": "John Doe",
"consignee_company": "ACME Corp",
"consignee_phone": "2125550001",
"consignee_email": "john@example.com",
"consignee_country": "US",
"consignee_state_code": "NY",
"consignee_city": "New York",
"consignee_postal_code": "10001",
"consignee_address": "123 Main Street",
"consignee_address_other": "Suite 100",
"unit_type": "cm-g",
"package_option": null,
"label_sender": "MY STORE",
"service_add": "",
"packages": [
{
"weight": 1000,
"length": 30,
"width": 20,
"height": 15,
"goods": [
{
"name_en": "Electronic Device",
"name_vi": "Thiết bị điện tử",
"brand": "BrandName",
"packaging_type": "Box",
"origin": "CN",
"price": 150.00,
"quantity": 2,
"unit": "pcs",
"hs_code": "8471.30",
"material": "Plastic"
}
]
},
{
"weight": 500,
"length": 25,
"width": 18,
"height": 10,
"goods": [
{
"name_en": "Accessories",
"name_vi": "Phụ kiện",
"brand": null,
"packaging_type": null,
"origin": "VN",
"price": 25.50,
"quantity": 5,
"unit": "pcs",
"hs_code": null,
"material": null
}
]
}
],
"extra_fields": {
"trade_terms": "DDP",
"tax_type": "IOSS",
"tax_number": "IOSS-123456789",
"signature_required": true
}
}
So sánh Simple vs Advanced
| Đặc điểm | Simple (mặc định) | Advanced |
|---|---|---|
| Số kiện hàng | 1 kiện (truyền thẳng length, width, height, weight) | Nhiều kiện (mảng packages) |
| Khai báo hàng hóa | product_name + product_price | Mảng goods chi tiết (tên, xuất xứ, HS code, ...) |
| Dịch vụ hỗ trợ | Tất cả dịch vụ nội địa | Bắt buộc cho dịch vụ quốc tế (UPS WW, FedEx IP) |
| Extra fields | Không | Hỗ trợ trade_terms, tax_type, tax_number |
Giải thích các field bổ sung
| No. | Field Name | Data Type | Description |
|---|---|---|---|
| 1 | mode | String | Bắt buộc với service nâng cao. Giá trị: "advanced" |
| 2 | consignee_company | String | Tên công ty người nhận. Bắt buộc với service advanced, tối đa 100 ký tự |
| 3 | consignee_email | String | Email người nhận. Không bắt buộc, tối đa 50 ký tự |
| 4 | packages | Array | Mảng các kiện hàng. Bắt buộc, tối thiểu 1 kiện |
| 5 | packages[].weight | Decimal | Trọng lượng kiện (theo unit_type, mặc định gram) |
| 6 | packages[].length | Decimal | Chiều dài (theo unit_type, mặc định cm) |
| 7 | packages[].width | Decimal | Chiều rộng (theo unit_type, mặc định cm) |
| 8 | packages[].height | Decimal | Chiều cao (theo unit_type, mặc định cm) |
| 9 | packages[].goods | Array | Mảng hàng hóa trong kiện này. Bắt buộc, tối thiểu 1 mục |
| 10 | packages[].goods[].name_en | String | Tên hàng hóa (tiếng Anh). Bắt buộc, tối đa 100 ký tự |
| 11 | packages[].goods[].name_vi | String | Tên hàng hóa (tiếng Việt). Không bắt buộc |
| 12 | packages[].goods[].brand | String | Thương hiệu. Không bắt buộc |
| 13 | packages[].goods[].packaging_type | String | Loại đóng gói. Không bắt buộc |
| 14 | packages[].goods[].origin | String | Mã quốc gia xuất xứ (ISO-2). Bắt buộc, 2 ký tự |
| 15 | packages[].goods[].price | Decimal | Giá trị hàng hóa (USD). Bắt buộc, tối thiểu 0.01 |
| 16 | packages[].goods[].quantity | Integer | Số lượng. Bắt buộc, tối thiểu 1 |
| 17 | packages[].goods[].unit | String | Đơn vị tính (vd: pcs, kg, set). Không bắt buộc |
| 18 | packages[].goods[].hs_code | String | Mã HS Code hải quan. Không bắt buộc |
| 19 | packages[].goods[].material | String | Chất liệu. Không bắt buộc |
| 20 | extra_fields | Object | Thông tin thuế/thương mại bổ sung. Không bắt buộc |
| 21 | extra_fields.trade_terms | String | Điều khoản thương mại: DDU, DDP, CIP, C&F. Với FEDEX_ICP/FEDEX_ICP2 chỉ được DDP |
| 22 | extra_fields.tax_type | String | Loại thuế: IOSS, EORI, VAT |
| 23 | extra_fields.tax_number | String | Mã số thuế tương ứng (tối đa 100 ký tự) |
| 24 | extra_fields.signature_required | Boolean | Yêu cầu chữ ký khi giao hàng. Chỉ hỗ trợ dịch vụ JingDong, chỉ dùng trong Advanced Mode |
Validation cho Advanced Mode
packages
- Bắt buộc, mảng tối thiểu 1 phần tử.
- Mỗi kiện phải có đầy đủ:
weight,length,width,height. - Giá trị phải > 0. Kích thước tối đa 150cm (quy đổi theo
unit_type).
goods (với service bắt buộc advanced)
- Bắt buộc, mảng tối thiểu 1 phần tử.
- Mỗi mục hàng hóa phải có:
name_en: bắt buộc, tối đa 100 ký tựorigin: bắt buộc, 2 ký tự (mã quốc gia ISO-2)price: bắt buộc, số > 0 (tối thiểu 0.01)quantity: bắt buộc, số nguyên ≥ 1
extra_fields
- Không bắt buộc.
- Nếu truyền, các giá trị bên trong đều là string hoặc boolean.
extra_fields.trade_terms
- Giá trị cho phép:
DDU,DDP,CIP,C&F. - Với dịch vụ
FEDEX_ICPvàFEDEX_ICP2: chỉ chấp nhậnDDP.
extra_fields.tax_type
- Giá trị cho phép:
IOSS,EORI,VAT.
extra_fields.signature_required
- Kiểu
boolean. Chỉ hỗ trợ dịch vụ JingDong. - Chỉ có thể dùng trong Advanced Mode — bị từ chối (
prohibited) nếu truyền ở Simple Mode.
Quy đổi đơn vị
Hệ thống lưu trữ nội bộ theo mm-g. Khi truyền unit_type khác, hệ thống tự quy đổi:
| unit_type | Cân nặng → gram | Kích thước → mm |
|---|---|---|
| mm-g | ×1 | ×1 |
| cm-g | ×1 | ×10 |
| cm-kg | ×1000 | ×10 |
| in-lb | ×453.59 | ×25.4 |
Response
Giống response tạo đơn thường:
{
"error": false,
"ref": null,
"message": "Tạo đơn thành công",
"data": "BELL240625120345123"
}
Ví dụ lỗi validation
{
"error": true,
"ref": null,
"message": "Service này yêu cầu mode \"advanced\" với đầy đủ thông tin goods.",
"errors": {
"goods.0.origin": ["origin là bắt buộc"],
"goods.0.price": ["price là bắt buộc"]
},
"data": null
}
Chỉnh sửa địa chỉ đơn lỗi và gửi lại
Dùng cho đơn đang ở trạng thái Error (status = 11) do nhà vận chuyển từ chối vì thông tin địa chỉ người nhận. API lưu địa chỉ mới và đưa đơn vào luồng gửi lại, giữ nguyên mã đơn BELL — không tạo đơn mới.
Request là bất đồng bộ: BELL trả về 202 ngay sau khi lưu địa chỉ và xếp hàng, rồi mới gọi sang nhà vận chuyển. Kết quả cuối cùng lấy bằng cách tra cứu đơn (xem Theo dõi kết quả).
| Method | POST |
|---|---|
| URL | /api/order/edit-order |
- Gọi
/api/order/get-order-info/{id}để đọcstatusvàprocessing_error— biết chính xác trường nào cần sửa. - Gọi
/api/order/edit-ordervới các field địa chỉ cần thay đổi. - Nhận
202= yêu cầu đã được xếp hàng. Tra lại/api/order/get-order-info/{id}để lấy kết quả cuối. - Nếu bị lỗi, đọc
codetrong response lỗi để xử lý (xem bảng mã kết quả).
Body request
{
"order_code": "BELL240625120345123",
"consignee_country": "US",
"consignee_state_code": "CA",
"consignee_city": "San Francisco",
"consignee_postal_code": "94105",
"consignee_address": "123 Main Street",
"consignee_address_other": "Suite 200"
}
Giải thích
| No. | Field Name | Data Type | Description |
|---|---|---|---|
| 1 | order_code | String | Bắt buộc. Mã vận đơn BELL (order_code), tối đa 100 ký tự. Không dùng mã đối tác hoặc mã nhà vận chuyển |
| 2 | consignee_country | String | Mã quốc gia (ISO-2), tối đa 2 ký tự |
| 3 | consignee_state_code | String | State code, tối đa 50 ký tự. Bắt buộc với US và các dịch vụ advanced |
| 4 | consignee_city | String | Tỉnh / thành phố, tối đa 50 ký tự |
| 5 | consignee_postal_code | String | Mã bưu chính, tối đa 20 ký tự. Theo đúng quy tắc quốc gia / UniUni ở Validation Rules |
| 6 | consignee_address | String | Địa chỉ người nhận 1, tối đa 200 ký tự |
| 7 | consignee_address_other | String | Địa chỉ người nhận 2, tối đa 200 ký tự. Cho phép null để xoá |
Quy tắc chỉnh sửa
- Phải truyền ít nhất một field địa chỉ. Chỉ truyền
order_codesẽ bị từ chốiVALIDATION_FAILED. - Field địa chỉ không truyền thì giữ nguyên giá trị đang lưu. Truyền lại đúng giá trị cũ vẫn được coi là yêu cầu gửi lại đơn.
- Chỉ 6 field địa chỉ trên là được phép. Mọi key khác (
address_id,service_code,status,consignee_name,consignee_phone,packages,goods,extra_fields, các field tiền...) đều bị từ chối, kể cả khi truyềnnull. - Kho gửi, mã đơn BELL, dịch vụ, kiện hàng và hàng hoá không thay đổi. Muốn sửa các thông tin này phải huỷ đơn và tạo lại.
- Địa chỉ mới được validate theo đúng ràng buộc của dịch vụ đang gắn với đơn.
consignee_countryđược tự chuẩn hoá sang chữ in hoa vàUK→GB. - Với các dịch vụ yêu cầu ASCII (
US_UNIUNI_D,US_UPS_GROUND,LBE6), địa chỉ gửi lên được tự chuyển sang ASCII và response trả về mảngwarningstương ứng.
Điều kiện đơn hợp lệ
Đơn phải thoả tất cả điều kiện sau, nếu không sẽ nhận 409:
- Thuộc đúng customer đang gọi API (sai chủ sở hữu trả
404, không phân biệt với đơn không tồn tại). - Đang ở trạng thái
Error(status = 11), chưa bị xoá. - Chưa có mã đơn phía nhà vận chuyển và chưa có tracking.
- Không có lượt gửi lại nào đang xử lý.
Không import, sửa hay huỷ đơn từ giao diện trong lúc một lượt gửi lại đang chạy. Mỗi đơn chỉ xử lý một lượt tại một thời điểm.
Response thành công (202)
Envelope ngắn, giống API tạo đơn:
{
"error": false,
"ref": null,
"message": "Cập nhật đơn thành công",
"data": "BELL240625120345123",
"warnings": []
}
Giải thích
| No. | Field Name | Data Type | Description |
|---|---|---|---|
| 1 | error | boolean | false = BELL đã nhận và ghi nhận yêu cầu |
| 2 | ref | String | Luôn null ở response thành công |
| 3 | message | String | Cập nhật đơn thành công |
| 4 | data | String | Mã vận đơn BELL (không đổi so với trước khi sửa) |
| 5 | warnings | Array | Cảnh báo không chặn, ví dụ ASCII auto-sanitize. Cùng cấu trúc với API tạo đơn |
202 không có nghĩa là nhà vận chuyển đã nhận đơn202 chỉ khẳng định: địa chỉ mới đã được lưu và đơn đã được xếp vào luồng gửi lại. Việc gọi sang nhà vận chuyển diễn ra sau khi response đã trả về. Kết quả cuối cùng phải tra cứu riêng — xem mục Theo dõi kết quả.
Luồng xử lý
Đồng bộ (trước khi trả response):
- Kiểm tra quyền sở hữu và điều kiện đơn.
- Validate địa chỉ mới theo ràng buộc của dịch vụ đang gắn với đơn.
- Xác thực địa chỉ qua nhà cung cấp xác thực (có thể mất tới ~25 giây).
- Tính cước tạm cho địa chỉ mới — chỉ đọc bảng giá, chưa ghi gì vào công nợ.
- Lưu địa chỉ mới + payload gửi nhà vận chuyển. Đơn chuyển từ
Error(11) sangInit(1). - Trả
202.
Bất đồng bộ (sau khi response đã trả về):
- BELL gọi nhà vận chuyển tạo lô hàng, ghi nhận kết quả.
- Nếu được tiếp nhận: cập nhật cước, tải nhãn, đơn về
Label(3). - Nếu bị từ chối: đơn quay lại
Error(11),processing_errorđược cập nhật với lý do mới.
Theo dõi kết quả
Gọi /api/order/get-order-info/{id} và đọc status:
status | Ý nghĩa |
|---|---|
Init | Đang gửi sang nhà vận chuyển. Chờ và tra lại |
Label | Gửi lại thành công. tracking_code và tracking_label_url đã có giá trị |
Error | Nhà vận chuyển từ chối. Đọc processing_error để biết lý do, sửa tiếp rồi gọi lại API |
Thường mất vài giây tới vài chục giây. Nên chờ 5–10 giây rồi mới tra lần đầu, và giới hạn số lần poll. Nếu đơn ở Init quá lâu (trên vài phút), liên hệ hỗ trợ kèm mã đơn thay vì gọi lại API — gọi lại sẽ bị chặn 409.
Bảng mã kết quả
Thành công luôn là 202 với envelope ngắn ở trên. Mọi mã dưới đây đều là lỗi xảy ra trước khi địa chỉ được lưu. Envelope lỗi có thêm field code — luôn xử lý theo code, không dựa vào message.
| HTTP | code | Ý nghĩa và hành động phía đối tác |
|---|---|---|
| 404 | ORDER_NOT_FOUND | Không tìm thấy đơn hoặc đơn không thuộc customer. data = null |
| 409 | ORDER_BUSY | Đơn đang được xử lý bởi một tiến trình khác. Thử lại sau |
| 409 | ORDER_NOT_EDITABLE | Đơn không ở trạng thái Error, hoặc đã có mã đơn / tracking từ nhà vận chuyển |
| 409 | RECOVERY_NOT_RETRYABLE | Không còn lượt khôi phục nào hợp lệ cho đơn này |
| 409 | PROVIDER_RESULT_UNKNOWN | Đã có một lượt gửi lại đang xử lý hoặc chưa rõ kết quả. Không gọi lại — chờ hoặc liên hệ hỗ trợ kèm ref |
| 409 | BILLING_LOCKED | Invoice đã chốt hoặc công nợ cần kiểm tra. Liên hệ hỗ trợ |
| 409 | ADDRESS_RECOMMENDATION_AVAILABLE | Địa chỉ có đề xuất chỉnh sửa. Xem suggestions, xác nhận rồi gọi lại |
| 422 | VALIDATION_FAILED | Payload hoặc địa chỉ không hợp lệ. Xem errors |
| 422 | ADDRESS_VALIDATION_FAILED | Địa chỉ không xác thực được |
| 422 | PRICING_UNAVAILABLE | Không tính được cước cho địa chỉ mới |
| 422 | UNSUPPORTED_PROVIDER | Cấu hình nhà vận chuyển của đơn không hỗ trợ luồng này |
| 503 | PROVIDER_UNAVAILABLE | Không chuẩn bị được yêu cầu gửi nhà vận chuyển. Chưa gửi gì đi, có thể thử lại |
| 503 | ADDRESS_VALIDATION_UNAVAILABLE | Dịch vụ xác thực địa chỉ tạm thời không khả dụng. Thử lại sau |
| 503 | LOCAL_PERSISTENCE_FAILED | BELL chưa xử lý được yêu cầu. Nếu response có ref khác null, không gọi lại — tra cứu trạng thái đơn trước |
Ví dụ field không được phép sửa (422)
{
"error": true,
"ref": null,
"code": "VALIDATION_FAILED",
"message": "This field cannot be edited.",
"data": null,
"errors": {
"consignee_name": ["This field cannot be edited."]
},
"warnings": []
}
Ví dụ địa chỉ có đề xuất (409)
{
"error": true,
"ref": null,
"code": "ADDRESS_RECOMMENDATION_AVAILABLE",
"message": "Địa chỉ có đề xuất cần xác nhận trước khi tiếp tục.",
"data": null,
"suggestions": {
"consignee_city": "San Francisco",
"consignee_postal_code": "94105-1804"
},
"warnings": []
}
suggestions dùng tên field theo chuẩn đối tác và không được tự áp dụng — đối tác xác nhận rồi gọi lại API với giá trị mong muốn.
Cước phí và thanh toán
- Bước tính cước trong preflight chỉ đọc bảng giá và hạn mức ví. Không tạo giao dịch, không giữ tiền, không ghi cước.
- Cước chỉ được cập nhật sau khi nhà vận chuyển tiếp nhận đơn, tức là sau khi response
202đã trả về. Nhận202chưa có nghĩa là cước đã thay đổi. - Tra cước mới qua
/api/price/get-price/{order_number}sau khi đơn vềLabel. Trước đó giá trị trả về vẫn là cước của địa chỉ cũ. - Nếu nhà vận chuyển từ chối, cước giữ nguyên như trước khi sửa.
- Luồng này không tạo đơn mới, kiện hàng mới, hàng hoá mới hay giao dịch thanh toán mới.
Timeout và retry
API không còn chờ nhà vận chuyển, nhưng vẫn có bước xác thực địa chỉ đồng bộ có thể mất tới ~25 giây. Đặt timeout HTTP tối thiểu 60 giây.
Nếu request timeout hoặc lỗi mạng phía đối tác, không gọi lại ngay — địa chỉ có thể đã được lưu và đơn đã vào luồng gửi lại. Tra /api/order/get-order-info/{id} để xem status thực tế trước khi làm bất kỳ thao tác nào.
| Tình huống | Có gọi lại được không |
|---|---|
202 thành công | Không. Đơn đã vào luồng gửi lại — hãy theo dõi kết quả |
VALIDATION_FAILED, ADDRESS_VALIDATION_FAILED | Được, sau khi sửa dữ liệu |
ADDRESS_RECOMMENDATION_AVAILABLE | Được, sau khi xác nhận đề xuất |
ORDER_BUSY, PROVIDER_UNAVAILABLE, ADDRESS_VALIDATION_UNAVAILABLE | Được, chờ ít phút rồi thử lại |
PROVIDER_RESULT_UNKNOWN, LOCAL_PERSISTENCE_FAILED có ref | Không. Tra cứu trạng thái đơn, liên hệ hỗ trợ kèm ref |
| Timeout / không nhận được response | Không. Tra get-order-info trước |
Đơn về Error với processing_error mới | Được, sửa địa chỉ theo lý do rồi gọi lại |
Hủy đơn hàng
| Method | POST |
|---|---|
| URL | /api/order/cancel-order |
Payload request
| No. | Field Name | Data Type | Description |
|---|---|---|---|
| 1 | order_number | String | Mã vận đơn của BELL |
Response
{
"error": false,
"ref": null,
"message": "Thành công",
"data": null
}
In nhãn vận đơn
| Method | GET |
|---|---|
| URL | /api/order/print-order/{order_number} |
Path parameter
| No. | Field Name | Data Type | Description |
|---|---|---|---|
| 1 | order_number | String | Mã vận đơn BELL hoặc mã đơn đối tác (order_code_partner) |
Response
{
"error": false,
"ref": null,
"message": "Thành công",
"data": {
"orderNumber": "BELL1202103548",
"tracking": "42080521921449037400250000264",
"labelFormat": "PDF",
"labelSize": "4x6",
"label": "",
"labelUrl": "https://storage.bellvn.com/labels/BELL1202103548.pdf",
"receiptUrls": [
"https://storage.bellvn.com/receipts/BELL1202103548_1.pdf"
],
"trackings": [
{
"tracking_code": "42080521921449037400250000264",
"package_no": 1
}
],
"processing_error": null
}
}
Giải thích
| No. | Field Name | Data Type | Description |
|---|---|---|---|
| 1 | error | boolean | Trạng thái lỗi |
| 2 | ref | String | Mã tham chiếu |
| 3 | message | String | Thông báo |
| 4 | data.orderNumber | String | Mã đơn hàng truy vấn |
| 5 | data.tracking | String | Tracking number chính của đơn |
| 6 | data.labelFormat | String | Định dạng file nhãn: PDF, GIF, PNG, JPG (hoặc rỗng nếu chưa có nhãn) |
| 7 | data.labelSize | String | Kích thước nhãn (mặc định 4x6) |
| 8 | data.label | String | Nội dung nhãn Base64 (hiện luôn rỗng — dùng labelUrl thay thế) |
| 9 | data.labelUrl | String | URL file nhãn vận đơn để tải/xem trực tuyến |
| 10 | data.receiptUrls | Array | Danh sách URL file biên lai (waybill receipt). Có thể rỗng [] |
| 11 | data.trackings | Array | Danh sách tracking theo từng kiện (multi-package). Rỗng [] nếu đơn 1 kiện hoặc chưa có tracking |
| 12 | data.processing_error | String | Lý do đơn bị lỗi (status = 11 Error) đã được diễn giải sang tiếng Việt. null nếu đơn không ở trạng thái lỗi |
receiptUrls và trackings chỉ có giá trị với các đơn hàng dịch vụ JingDong (đơn nhiều kiện hoặc có biên lai riêng). Với các dịch vụ khác, hai trường này trả về mảng rỗng.
Tra cứu thông tin đơn hàng
| Method | GET |
|---|---|
| URL | /api/order/get-order-info/{id} |
Path parameter
| No. | Field Name | Data Type | Description |
|---|---|---|---|
| 1 | id | String | Mã đơn hàng BELL (order_code), mã đối tác (order_code_partner), hoặc ID nội bộ (id) |
Response
{
"status": "success",
"message": "Get order info successfully",
"data": {
"order_code": "BELL240625120345123",
"order_code_partner": "DEV123456789",
"status": "Label",
"service": "EPK",
"reason": null,
"processing_error": null,
"tracking_code": "42080521921449037400250000264",
"tracking_label_url": "https://storage.bellvn.com/labels/BELL240625120345123.pdf",
"carrier": "USPS",
"ship_date": "2024-06-25",
"consignee_name": "sarenda mcguire",
"consignee_phone": "0123456789",
"consignee_company": null,
"consignee_country": "US",
"consignee_state": "SD",
"consignee_city": "Wildomar",
"consignee_postal_code": "57718",
"consignee_address": "6105 W Elmwood Dr",
"consignee_address2": null,
"created_date": "2024-06-25 12:03:45"
}
}
Giải thích response
| No. | Field Name | Data Type | Description |
|---|---|---|---|
| 1 | status | String | success hoặc error |
| 2 | message | String | Thông báo kết quả |
| 3 | data.order_code | String | Mã vận đơn BELL |
| 4 | data.order_code_partner | String | Mã đơn hàng của đối tác |
| 5 | data.status | String | Trạng thái đơn hàng (xem bảng bên dưới) |
| 6 | data.service | String | Mã dịch vụ |
| 7 | data.reason | String | Lý do (ví dụ: lý do hủy đơn). Null nếu không có |
| 8 | data.processing_error | String | Lý do đơn bị lỗi (status = Error), đã được BELL diễn giải sang tiếng Việt. null nếu đơn không ở trạng thái lỗi hoặc không xác định được nguyên nhân |
| 9 | data.tracking_code | String | Tracking number của carrier |
| 10 | data.tracking_label_url | String | URL file nhãn vận đơn |
| 11 | data.carrier | String | Tên carrier vận chuyển |
| 12 | data.ship_date | String | Ngày gửi hàng |
| 13 | data.consignee_name | String | Tên người nhận |
| 14 | data.consignee_phone | String | Số điện thoại người nhận |
| 15 | data.consignee_company | String | Công ty người nhận |
| 16 | data.consignee_country | String | Mã quốc gia (ISO-2) |
| 17 | data.consignee_state | String | Bang / tỉnh |
| 18 | data.consignee_city | String | Thành phố |
| 19 | data.consignee_postal_code | String | Mã bưu chính |
| 20 | data.consignee_address | String | Địa chỉ người nhận |
| 21 | data.consignee_address2 | String | Địa chỉ người nhận 2 |
| 22 | data.created_date | String | Thời gian tạo đơn |
Bảng trạng thái đơn hàng
| Giá trị | Mô tả |
|---|---|
Init | Mới tạo |
Label | Đã có nhãn |
In Transit | Đang vận chuyển |
Out For Delivery | Đang giao hàng |
Delivered | Đã giao thành công |
Exception | Có vấn đề phát sinh |
Void | Đã hủy |
Request Cancel | Yêu cầu hủy |
Unknown | Không xác định |
Draft | Bản nháp |
Lỗi thường gặp
{
"status": "error",
"message": "Order not found"
}
{
"status": "error",
"message": "Order not belong to Customer"
}
Track shipment
| Method | GET |
|---|---|
| URL | /api/order/tracking/{order_number} |
Path request
| No. | Field Name | Data Type | Description |
|---|---|---|---|
| 1 | order_number | String | Mã vận đơn của BELL |
Response
{
"error": false,
"ref": null,
"message": "Thành công",
"data": [
{
"trackingNumber": "BELL2512171654532484",
"code": "12345678900",
"city": "City 0",
"stateCode": "State 0",
"zipCode": "Zip 0",
"countryCode": "Country 0",
"eventDate": "2025-12-18T03:57:04.896549Z",
"eventStatus": "LabelCreated 0",
"note": "Label Created"
},
{
"trackingNumber": "BELL2512171654532484",
"code": "12345678901",
"city": "City 1",
"stateCode": "State 1",
"zipCode": "Zip 1",
"countryCode": "Country 1",
"eventDate": "2025-12-18T03:57:04.896558Z",
"eventStatus": "LabelCreated 1",
"note": "Label Created"
}
]
}
Giải thích
| No. | Field Name | Data Type | Description |
|---|---|---|---|
| 1 | error | boolean | Trạng thái lỗi (false = thành công) |
| 2 | ref | String | Mã tham chiếu yêu cầu (có thể null) |
| 3 | message | String | Thông báo kết quả xử lý |
| 4 | data | Array | Danh sách sự kiện tracking |
| 5 | data[].trackingNumber | String | Mã vận đơn / tracking number |
| 6 | data[].code | String | Mã sự kiện hoặc mã tham chiếu nội bộ |
| 7 | data[].city | String | Thành phố phát sinh sự kiện |
| 8 | data[].stateCode | String | Mã bang / tỉnh |
| 9 | data[].zipCode | String | Mã bưu chính |
| 10 | data[].countryCode | String | Mã quốc gia (ISO-2) |
| 11 | data[].eventDate | String | Thời gian xảy ra sự kiện (ISO 8601, UTC) |
| 12 | data[].eventStatus | String | Trạng thái / nội dung sự kiện tracking |
| 13 | data[].note | String | Ghi chú/mô tả trạng thái |
Tra cứu cước phí đơn hàng
| Method | GET |
|---|---|
| URL | /api/price/get-price/{order_number} |
Path request
| No. | Field Name | Data Type | Description |
|---|---|---|---|
| 1 | order_number | String | Mã vận đơn của BELL |
Response
{
"error": false,
"message": "Success",
"data": [
{
"order_code": "BELL2512171654532484",
"amount": 15.50,
"type": "MAIN"
}
]
}
Giải thích
| No. | Field Name | Data Type | Description |
|---|---|---|---|
| 1 | error | boolean | Trạng thái lỗi (false = thành công) |
| 2 | message | String | Thông báo kết quả xử lý |
| 3 | data | Array | Danh sách chi tiết cước phí |
| 4 | data[].order_code | String | Mã vận đơn |
| 5 | data[].amount | Decimal | Số tiền cước |
| 6 | data[].type | String | Loại phí (MAIN: cước chính, hoặc phụ phí khác) |
API chỉ trả về cước phí của các đơn hàng thuộc invoice đang active. Nếu đơn chưa được tính cước hoặc chưa có invoice, sẽ trả về lỗi.