Skip to content
Translated page. The English version is the source of truth.

POST /apiv2/order1h

Tạo đơn thuê energy thời hạn 1 giờ thông qua nhiều nhà cung cấp energy với cơ chế tự động chuyển đổi dự phòng (failover).

URL Endpoint

POST https://netts.io/apiv2/order1h

Headers của yêu cầu

HeaderBắt buộcMô tả
Content-Typeapplication/json
X-API-KEYKhóa API của bạn từ bảng điều khiển Netts
X-Real-IPĐịa chỉ IP thuộc danh sách trắng của bạn

Body của yêu cầu

json
{
    "amount": 131000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"
}

Tham số

Tham sốLoạiBắt buộcMô tả
amountsố nguyênLượng Energy cần thuê (tối thiểu: 61000, tối đa: 3000000)
receiveAddresschuỗiĐịa chỉ TRON sẽ nhận energy (định dạng TRC-20)

Lựa chọn nhà cung cấp

API tự động lựa chọn nhà cung cấp energy tối ưu dựa trên:

  • Hiệu quả chi phí - Luôn tìm mức giá khả dụng thấp nhất
  • Tính khả dụng - Đảm bảo lượng dự trữ energy đầy đủ
  • Độ tin cậy - Sử dụng các nhà cung cấp có tỷ lệ thành công cao
  • Tốc độ - Ưu tiên thời gian bàn giao nhanh nhất

Yêu cầu mẫu

cURL

bash
curl -X POST https://netts.io/apiv2/order1h \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: your_api_key" \
  -H "X-Real-IP: your_whitelisted_ip" \
  -d '{
    "amount": 131000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"
  }'

Python

python
import requests

url = "https://netts.io/apiv2/order1h"
headers = {
    "Content-Type": "application/json",
    "X-API-KEY": "your_api_key",
    "X-Real-IP": "your_whitelisted_ip"
}

payload = {
    "amount": 131000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"
}

response = requests.post(url, headers=headers, json=payload)
data = response.json()

if response.status_code == 200:
    detail = data.get('detail', {})
    order_data = detail.get('data', {})
    print(f"Order ID: {order_data.get('orderId')}")
    print(f"Transaction Hash: {order_data.get('hash')}")
    print(f"Energy Delivered: {order_data.get('energy')}")
    print(f"Cost: {order_data.get('paidTRX')} TRX")
    print(f"Delegate Address: {order_data.get('delegateAddress')}")
else:
    error_detail = data.get('detail', data)
    print(f"Error Code: {error_detail.get('code', 'N/A')}")
    print(f"Error Message: {error_detail.get('msg', error_detail)}")

Phản hồi

Phản hồi thành công (200 OK)

json
{
    "detail": {
        "code": 10000,
        "msg": "Successful, 2.23 TRX deducted",
        "data": {
            "orderId": "1H123456",
            "paidTRX": 2.23,
            "hash": "a1b2c3d4e5f6789...",
            "delegateAddress": "TDelegatePoolAddress...",
            "energy": 131050
        }
    }
}

Các trường phản hồi

TrườngLoạiMô tả
detail.codesố nguyênLuôn là 10000 cho các đơn hàng thành công
detail.msgchuỗiThông báo thành công kèm theo số tiền đã trừ
detail.data.orderIdchuỗiMã định danh đơn hàng hợp nhất (định dạng: 1H{request_id})
detail.data.paidTRXsốTổng chi phí bằng TRX (bao gồm phí kích hoạt nếu địa chỉ chưa được kích hoạt)
detail.data.hashchuỗi | nullHash giao dịch. Trường này luôn tồn tại nhưng có thể rỗng - một số nhà cung cấp không trả về hash ngay lập tức. Sử dụng /apiv2/order_check sau 1 phút để lấy hash
detail.data.delegateAddresschuỗiĐịa chỉ pool đã ủy quyền (delegate) energy
detail.data.energysố nguyênLượng Energy + phần dư dự phòng (thường là +50)

Phản hồi lỗi

Lỗi xác thực (401)

json
{
    "detail": "Invalid API key or IP not in whitelist"
}

Không đủ số dư (403)

json
{
    "code": 1004,
    "msg": "Insufficient funds. Required: 2.23 TRX, Available: 1.50 TRX"
}

Dịch vụ không khả dụng (503)

json
{
    "code": 5003,
    "msg": "Service temporarily unavailable. All energy providers are currently unavailable."
}

Lỗi nhà cung cấp (503)

json
{
    "code": 5001,
    "msg": "Energy provider temporarily unavailable"
}
json
{
    "code": 5002,
    "msg": "Energy provider temporarily unavailable"
}
json
{
    "code": 5004,
    "msg": "Energy provider requires higher minimum amount"
}

Lỗi máy chủ nội bộ (500)

json
{
    "code": 5000,
    "msg": "Internal server error occurred"
}

Bảng tra cứu mã lỗi

Mô tảTrạng thái HTTP
10000Thành công200
10000Thành công (phản hồi từ bộ nhớ đệm)208
-Yêu cầu trùng lặp vẫn đang được xử lý409
1004Không đủ số dư403
5000Lỗi máy chủ nội bộ500
5001Nhà cung cấp energy không khả dụng503
5002Nhà cung cấp energy không khả dụng503
5003Dịch vụ energy không khả dụng503
5004Không đáp ứng mức tối thiểu của nhà cung cấp energy503

Giới hạn tốc độ

Các giới hạn tốc độ sau áp dụng cho endpoint này (trên mỗi địa chỉ IP):

Khoảng thời gianGiới hạnMô tả
1 giây50 yêu cầuTối đa 50 yêu cầu mỗi giây

Headers giới hạn tốc độ

http
RateLimit-Limit: 50
RateLimit-Remaining: 49
RateLimit-Reset: 1
X-RateLimit-Limit-Second: 50
X-RateLimit-Remaining-Second: 49

Vượt quá giới hạn tốc độ (429)

json
{
    "message": "API rate limit exceeded"
}

Tính lũy quyền (Idempotency)

API hỗ trợ tính lũy quyền để ngăn ngừa việc xử lý đơn hàng trùng lặp. Khi bạn gửi nhiều yêu cầu giống hệt nhau, hệ thống đảm bảo đơn hàng chỉ được xử lý đúng một lần.

Cơ chế hoạt động của tính lũy quyền

Tính duy nhất của yêu cầu được xác định bởi sự kết hợp của:

  • Dấu thời gian của yêu cầu (khoảng thời gian 1 giây)
  • Lượng Energy
  • Địa chỉ nhận
  • Khóa API

Mỗi yêu cầu được cấp một khoảng thời gian duy nhất 1 giây. Để bảo vệ hệ thống khỏi việc lạm dụng và đảm bảo xử lý chính xác, các yêu cầu có tham số giống hệt nhau không thể gửi thường xuyên hơn một lần mỗi giây.

Hành vi hiện tại: Hệ thống tự động bảo vệ khách hàng khỏi các lần thử lại do nhầm lẫn đối với lượng energy đã được đặt. Nếu bạn vô tình gửi cùng một yêu cầu hai lần, bạn sẽ không bị tính phí hai lần.

Cung cấp khóa riêng của bạn

Bạn có thể chủ động kiểm soát tính lũy quyền bằng cách gửi header X-Idempotency-Key. Khi header này xuất hiện, chỉ riêng giá trị đó sẽ quyết định liệu một yêu cầu có phải là lặp lại hay không, và sự kết hợp tự động ở trên sẽ không được sử dụng. Khi nó vắng mặt, không có gì thay đổi — máy chủ sẽ tự suy ra khóa cho bạn.

HeaderX-Idempotency-Key
Định dạngChính xác 64 ký tự thập lục phân viết thường — một chuỗi băm SHA-256
Thời gian tồn tại24 giờ kể từ yêu cầu đầu tiên mang khóa đó
Phạm viTài khoản của bạn. Cùng một giá trị được gửi bởi một tài khoản khác không bao giờ trả về kết quả của bạn

Một khóa có bất kỳ định dạng nào khác — UUID có dấu gạch ngang, base64, chữ hoa hex — đều bị từ chối với mã 400 trước khi đơn hàng được đặt và trước khi bất kỳ khoản phí nào bị trừ:

json
{
    "detail": "Invalid idempotency key format. Must be 64-character hexadecimal string."
}

Định dạng này khác với các endpoint khác. /apiv2/withdraw, /apiv2/bandwidth và orchestrator chấp nhận khóa base64 từ 16–64 ký tự. Endpoint này chỉ chấp nhận chuỗi băm hex 64 ký tự, do đó mã tạo khóa được sao chép từ các endpoint đó sẽ trả về lỗi 400 tại đây.

Cách tạo khóa

Hãy tạo khóa bắt nguồn từ khóa API của bạn. Điều này giúp giá trị là duy nhất cho tài khoản của bạn, có thể tái tạo khi thử lại, và người khác không thể đoán ra được:

python
import hashlib
import hmac

def make_idempotency_key(api_key: str, address: str, amount: int, nonce: str) -> str:
    message = f"{address}:{amount}:{nonce}"
    return hmac.new(api_key.encode(), message.encode(), hashlib.sha256).hexdigest()

nonce thuộc về đơn hàng, không thuộc về yêu cầu. Hãy chọn nó một lần duy nhất khi đơn hàng được tạo phía bạn, và truyền cùng giá trị đó trong mỗi lần gửi của đơn hàng đó — bao gồm lần thử đầu tiên cũng như mọi lần thử lại. Việc tạo một giá trị mới bên trong hàm gửi (str(uuid.uuid4()) ở mỗi lệnh gọi) sẽ khiến mỗi lần thử có một khóa khác nhau, vì vậy việc thử lại sau khi hết thời gian chờ (timeout) sẽ bị coi là một đơn hàng thứ hai và bị trừ tiền lần nữa. Lựa chọn đúng đắn và đơn giản nhất chính là mã ID đơn hàng bạn đã có sẵn: nó tồn tại trước lần thử đầu tiên và vẫn giữ nguyên kể cả khi tiến trình của bạn khởi động lại.

python
# một lần, khi đơn hàng xuất hiện trong hệ thống của bạn
order = create_order(address="TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE", amount=131000)

# ở lần thử đầu tiên và ở mọi lần thử lại — cùng ba đầu vào, cùng một khóa
key = make_idempotency_key(API_KEY, order.address, order.amount, order.id)

headers = {
    "Content-Type": "application/json",
    "X-API-KEY": API_KEY,
    "X-Idempotency-Key": key,
}

Một khóa tồn tại trong 24 giờ. Sau khoảng thời gian đó, cùng một nonce sẽ được tự do trở lại và bắt đầu một đơn hàng mới.

Không sử dụng giá trị mà bất kỳ ai khác cũng có thể tạo ra — 64 số không, chuỗi băm của một từ cố định. Các khóa dùng chung một không gian giữa các tài khoản. Sự trùng lặp như vậy không bao giờ để lộ đơn hàng của tài khoản khác, nhưng yêu cầu của bạn sẽ bị từ chối với mã 409 cho đến khi khóa của họ hết hạn, đây không phải là câu trả lời bạn mong muốn khi đang thử lại.

Đặt hai đơn hàng giống hệt nhau

Đôi khi bạn thực sự muốn tạo cùng một đơn hàng hai lần — cùng một lượng energy gửi đến cùng một địa chỉ, liên tiếp nhau. Khóa tự động không thể phân biệt điều đó với một lần thử lại: hai yêu cầu giống nhau đến từng byte, và điều duy nhất phân biệt chúng là thời điểm chúng đến nơi.

Nếu không có khóa riêng của bạn, kết quả sẽ phụ thuộc vào khoảng cách thời gian giữa chúng:

Khoảng cách giữa hai yêu cầuĐiều gì xảy ra
Trong cùng khoảng thời gian 1 giâyYêu cầu thứ hai bị coi là lặp lại. Nó không được thực thi: bạn nhận được 208 và phản hồi của đơn hàng đầu tiên, bao gồm cả orderId. Bạn không bị tính phí cho yêu cầu này
Cách nhau hơn một giâyHai khóa khác nhau — cả hai đơn hàng đều được đặt và cả hai đều bị tính phí

Vì vậy, nếu bạn dựa vào khóa tự động, hãy để khoảng cách nhiều hơn một giây giữa hai đơn hàng giống hệt nhau, và kiểm tra mã trạng thái: 208 có nghĩa là đơn hàng bạn vừa gửi đã không được đặt.

Việc tạm dừng chỉ là một giải pháp tình thế, không phải là cách khắc phục triệt để. Nó phân tách mọi yêu cầu, bao gồm cả những yêu cầu bạn không bao giờ có ý định lặp lại — một lần thử lại sau khi hết thời gian chờ, một lần nhấp đúp chuột, một tin nhắn được gửi lại bởi hàng đợi của bạn. Những yêu cầu đó cũng đến muộn hơn khoảng thời gian 1 giây, vì vậy chúng được đặt thành các đơn hàng riêng biệt và bị tính phí riêng biệt. Thời gian chờ phản hồi của endpoint này là 10 giây, đã vượt xa khoảng thời gian quy định: khóa tự động không bảo vệ được lần thử lại diễn ra sau khi hết thời gian chờ.

Khóa riêng của bạn giúp loại bỏ việc phỏng đoán, vì quyền quyết định được chuyển về phía duy nhất biết rõ câu trả lời:

Bạn đang làm gìThứ bạn gửiKết quả
Một đơn hàng thứ hai, thực sự mớiMột nonce mớiMột khóa mới — đơn hàng được đặt
Một lần thử lại của đơn hàng mà bạn chưa biết kết quảnonce của lần thử đầu tiênCùng một khóa — 208, phản hồi ban đầu, không bị trừ tiền lần hai

Hàng thứ hai chính là lý do header này tồn tại, và cũng là nơi các triển khai thường mắc lỗi: xem lưu ý bên dưới mục Cách tạo khóa.

Mã trạng thái HTTP cho các yêu cầu trùng lặp

Mã trạng tháiTênMô tả
200OKĐơn hàng đã được xử lý thành công (yêu cầu đầu tiên)
208Already ReportedĐơn hàng đã được xử lý trước đó, trả về phản hồi từ bộ nhớ đệm
409ConflictYêu cầu hiện đang được xử lý, không thử lại

Yêu cầu trùng lặp - Đã được xử lý (208)

Khi nhận được một yêu cầu trùng lặp cho một đơn hàng đã hoàn tất:

json
{
    "detail": {
        "code": 10000,
        "msg": "Successful, 2.54 TRX deducted",
        "data": {
            "hash": "9e4c20e21e01e4c39b21b670d1ea1fc1e4b0de94d8fbd4c190d5378ba911dfae",
            "energy": 65050,
            "orderId": "1H70bcc7962a",
            "paidTRX": 2.535,
            "delegateAddress": "TNp5gsJhBmZFXgCdgjMgr8pEZ8fHgXUHDq"
        }
    },
    "idempotency": {
        "status": "completed",
        "cached": true,
        "original_created_at": "2025-12-03T10:34:49.104896"
    }
}

Nội dung phản hồi giống hệt với phản hồi thành công ban đầu, có thêm đối tượng idempotency cho biết đây là phản hồi từ bộ nhớ đệm.

Yêu cầu trùng lặp - Vẫn đang xử lý (409)

Khi một yêu cầu trùng lặp đến trong khi yêu cầu ban đầu vẫn đang được xử lý:

json
{
    "success": false,
    "error": "duplicate_request_processing",
    "message": "This request is currently being processed. Please wait and do not retry.",
    "idempotency_key": "b9e67b2412d33c92...",
    "retry_after_seconds": 3
}

Khuyến nghị: Chờ đúng số giây được chỉ định trong retry_after_seconds trước khi kiểm tra trạng thái đơn hàng.

Các phương pháp hay nhất

  • Không gửi các yêu cầu song song có cùng tham số - hãy đợi phản hồi của từng yêu cầu
  • Sử dụng nonce mới cho mỗi đơn hàng mới, và dùng lại nonce của lần thử đầu tiên cho mỗi lần thử lại của đơn hàng đó
  • Không bao giờ tạo lại nonce tại thời điểm gửi — lần thử lại phải tái tạo đúng khóa của lần thử đầu tiên, không phải một khóa mới
  • Xử lý các phản hồi 409 bằng cách chờ đợi, không thử lại ngay lập tức
  • Kiểm tra trường idempotency.cached để xác định các phản hồi từ bộ nhớ đệm — mã 208 có nghĩa là đơn hàng bạn vừa gửi đã không được đặt

Ghi chú

  • Energy được bàn giao ngay lập tức sau khi đặt hàng thành công (thường trong vòng 0.5-10 giây)
  • Thời gian chờ phản hồi API: Tối đa 10 giây, thường phản hồi trong vòng tối đa 2 giây
  • Kích hoạt địa chỉ: Nếu địa chỉ nhận chưa được kích hoạt, Netts sẽ kích hoạt địa chỉ đó theo giá vốn
  • Độ trễ kích hoạt: Đối với các địa chỉ chưa được kích hoạt, phản hồi API có thể mất tới 6 giây do quy trình kích hoạt
  • Các đơn hàng được xử lý 24/7 với cơ chế tự động chuyển đổi dự phòng nhà cung cấp
  • Lượng Energy tối thiểu: 61.000 đơn vị
  • Lượng Energy tối đa: 3.000.000 đơn vị mỗi đơn hàng
  • Phần dư Energy dự phòng: +50 đơn vị được cộng tự động để bù trừ cho nhà cung cấp (miễn phí)
  • Hash giao dịch: Trường này luôn tồn tại nhưng có thể rỗng nếu nhà cung cấp không trả về ngay lập tức. Để lấy hash, hãy gọi /apiv2/order_check không sớm hơn 1 phút sau khi đặt đơn hàng
  • Lựa chọn nhà cung cấp: Tự động dựa trên chi phí và tính khả dụng
  • Định dạng mã đơn hàng: 1H{request_id} để theo dõi hợp nhất
  • Định giá: Linh hoạt dựa trên thời gian trong ngày và lượng energy
  • Thời hạn: Cố định 1 giờ (3600 giây)
  • Giới hạn tốc độ: 50 yêu cầu mỗi giây trên mỗi địa chỉ IP