Appearance
GET /apiv2/pricing
Endpoint penetapan harga universal yang mengembalikan semua harga layanan dalam satu respons tunggal dengan periode waktu yang dinamis.
Harga dapat berubah selama pemenuhan
Harga yang dikembalikan oleh endpoint ini dapat berubah saat pesanan sedang diproses. Penyedia energy dapat menolak permintaan delegasi, dan dalam kasus ini Netts secara otomatis merutekan pesanan ke penyedia berikutnya yang tersedia. Netts berkomitmen tidak hanya untuk menawarkan harga paling kompetitif, tetapi juga untuk memastikan pasokan energy yang andal — oleh karena itu pesanan dapat dipenuhi pada harga yang lebih tinggi dari yang dikutip. Ini hanya berlaku untuk pesanan 300.000 unit energy ke atas.
Direkomendasikan
Ini adalah endpoint penetapan harga yang direkomendasikan. Endpoint ini menggantikan endpoint lama /apiv2/prices yang akan segera dihentikan.
URL Endpoint
GET https://netts.io/apiv2/pricingHeader Permintaan
| Header | Wajib | Deskripsi | Nilai |
|---|---|---|---|
| X-API-KEY | Ya | Kunci API Anda | string |
| X-Real-IP | Ya | Alamat IP dari whitelist | Alamat IP |
| X-Format | Tidak | Format respons (default: full JSON) | now, compact, short, short1h, count |
Parameter Kueri
| Parameter | Tipe | Default | Deskripsi |
|---|---|---|---|
| services | string | all | Filter layanan yang dipisahkan koma untuk disertakan |
Layanan yang Tersedia
| Layanan | Deskripsi |
|---|---|
energy_1h | Harga delegasi energy 1 jam |
energy_5m | Harga delegasi energy 5 menit |
host | Tarif delegasi Host energy |
aml | Harga pemeriksaan alamat AML |
bandwidth | Harga sewa Bandwidth — opsional (opt-in): dikembalikan hanya jika diminta secara eksplisit via ?services=bandwidth (bukan bagian dari respons default) |
Contoh Permintaan
cURL — Respons Lengkap
bash
curl -X GET https://netts.io/apiv2/pricing \
-H "X-API-KEY: your_api_key" \
-H "X-Real-IP: your_whitelisted_ip"cURL — Filter Berdasarkan Layanan
bash
# Only energy 1h prices
curl -X GET "https://netts.io/apiv2/pricing?services=energy_1h" \
-H "X-API-KEY: your_api_key" \
-H "X-Real-IP: your_whitelisted_ip"
# Energy 1h + AML
curl -X GET "https://netts.io/apiv2/pricing?services=energy_1h,aml" \
-H "X-API-KEY: your_api_key" \
-H "X-Real-IP: your_whitelisted_ip"
# Host prices only
curl -X GET "https://netts.io/apiv2/pricing?services=host" \
-H "X-API-KEY: your_api_key" \
-H "X-Real-IP: your_whitelisted_ip"
# Bandwidth rental prices (opt-in — must be requested explicitly)
curl -X GET "https://netts.io/apiv2/pricing?services=bandwidth" \
-H "X-API-KEY: your_api_key" \
-H "X-Real-IP: your_whitelisted_ip"Python
python
import requests
url = "https://netts.io/apiv2/pricing"
headers = {
"X-API-KEY": "your_api_key",
"X-Real-IP": "your_whitelisted_ip"
}
response = requests.get(url, headers=headers)
data = response.json()
if data.get("success"):
print(f"API version: {data['version']}")
print(f"TRX/USD rate: {data['data']['trx_rate_usd']}")
services = data["data"]["services"]
for svc_name, svc_data in services.items():
pricing_type = svc_data.get("pricing_type")
print(f"\n--- {svc_name} ({pricing_type}) ---")
if pricing_type == "periodic":
for period in svc_data["periods"]:
marker = " <-- current" if period["is_current"] else ""
print(f" {period['label']}: {period['price']} {svc_data['unit']}{marker}")
elif pricing_type == "flat_rates":
for rate, price in svc_data["rates"].items():
print(f" {rate}: {price} {svc_data['unit']}")
elif pricing_type == "provider_based":
for name, info in svc_data["providers"].items():
status = "available" if info["available"] else "unavailable"
print(f" {name}: {info['price']} {svc_data['unit']} - {status}")Python — Filter Layanan
python
params = {"services": "energy_1h,aml"}
response = requests.get(url, headers=headers, params=params)Struktur Respons
Bidang Tingkat Atas
| Bidang | Tipe | Deskripsi |
|---|---|---|
| success | boolean | true untuk permintaan yang berhasil |
| version | string | Versi API (misal "2.1") |
| timestamp | string | Waktu server dalam ISO 8601 UTC |
| data | object | Payload respons |
Bidang Data
| Bidang | Tipe | Deskripsi |
|---|---|---|
| data.trx_rate_usd | number | Nilai tukar TRX/USD saat ini |
| data.units_meta | object | Informasi konversi unit yang dapat dibaca mesin |
| data.services | object | Peta layanan yang diminta beserta data penetapan harga |
Meta Unit
Memungkinkan klien untuk mengonversi antar unit secara terprogram:
json
{
"units_meta": {
"sun": {"base": "trx", "multiplier": 1000000},
"trx": {"base": "trx", "multiplier": 1},
"usdt": {"base": "usdt", "multiplier": 1}
}
}Untuk mengonversi dari SUN ke TRX: trx_price = sun_price / units_meta.sun.multiplier
Bidang Umum Layanan
Setiap layanan menyertakan bidang-bidang berikut:
| Bidang | Tipe | Deskripsi |
|---|---|---|
| unit | string | Unit harga (sun, trx, usdt) |
| pricing_type | string | Cara mem-parsing layanan ini (lihat di bawah) |
| description | string | Deskripsi yang dapat dibaca manusia |
| cache_ttl | integer | Seberapa sering data ini diperbarui (detik) |
Tipe Penetapan Harga
Bidang pricing_type memberi tahu klien cara mem-parsing setiap layanan:
| Tipe | Struktur | Digunakan oleh |
|---|---|---|
periodic | Larik periods[] dengan harga berbasis waktu | energy_1h, energy_5m |
flat_rates | Objek rates{} dengan kunci tarif bernama | host |
provider_based | Objek providers{} dengan data penyedia | aml |
tiered_by_amount_and_period | tiers[] berdasarkan rentang jumlah, masing-masing dengan periods[] | bandwidth |
Layanan: energy_1h / energy_5m
pricing_type: periodic
| Bidang | Tipe | Deskripsi |
|---|---|---|
| current_period | string | Slug dari periode yang sedang aktif |
| periods[] | array | Semua periode penetapan harga (dinamis, dimuat dari DB) |
| periods[].id | string | Pengenal unik periode (slug) |
| periods[].label | string | Nama periode yang dapat dibaca manusia |
| periods[].start | string | Waktu mulai periode (HH:MM UTC) |
| periods[].end | string | Waktu berakhir periode (HH:MM UTC) |
| periods[].is_current | boolean | Apakah periode ini sedang aktif |
| periods[].price | integer | Harga per unit energy dalam SUN |
| periods[].tiers | array|null | Tingkatan harga berdasarkan volume (lihat Tingkatan) |
Periode dinamis
Jumlah periode, rentang waktu, label, dan harganya bersifat dinamis dan dikelola di sisi server. Jangan melakukan hardcode pada ID atau jumlah periode. Selalu lakukan iterasi pada larik periods.
Layanan: host
pricing_type: flat_rates
| Bidang | Tipe | Deskripsi |
|---|---|---|
| rates.standard_65k | number | Tarif standar untuk 65k energy (TRX) |
| rates.standard_131k_initial | number | Tarif standar untuk 131k energy, aktivasi awal (TRX) |
| rates.frequent_65k | number | Tarif sering (frequent) untuk 65k energy (TRX) |
| rates.frequent_131k | number | Tarif sering (frequent) untuk 131k energy (TRX) |
Layanan: aml
pricing_type: provider_based
| Bidang | Tipe | Deskripsi |
|---|---|---|
| providers | object | Peta penyedia AML (dinamis, dapat berubah) |
| providers[name].price | number | Harga pemeriksaan dalam USDT |
| providers[name].price_trx | number | Harga pemeriksaan dikonversi ke TRX pada kurs saat ini |
| providers[name].available | boolean | Apakah penyedia memiliki kuota yang tersedia |
Penyedia dinamis
Penyedia AML dimuat dari basis data. Penyedia baru dapat muncul atau yang sudah ada dapat menjadi tidak tersedia. Selalu lakukan iterasi pada objek providers.
Layanan: bandwidth
pricing_type: tiered_by_amount_and_period
Pilihan (Opt-in) & akses
Penetapan harga Bandwidth dikembalikan hanya ketika diminta secara eksplisit melalui ?services=bandwidth — ini bukan bagian dari respons default. Endpoint sewa Bandwidth itu sendiri tersedia berdasarkan permintaan; hubungi tim dukungan untuk mendapatkan akses. Lihat Sewa Bandwidth.
Harga sewa Bandwidth bergantung pada jumlah pesanan (tingkatan unit), periode sewa (misal 5m / 1h), jendela waktu hari (UTC), dan hari dalam seminggu. Harga dasar dalam SUN per unit; di atas harga dasar, biaya tambahan tetap (dalam TRX) dapat berlaku — semua nilai dikembalikan dalam respons.
Respons menyediakan tampilan praktis (tiers — harga untuk jendela/hari saat ini) dan kisi lengkap (windows + schedule — setiap jendela di setiap hari kerja).
Format adaptif — jangan lakukan hardcode
Kisi penetapan harga sepenuhnya didorong oleh data dan dapat berubah sewaktu-waktu: jumlah jendela waktu, label-nya, waktu mulai/selesai-nya, serangkaian periode sewa (periode baru dapat ditambahkan atau dihapus), tingkatan jumlah, rincian hari dalam seminggu, dan harga itu sendiri. Klien harus melakukan iterasi pada larik yang dikembalikan (windows, schedule, tiers, periods) dan mencocokkan berdasarkan nilai — jangan pernah mengasumsikan jumlah tetap, label tetap, waktu tetap, atau id periode tetap. Kode yang ditulis dengan cara ini akan tetap berfungsi ketika jadwal berubah.
| Bidang | Tipe | Deskripsi |
|---|---|---|
| unit | string | sun_per_unit |
| window | string | Label jendela waktu hari saat ini (UTC) |
| current_day_of_week | integer | Hari kerja saat ini, ISO 1=Sen … 7=Min (UTC) |
| tiers[] | array | Tingkatan jumlah untuk jendela/hari saat ini (kemudahan; bentuk yang sama seperti di dalam schedule) |
| windows[] | array | Direktori semua jendela waktu hari (dapat bertambah/berkurang/bergeser) |
| windows[].label | string | Label jendela |
| windows[].start / .end | string | Waktu mulai/selesai jendela HH:MM UTC (jendela dapat melewati tengah malam, yaitu start > end) |
| schedule[] | array | Kisi lengkap — satu entri per (hari dalam seminggu × jendela) |
| schedule[].day_of_week | integer | Hari kerja ISO 1…7 |
| schedule[].window | string | Label jendela (cocok dengan windows[].label) |
| schedule[].period_start / .period_end | string | HH:MM UTC |
| schedule[].is_current | boolean | true untuk segmen yang aktif saat ini |
| schedule[].tiers[] | array | Tingkatan jumlah untuk segmen ini |
| tiers[].amount_min | integer | Batas bawah tingkatan (inklusif) |
| tiers[].amount_max | integer|null | Batas atas tingkatan (eksklusif). null = tidak terbatas |
| tiers[].periods[] | array | Harga per periode sewa di dalam tingkatan |
| tiers[].periods[].id | string | ID periode sewa (misal 5m, 1h) — dapat berubah/bertambah |
| tiers[].periods[].rental_seconds | integer | Durasi periode dalam detik |
| tiers[].periods[].price | integer | Harga per unit Bandwidth dalam SUN |
| surcharges | object | Tambahan tetap pada harga klien (TRX) — lihat di bawah |
| limits | object | Batasan pesanan: min_units, max_units |
Biaya Tambahan
| Bidang | Tipe | Deskripsi |
|---|---|---|
| surcharges.small_order_threshold_units | integer | Pesanan dengan amount di bawah nilai ini dikenakan biaya tambahan pesanan kecil |
| surcharges.small_order_surcharge_trx | number | Ditambahkan (TRX) untuk pesanan delegasi kecil — kompensasi untuk delegasi on-chain + reclaim |
| surcharges.trx_send_surcharge_trx | number | Ditambahkan (TRX) saat pesanan dipenuhi dengan mengirim TRX — kompensasi untuk transfer TRX |
Contoh Respons
json
{
"bandwidth": {
"unit": "sun_per_unit",
"pricing_type": "tiered_by_amount_and_period",
"description": "Bandwidth delegation rental",
"cache_ttl": 30,
"window": "<current window label>",
"current_day_of_week": 7,
"tiers": [
{
"amount_min": 400,
"amount_max": 1000,
"periods": [
{"id": "5m", "rental_seconds": 300, "price": "<price_sun>"},
{"id": "1h", "rental_seconds": 3600, "price": "<price_sun>"}
]
},
{"amount_min": 1000, "amount_max": 3000, "periods": ["..."]},
{"amount_min": 3000, "amount_max": null, "periods": ["..."]}
],
"windows": [
{"label": "<window label>", "start": "01:00", "end": "09:00"},
{"label": "<window label>", "start": "14:00", "end": "00:00"}
],
"schedule": [
{
"day_of_week": 1,
"window": "<window label>",
"period_start": "01:00",
"period_end": "09:00",
"is_current": false,
"tiers": [
{"amount_min": 400, "amount_max": 1000, "periods": [
{"id": "5m", "rental_seconds": 300, "price": "<price_sun>"},
{"id": "1h", "rental_seconds": 3600, "price": "<price_sun>"}
]}
]
}
],
"surcharges": {
"small_order_threshold_units": 1000,
"small_order_surcharge_trx": "<trx>",
"trx_send_surcharge_trx": "<trx>"
},
"limits": {"min_units": 400, "max_units": 5000}
}
}schedule berisi satu entri untuk setiap kombinasi (hari kerja × jendela) — lakukan iterasi untuk merender kalender harga penuh. Tepat satu entri memiliki is_current: true.
Logika Klien (menghitung harga pesanan)
Gunakan tiers untuk "harga saat ini". Untuk mencari harga pada waktu lain, pilih entri schedule yang cocok berdasarkan hari kerja + jendela yang mana rentang [period_start, period_end) memuat waktu tersebut (ingat bahwa jendela dapat melintasi tengah malam ketika start > end), kemudian gunakan tiers miliknya.
# price for the current moment:
for tier in bandwidth.tiers:
if tier.amount_min <= amount < (tier.amount_max or infinity):
for p in tier.periods:
if p.id == requested_period: # match by value, not by index
base_trx = (p.price / units_meta.sun.multiplier) * amount
if amount < surcharges.small_order_threshold_units:
base_trx += surcharges.small_order_surcharge_trx # delegation orders
# TRX-send fulfillment branch instead:
# trx_branch_trx = base_trx_for_smallest_tier_shortest_period + surcharges.trx_send_surcharge_trx
# price for an arbitrary weekday/time: same logic, but first select the schedule[] entry
# where day_of_week matches and the time falls in [period_start, period_end).Terpusat & dinamis
Harga Bandwidth, jendela, rincian hari kerja, dan biaya tambahan dikelola di sisi server (DB) dan dapat berubah. Selalu lakukan iterasi pada windows, schedule, tiers, dan periods dari respons serta cocokkan berdasarkan nilai — jangan lakukan hardcode pada jumlah, label, waktu, atau id periode. Markup pengguna SUB tidak berlaku untuk Bandwidth.
Tingkatan
Saat ini tiers bernilai null untuk semua periode. Ketika penetapan harga berbasis volume diaktifkan, bidang ini akan berisi larik objek tingkatan:
json
{
"tiers": [
{
"min_energy": 0,
"max_energy": 64999,
"price": "<price_sun>",
"label": "standard"
},
{
"min_energy": 65000,
"max_energy": 130999,
"price": "<price_sun>",
"label": "65k"
},
{
"min_energy": 131000,
"max_energy": 131000,
"price": "<price_sun>",
"label": "131k"
},
{
"min_energy": 131001,
"max_energy": null,
"price": "<price_sun>",
"label": "bulk"
}
]
}Skema Tingkatan
| Bidang | Tipe | Deskripsi |
|---|---|---|
| min_energy | integer | Jumlah minimum energy untuk tingkatan ini (inklusif) |
| max_energy | integer|null | Jumlah maksimum energy untuk tingkatan ini (inklusif). null = tidak terbatas |
| price | integer | Harga per unit energy dalam SUN untuk tingkatan ini |
| label | string | Pengenal tingkatan |
Logika Klien
if tiers != null:
find the tier where min_energy <= order_amount <= max_energy
use that tier's price
else:
use the flat price field for all order amountsFormat Respons Ringkas
Gunakan header X-Format untuk mendapatkan respons teks ringkas. Format ini mengembalikan harga periode aktif saat ini dari energy_1h.
X-Format: now / compact / short
bash
curl -H "X-API-KEY: your_key" -H "X-Format: now" https://netts.io/apiv2/pricingtext
<Period>: price=<N> sun, 65k=<X.XXX> TRX (<X.XX>$), 131k=<X.XXX> TRX (<X.XX>$), 1m=<X.XXX> TRX (<X.XX>$)X-Format: short1h
Sama tetapi tanpa label periode dan harga per unit.
bash
curl -H "X-API-KEY: your_key" -H "X-Format: short1h" https://netts.io/apiv2/pricingtext
65k=<X.XXX> TRX (<X.XX>$), 131k=<X.XXX> TRX (<X.XX>$), 1m=<X.XXX> TRX (<X.XX>$)X-Format: count
Harga pesanan massal untuk 1, 2, 3, 5, 10, 20 pesanan.
bash
curl -H "X-API-KEY: your_key" -H "X-Format: count" https://netts.io/apiv2/pricingtext
1-<X.XXX> TRX (<X.XX>$), 2-<X.XXX> TRX (<X.XX>$), ...Rumus Perhitungan
TRX cost = (price_sun / units_meta.sun.multiplier) x energy_amount
USD cost = TRX_cost x trx_rate_usdMarkup Pengguna SUB
Pengguna SUB secara otomatis menerima harga dengan markup induknya yang telah diterapkan. API selalu mengembalikan harga akhir untuk pengguna yang terautentikasi — tidak diperlukan perhitungan di sisi klien.
Respons Kesalahan
Kesalahan dapat berasal dari dua lapisan dengan format yang berbeda. Klien Anda harus menangani keduanya.
Kesalahan Aplikasi (dari API)
Kesalahan tingkat aplikasi menggunakan format standar success/error:
Layanan Tidak Valid (400)
json
{
"success": false,
"error": {
"code": 4002,
"message": "Unknown services: invalid_service"
}
}Kesalahan Autentikasi (401)
Dikembalikan oleh aplikasi ketika kunci API hilang atau IP tidak masuk dalam whitelist:
json
{
"detail": {
"code": -1,
"msg": "Invalid API key or IP not in whitelist"
}
}Format berbeda
Kesalahan autentikasi menggunakan format bawaan FastAPI detail, bukan struktur success/error. Ini terjadi karena kesalahan dipicu sebelum permintaan mencapai logika aplikasi.
Pengguna Tidak Ditemukan (404)
json
{
"detail": {
"code": -1,
"msg": "User not found"
}
}Kesalahan Server Internal (500)
json
{
"success": false,
"error": {
"code": 5001,
"message": "Failed to retrieve pricing data"
}
}Kesalahan Gateway (dari Kong)
Kesalahan ini dikembalikan oleh API gateway sebelum permintaan mencapai aplikasi. Kesalahan ini menggunakan format Kong sendiri:
Batas Kecepatan Terlampaui (429)
json
{
"message": "API rate limit exceeded"
}Gateway Waktu Habis (504)
json
{
"message": "An invalid response was received from the upstream server"
}Referensi Kode Kesalahan
| Kode | Deskripsi | Status HTTP | Sumber |
|---|---|---|---|
-1 | Kunci API tidak disediakan | 401 | App |
-1 | Kunci API tidak valid atau IP tidak ada dalam whitelist | 401 | App |
-1 | Pengguna tidak ditemukan | 404 | App |
4002 | Layanan tidak dikenal dalam parameter ?services= | 400 | App |
5000 | Kesalahan server internal | 500 | App |
5001 | Gagal mengambil data harga | 500 | App |
5002 | Data harga tidak tersedia untuk format ringkas | 500 | App |
- | Batas kecepatan API terlampaui | 429 | Kong |
Penanganan Kesalahan Klien yang Direkomendasikan
python
response = requests.get(url, headers=headers)
data = response.json()
if response.status_code == 200 and data.get("success"):
# Success — process data
services = data["data"]["services"]
elif response.status_code == 429:
# Kong rate limit — back off and retry
retry_after = response.headers.get("Retry-After", "60")
time.sleep(int(retry_after))
elif "detail" in data:
# FastAPI auth/validation error
detail = data["detail"]
if isinstance(detail, dict):
print(f"Error {detail.get('code')}: {detail.get('msg')}")
else:
print(f"Error: {detail}")
elif "error" in data:
# Application error
err = data["error"]
print(f"Error {err.get('code')}: {err.get('message')}")
else:
print(f"Unexpected response: {response.status_code}")Migrasi dari /apiv2/prices
| Aspek | /apiv2/prices (lama) | /apiv2/pricing (baru) |
|---|---|---|
| Periode | 5 tetap | Dinamis dari DB |
| Tingkatan harga | 3 di-hardcode | Harga tunggal + tiers masa depan |
| Variasi durasi | Tidak tersedia | energy_5m |
| Harga AML | Endpoint terpisah | Disertakan melalui ?services=aml |
| Harga Host | Tercampur dalam respons | Layanan host terpisah |
| Pemfilteran layanan | Tidak tersedia | Parameter ?services= |
| Konversi unit | Tidak terdokumentasi | units_meta dalam respons |
| Informasi cache | Tidak terdokumentasi | cache_ttl per layanan |
| Format respons | {"status": "success", ...} | {"success": true, "version": "2.1", "data": {...}} |
Batas Kecepatan
Batas kecepatan yang sama seperti /apiv2/prices berlaku (dikonfigurasi di Kong gateway).
Catatan
- Semua harga energy dalam SUN — gunakan
units_metauntuk konversi - Harga Host dalam TRX
- Harga AML dalam USDT dengan konversi TRX yang disertakan
- Semua waktu dalam UTC
- Gunakan
cache_ttlper layanan untuk mengetahui seberapa sering data diperbarui - Gunakan
pricing_typeuntuk menentukan cara mem-parsing setiap layanan - Periode, penyedia, tarif, dan semua nilai bersifat dinamis — jangan meng-hardcode-nya
- Penetapan harga Bandwidth bersifat opsional (opt-in) (
?services=bandwidth), menggunakantiered_by_amount_and_perioddengansurcharges, dan tidak dikenakan markup pengguna SUB