Appearance
POST /apiv2/order1h
Buat pesanan sewa Energy 1 jam melalui beberapa penyedia Energy dengan failover otomatis.
URL Endpoint
POST https://netts.io/apiv2/order1hHeader Permintaan
| Header | Diperlukan | Deskripsi |
|---|---|---|
| Content-Type | Ya | application/json |
| X-API-KEY | Ya | Kunci API Anda dari dasbor Netts |
| X-Real-IP | Ya | Alamat IP dari whitelist Anda |
Isi Permintaan
json
{
"amount": 131000,
"receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"
}Parameter Permintaan
| Parameter | Tipe | Diperlukan | Deskripsi |
|---|---|---|---|
| amount | integer | Ya | Jumlah Energy yang akan disewa (minimum: 61000, maksimum: 3000000) |
| receiveAddress | string | Ya | Alamat TRON yang akan menerima Energy (format TRC-20) |
Pemilihan Penyedia
API secara otomatis memilih penyedia Energy yang optimal berdasarkan:
- Efisiensi biaya - Selalu menemukan harga terendah yang tersedia
- Ketersediaan - Memastikan cadangan Energy yang cukup
- Keandalan - Menggunakan penyedia dengan tingkat keberhasilan tinggi
- Kecepatan - Memprioritaskan waktu pengiriman tercepat
Contoh
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)}")Respons
Respons Sukses (200 OK)
json
{
"detail": {
"code": 10000,
"msg": "Successful, 2.23 TRX deducted",
"data": {
"orderId": "1H123456",
"paidTRX": 2.23,
"hash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
"delegateAddress": "TNp5gsJhBmZFXgCdgjMgr8pEZ8fHgXUHDq",
"energy": 131050
}
}
}Bidang Respons
| Bidang | Tipe | Deskripsi |
|---|---|---|
| detail.code | integer | Selalu 10000 untuk pesanan yang berhasil |
| detail.msg | string | Pesan sukses dengan jumlah yang dipotong |
| detail.data.orderId | string | ID pesanan terpadu (format: 1H{request_id}) |
| detail.data.paidTRX | number | Total biaya dalam TRX (termasuk biaya aktivasi jika alamat belum diaktifkan) |
| detail.data.hash | string | null | Hash transaksi. Bidang selalu ada tetapi mungkin kosong - beberapa penyedia tidak mengembalikan hash secara langsung. Gunakan /apiv2/order_check setelah 1 menit untuk mendapatkan hash |
| detail.data.delegateAddress | string | Alamat pool yang mendelegasikan Energy |
| detail.data.energy | integer | Jumlah Energy + buffer (biasanya +50) |
Respons Kesalahan
Kesalahan Autentikasi (401)
json
{
"detail": "Invalid API key or IP not in whitelist"
}Saldo Tidak Cukup (403)
json
{
"code": 1004,
"msg": "Insufficient funds. Required: 2.23 TRX, Available: 1.50 TRX"
}Layanan Tidak Tersedia (503)
json
{
"code": 5003,
"msg": "Service temporarily unavailable. All energy providers are currently unavailable."
}Kesalahan Penyedia (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"
}Kesalahan Server Internal (500)
json
{
"code": 5000,
"msg": "Internal server error occurred"
}Referensi Kode Kesalahan
| Kode | Deskripsi | Status HTTP |
|---|---|---|
10000 | Berhasil | 200 |
10000 | Berhasil (respons ter-cache) | 208 |
- | Permintaan duplikat masih diproses | 409 |
1004 | Saldo tidak mencukupi | 403 |
5000 | Kesalahan server internal | 500 |
5001 | Penyedia Energy tidak tersedia | 503 |
5002 | Penyedia Energy tidak tersedia | 503 |
5003 | Layanan Energy tidak tersedia | 503 |
5004 | Minimum penyedia Energy tidak terpenuhi | 503 |
Batas Kecepatan
Batas laju berikut berlaku untuk endpoint ini (per alamat IP):
| Periode | Batas | Deskripsi |
|---|---|---|
| 1 detik | 50 permintaan | Maksimum 50 permintaan per detik |
Header Batas Laju
http
RateLimit-Limit: 50
RateLimit-Remaining: 49
RateLimit-Reset: 1
X-RateLimit-Limit-Second: 50
X-RateLimit-Remaining-Second: 49Batas Laju Terlampaui (429)
json
{
"message": "API rate limit exceeded"
}Idempotensi
API mendukung idempotensi untuk mencegah pemrosesan pesanan ganda. Saat Anda mengirim beberapa permintaan yang identik, sistem memastikan pesanan hanya diproses satu kali.
Cara Kerja Idempotensi
Keunikan permintaan ditentukan oleh kombinasi dari:
- Timestamp permintaan (jendela 1 detik)
- Jumlah Energy
- Alamat penerima
- Kunci API
Setiap permintaan diberikan jendela keunikan 1 detik. Untuk melindungi sistem dari penyalahgunaan dan memastikan pemrosesan yang tepat, permintaan dengan parameter identik tidak dapat dikirim lebih sering daripada sekali per detik.
Perilaku saat ini: Sistem secara otomatis melindungi klien dari percobaan ulang yang keliru pada Energy yang sudah dipesan. Jika Anda tidak sengaja mengirim permintaan yang sama dua kali, Anda tidak akan dikenakan biaya dua kali.
Menyediakan Kunci Anda Sendiri
Anda dapat mengatur idempotensi sendiri dengan mengirimkan header X-Idempotency-Key. Jika ada, nilai itu sendiri yang menentukan apakah suatu permintaan merupakan pengulangan, dan kombinasi otomatis di atas tidak digunakan. Jika tidak ada, tidak ada yang berubah — server menghasilkan kunci untuk Anda.
| Header | X-Idempotency-Key |
| Format | Tepat 64 karakter heksadesimal huruf kecil — digest SHA-256 |
| Masa berlaku | 24 jam dari permintaan pertama yang membawa kunci tersebut |
| Cakupan | Akun Anda. Nilai yang sama yang dikirim oleh akun lain tidak akan pernah mengembalikan hasil Anda |
Kunci dengan bentuk lain apa pun — UUID dengan tanda hubung, base64, heksadesimal huruf besar — akan ditolak dengan 400 sebelum pesanan dibuat dan sebelum biaya apa pun dipotong:
json
{
"detail": "Invalid idempotency key format. Must be 64-character hexadecimal string."
}Formatnya berbeda dari endpoint lain.
/apiv2/withdraw,/apiv2/bandwidthdan orchestrator menerima kunci base64 16–64 karakter. Endpoint ini hanya menerima digest hex 64 karakter, jadi kode pembuatan kunci yang disalin dari endpoint tersebut akan mengembalikan 400 di sini.
Cara membentuk kunci
Turunkan dari kunci API Anda. Itu membuat nilainya unik untuk akun Anda, dapat direproduksi pada percobaan ulang, dan tidak mungkin diperoleh oleh orang lain:
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()
noncemilik pesanan, bukan permintaan. Tentukan sekali, saat pesanan dibuat di sisi Anda, dan berikan nilai yang sama persis pada setiap pengiriman pesanan tersebut — upaya pertama dan setiap percobaan ulang sama saja. Menghasilkan nilai baru di dalam fungsi pengiriman (str(uuid.uuid4())pada setiap panggilan) memberi setiap upaya kunci yang berbeda, sehingga percobaan ulang setelah waktu habis diterima sebagai pesanan kedua dan dikenakan biaya lagi. Pilihan benar yang paling sederhana adalah ID pesanan yang sudah Anda miliki: ID tersebut ada sebelum upaya pertama dan tetap bertahan saat proses Anda dimulai ulang.
python
# sekali, saat pesanan muncul di sistem Anda
order = create_order(address="TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE", amount=131000)
# pada upaya pertama dan pada setiap percobaan ulang — tiga input yang sama, kunci yang sama
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,
}Kunci berlaku selama 24 jam. Setelah itu nonce yang sama bebas kembali dan memulai pesanan baru.
Jangan gunakan nilai yang dapat diperoleh orang lain — 64 angka nol, digest dari kata tetap. Kunci berbagi satu ruang di seluruh akun. Tabrakan seperti itu tidak pernah mengekspos pesanan akun lain, tetapi permintaan Anda akan ditolak dengan 409 sampai kunci mereka kedaluwarsa, yang bukan merupakan jawaban yang Anda inginkan di tengah percobaan ulang.
Membuat Dua Pesanan Identik
Terkadang Anda benar-benar menginginkan pesanan yang sama dua kali — jumlah Energy yang sama ke alamat yang sama, satu demi satu. Kunci otomatis tidak dapat membedakannya dari percobaan ulang: kedua permintaan tersebut identik byte demi byte, dan satu-satunya hal yang membedakannya adalah momen kedatangannya.
Tanpa kunci Anda sendiri, hasilnya tergantung pada jarak waktu di antara keduanya:
| Jarak antara kedua permintaan | Apa yang terjadi |
|---|---|
| Di dalam jendela 1 detik yang sama | Permintaan kedua dianggap sebagai pengulangan. Permintaan tidak dieksekusi: Anda mendapatkan 208 dan respons pesanan pertama, termasuk orderId. Tidak ada biaya yang dikenakan untuk itu |
| Terpisah lebih dari satu detik | Dua kunci berbeda — kedua pesanan dibuat dan keduanya dikenakan biaya |
Jadi, jika Anda mengandalkan kunci otomatis, berikan jeda lebih dari satu detik antara dua pesanan yang identik, dan baca kode status: 208 berarti pesanan yang baru saja Anda kirim tidak dibuat.
Jeda adalah solusi sementara, bukan perbaikan tuntas. Itu memisahkan setiap permintaan, termasuk permintaan yang tidak pernah Anda maksudkan untuk diulang — percobaan ulang setelah waktu habis, klik ganda, pesan yang dikirim ulang oleh antrean Anda. Permintaan tersebut juga tiba lebih lambat dari jendela waktu, sehingga dibuat sebagai pesanan terpisah dan dikenakan biaya terpisah. Batas waktu respons endpoint ini adalah 10 detik, yang sudah jauh di luar jendela waktu: kunci otomatis tidak melindungi percobaan ulang yang terjadi setelah batas waktu terlampaui.
Kunci Anda sendiri menghilangkan tebakan, karena keputusan berpindah ke satu-satunya sisi yang tahu jawabannya:
| Yang Anda lakukan | Yang Anda kirim | Hasil |
|---|---|---|
| Pesanan kedua yang benar-benar baru | nonce baru | Kunci baru — pesanan dibuat |
| Percobaan ulang pesanan yang hasilnya belum Anda ketahui | nonce dari upaya pertama | Kunci yang sama — 208, respons asli, tidak ada biaya kedua |
Baris kedua adalah alasan keberadaan header ini, dan di situlah implementasi biasanya meleset: lihat catatan di bawah Cara membentuk kunci.
Kode Status HTTP untuk Permintaan Duplikat
| Kode Status | Nama | Deskripsi |
|---|---|---|
| 200 | OK | Pesanan berhasil diproses (permintaan pertama) |
| 208 | Already Reported | Pesanan telah diproses sebelumnya, mengembalikan respons ter-cache |
| 409 | Conflict | Permintaan sedang diproses, jangan coba lagi |
Permintaan Duplikat - Sudah Diproses (208)
Saat permintaan duplikat diterima untuk pesanan yang sudah selesai:
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"
}
}Badan respons identik dengan respons sukses asli, dengan tambahan objek idempotency yang menunjukkan bahwa ini adalah respons yang di-cache.
Permintaan Duplikat - Masih Diproses (409)
Saat permintaan duplikat tiba ketika permintaan asli masih diproses:
json
{
"success": false,
"error": "duplicate_request_processing",
"message": "This request is currently being processed. Please wait and do not retry.",
"idempotency_key": "b9e67b2412d33c92a4f0e1c3d5b7a9f2e4c6d8b0a2f4e6c8d0b2a4f6e8c0d2b4",
"retry_after_seconds": 3
}Rekomendasi: Tunggu selama retry_after_seconds yang ditentukan sebelum memeriksa status pesanan.
Praktik Terbaik
- Jangan mengirim permintaan paralel dengan parameter yang sama - tunggu setiap respons
- Gunakan
noncebaru untuk setiap pesanan baru, dannonceupaya pertama untuk setiap percobaan ulangnya - Jangan pernah membuat ulang
noncepada saat pengiriman — percobaan ulang harus mereproduksi kunci upaya pertama, bukan kunci baru - Tangani respons 409 dengan menunggu, bukan dengan langsung mencoba lagi
- Periksa bidang
idempotency.cacheduntuk mengidentifikasi respons yang di-cache —208berarti pesanan yang baru saja Anda kirim tidak dibuat
Akun Pascabayar
Akun pada penagihan pascabayar menggunakan endpoint, URL, header, dan badan permintaan yang sama seperti yang lain. Perbedaannya adalah cara pembayaran pesanan:
- Tidak ada yang dipotong dari deposit Anda. Setiap pesanan yang berhasil ditambahkan ke saldo tagihan akun Anda dalam mata uang penyelesaian yang disepakati dalam kontrak Anda. Anda membayarnya melalui faktur, sesuai perjanjian Anda.
- Akun Anda memiliki batas kredit. Selama jumlah jatuh tempo berada dalam batas tersebut, pesanan diterima bahkan dengan deposit nol.
- Hanya layanan yang dikirimkan yang ditagih. Pesanan yang ditolak atau tidak dieksekusi tidak dikenakan biaya apa pun.
- Jika alamat penerima harus diaktifkan, aktivasi tersebut merupakan bagian dari pesanan yang sama dan ditagih sebagai biaya terpisah.
Penagihan pascabayar diaktifkan oleh Netts untuk akun berdasarkan permintaan. Setiap respons memberi tahu Anda bagaimana pesanan dibayar: paymentMode bernilai postpaid atau prepaid.
Bidang permintaan tambahan
| Parameter | Tipe | Diperlukan | Deskripsi |
|---|---|---|---|
| test | boolean | Tidak | true — hanya menghitung harga. Tidak ada yang dipesan, dikirim, atau ditagih |
| freezePrice | boolean | Tidak | true — mengunci harga berdasarkan kontrak Anda selama 60 detik. Tidak ada yang dipesan atau ditagih |
| quoteId | string | Tidak | Buat pesanan dengan harga dari penawaran yang diterbitkan oleh freezePrice |
| priceCurrency | string | Tidak | TRX (default) atau mata uang kontrak Anda, seperti dalam settlement.asset. Untuk akun pascabayar, jumlah dalam mata uang kontrak Anda selalu disertakan |
quoteId tidak dapat digabungkan dengan test atau freezePrice. Bidang lain apa pun di badan permintaan akan ditolak.
Pemeriksaan harga (test: true)
json
{
"amount": 65000,
"receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"test": true
}json
{
"detail": {
"code": 10010,
"msg": "Test calculation",
"data": {
"amount": 65000,
"unitPriceSun": "20",
"discount": null,
"energyTRX": "1.300000",
"activationTRX": "1.100000",
"wouldCostTRX": "2.400000",
"paidTRX": 0,
"paymentMode": "postpaid",
"activationCheck": "inactive",
"alt": {"USDC": {"energy": "0.430541", "activation": "0.364304", "total": "0.794845"}},
"fxAt": "2026-10-19T07:15:18.469870+00:00"
}
}
}| Bidang | Deskripsi |
|---|---|
| unitPriceSun | Harga per unit Energy dalam SUN, termasuk diskon pribadi Anda jika memilikinya |
| discount | Diskon pribadi Anda (type, value) atau null |
| energyTRX / activationTRX / wouldCostTRX | Energy, aktivasi (jika alamat memerlukannya) dan total, dalam TRX |
| activationCheck | inactive — alamat akan diaktifkan dan ditagih; active — tidak ada aktivasi; unknown — tidak dapat diperiksa saat ini |
alt.<currency> | Jumlah yang sama dalam mata uang kontrak Anda |
| fxAt | Waktu nilai tukar yang digunakan untuk jumlah dalam mata uang kontrak Anda |
Penawaran harga tetap (freezePrice: true)
Gunakan penawaran untuk mengunci harga berdasarkan kontrak Anda sebelum Anda memesan.
- Kirim pesanan dengan
"freezePrice": true. Respons memiliki kode10011(Quote issued), bidang yang sama seperti pemeriksaan harga, ditambahquoteIddanexpiresAt. - Dalam waktu 60 detik kirim pesanan dengan
"quoteId": "<quoteId>"danamountsertareceiveAddressyang sama. - Pesanan ditagih pada harga penawaran — harga berdasarkan kontrak Anda pada saat penawaran diberikan — bahkan jika harga berubah di antaranya.
Penawaran dapat digunakan sekali dan hanya untuk produk yang sama: penawaran 1 jam tidak dapat membayar pesanan 5 menit. Penawaran yang kedaluwarsa atau sudah digunakan akan ditolak dan tidak ada yang dipesan.
json
{
"amount": 65000,
"receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"quoteId": "q_4f540f16a2c94b7f8e3d1a6b5c0e9d72"
}Pesanan berhasil
json
{
"detail": {
"code": 10000,
"msg": "Successful, 1.30 TRX for energy + 1.10 TRX for address activation, postpaid",
"data": {
"orderId": "1Hf9544a1508",
"paidTRX": 2.4,
"hash": "032bda8fa6911b42c15a6d8d30520dc22bcc4077972a1503b6a3fae491967eb4",
"delegateAddress": "TVnkj2jHKgmea8DVJFo2teD7rRSpH51bne",
"energy": 65000,
"activationHash": "259e1ab276114ae717a6f62d7d25eb1f89a2dccb637cbe41be626df3c2a78519",
"paymentMode": "postpaid",
"energyTRX": "1.300000",
"activationTRX": "1.100000",
"totalTRX": "2.400000"
}
}
}| Bidang | Deskripsi |
|---|---|
| paidTRX | Biaya layanan dalam TRX. Untuk akun pascabayar ini tidak dipotong dari deposit |
| paymentMode | postpaid |
| energyTRX / activationTRX / totalTRX | Jumlah pasti, 6 tempat desimal |
| quoteId, alt | Ada ketika pesanan dibuat dengan penawaran: ID penawaran dan jumlah penawaran |
| activationFinal | Ada dan bernilai false hanya jika jumlah aktivasi bersifat sementara; jumlah akhir muncul di faktur Anda |
Semua bidang lainnya sama seperti pesanan prabayar.
Batas kredit tercapai (402)
json
{
"detail": {
"code": 1004,
"msg": "Postpaid credit limit reached.",
"paymentMode": "postpaid",
"reason": "limit_reached"
}
}Pesanan tidak dieksekusi dan tidak ada yang ditagih. Pesanan baru akan diterima kembali setelah pembayaran Anda terdaftar atau batas Anda ditingkatkan.
Kode kesalahan pascabayar
| Kode | HTTP | Deskripsi |
|---|---|---|
10010 | 200 | Hasil pemeriksaan harga (test) |
10011 | 200 | Penawaran diterbitkan (freezePrice) |
1004 | 402 | Batas kredit pascabayar tercapai |
4100 | 400 | Permintaan tidak valid |
4101 | 400 | priceCurrency tidak didukung |
4102 | 400 | quoteId digabungkan dengan test atau freezePrice |
4103 | 409 | Penawaran sudah digunakan |
4104 | 409 | Penawaran kedaluwarsa |
4105 | 409 | Kunci idempotensi sudah digunakan untuk permintaan yang berbeda |
4106 | 404 | Penawaran tidak ditemukan |
4107 | 409 | Parameter pesanan berbeda dari penawaran |
4108 | 400 | Format quoteId tidak valid |
4109 | 422 | Tidak tersedia untuk sub-akun |
5032 | 503 | Harga sementara tidak tersedia |
5033 | 503 | Nilai tukar sementara tidak tersedia |
5034 | 503 | Penagihan sementara tidak tersedia — pesanan tidak diterima |
5036 | 503 | Pemeriksaan kredit sementara tidak tersedia — coba lagi nanti |
Untuk semua respons 4xx dan 503 di atas tidak ada yang dipesan dan tidak ada yang ditagih.
Catatan
- Energy dikirimkan secara instan setelah pesanan berhasil (biasanya dalam 0,5-10 detik)
- Batas waktu respons API: Maksimum 10 detik, biasanya merespons hingga 2 detik
- Aktivasi alamat: Jika alamat penerima belum aktif, Netts mengaktifkannya sesuai harga modal
- Keterlambatan aktivasi: Untuk alamat yang belum diaktifkan, respons API mungkin memerlukan waktu hingga 6 detik karena proses aktivasi
- Pesanan diproses 24/7 dengan failover penyedia otomatis
- Jumlah Energy minimum: 61.000 unit
- Jumlah Energy maksimum: 3.000.000 unit per pesanan
- Buffer Energy: +50 unit ditambahkan secara otomatis untuk kompensasi penyedia (bebas biaya)
- Hash transaksi: Bidang selalu ada tetapi mungkin kosong jika penyedia tidak langsung mengembalikannya. Untuk mengambil hash, panggil /apiv2/order_check paling cepat 1 menit setelah membuat pesanan
- Pemilihan penyedia: Otomatis berdasarkan biaya dan ketersediaan
- Format ID pesanan:
1H{request_id}untuk pelacakan terpadu - Harga: Dinamis berdasarkan waktu hari dan jumlah Energy
- Durasi: Tetap 1 jam (3600 detik)
- Pembatasan laju: 50 permintaan per detik per alamat IP