POST /apiv2/time/add
เพิ่มที่อยู่ TRON ไปยัง Host Mode และลงทะเบียน callback URL สำหรับการแจ้งเตือนการมอบสิทธิ์ (delegation) และการหยุดชั่วคราว (ไม่บังคับ)
URL ของ Endpoint
POST https://netts.io/apiv2/time/addการยืนยันตัวตน
ระบุ API key ของคุณในเนื้อหาคำขอ (api_key) หรือในส่วนหัว X-API-KEY หมายเลข IP ของคำขอต้องอยู่ใน whitelist ที่กำหนดค่าไว้สำหรับ API key ของคุณ
เนื้อหาคำขอ
{
"api_key": "your_api_key",
"address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"callback_url": "https://your-server.com/webhook",
"infinity": true
}พารามิเตอร์
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
| api_key | string | ใช่* | API key นอกจากนี้ยังสามารถส่งในส่วนหัว X-API-KEY ได้ |
| address | string | ใช่ | ที่อยู่ TRON (TRC-20) ต้องตรงกับ ^T[1-9A-HJ-NP-Za-km-z]{33}$ (ขึ้นต้นด้วย T, ความยาว 34 ตัวอักษร) |
| callback_url | string | ไม่ | URL แบบ HTTP/HTTPS สาธารณะสำหรับแจ้งเตือนเมื่อมีการมอบสิทธิ์ Energy ให้กับที่อยู่ และเมื่อ Host Mode สำหรับที่อยู่นั้นถูกปิดการทำงาน สูงสุด 2048 ตัวอักษร |
| infinity | boolean | ไม่ | true — เปลี่ยนที่อยู่นั้นเข้าสู่โหมด infinity ทันทีด้วย ช่วยประหยัดการเรียกแยกไปยัง /apiv2/time/infinitystart ค่าเริ่มต้นคือ false |
* จำเป็นต้องมีในเนื้อหาคำขอ เว้นแต่จะใช้ส่วนหัว X-API-KEY
การตรวจสอบความถูกต้องของ callback_url: ต้องเป็น http/https และเป็นโฮสต์สาธารณะเท่านั้น (localhost, ช่วงส่วนตัวของ RFC1918, link-local 169.254.0.0/16, ที่อยู่ IPv6 private/link-local, ที่อยู่ reserved และ multicast จะถูกปฏิเสธ) และมีความยาวไม่เกิน 2048 ตัวอักษร
พฤติกรรม
- หากเป็นที่อยู่ใหม่ ที่อยู่นั้นจะถูกเพิ่มไปยัง Host Mode โดยมีสถานะ ไม่ใช้งาน (
status = 0,cycle_set = 0) เปิดใช้งานในภายหลังด้วย/apiv2/time/orderหรือ/apiv2/time/infinitystart - หากมีที่อยู่นี้อยู่แล้วภายใต้บัญชีของคุณ การเรียกนี้จะอัปเดต callback URL ของที่อยู่นั้น
- หากมีการระบุ
callback_urlระบบจะจัดเก็บ (หรืออัปเดต) สำหรับที่อยู่นั้น
infinity
เมื่อระบุ "infinity": true ที่อยู่จะถูกเพิ่ม และ เปิดใช้งานในโหมด infinity ภายในการเรียกเพียงครั้งเดียว — ผลลัพธ์เดียวกันกับการเรียก /apiv2/time/add แล้วตามด้วย /apiv2/time/infinitystart การคิดค่าบริการจะเหมือนกับการเรียกแยกต่างหากทุกประการ: จะไม่มีการเรียกเก็บเงิน ณ จุดนี้ และรอบจะถูกเรียกเก็บทีละรอบเมื่อมีการมอบสิทธิ์ Energy ดูที่ Host Mode → Cycles and Pricing
การเพิ่มที่อยู่และการเปิดใช้งานเป็นสองขั้นตอนที่แยกจากกัน และรับประกันเฉพาะขั้นตอนแรกเท่านั้น การตอบกลับจะรายงานผลของการเพิ่ม หากเพิ่มที่อยู่สำเร็จแต่ไม่สามารถเปิดใช้งานได้ การเรียกจะยังคงส่งคืน code: 0 พร้อมข้อความปกติ — ที่อยู่จะถูกปล่อยให้อยู่ในสถานะไม่ใช้งานตามเดิม เหมือนกับที่คุณไม่ได้ส่งแฟล็กนี้มา การเปิดใช้งานจะถูกข้ามเมื่อ:
- ยอดคงเหลือของคุณไม่ครอบคลุมหนึ่งรอบในราคาปัจจุบัน
- ที่อยู่นั้นเปิดใช้งานอยู่แล้ว
- ที่อยู่นั้นมีคำสั่งซื้อที่เปิดอยู่แล้ว
การตอบกลับจะเหมือนกันทั้งกรณีที่มีและไม่มีแฟล็ก — ไม่มีฟิลด์เพิ่มเติม ไม่มีรหัสข้อผิดพลาดเพิ่มเติม และจะไม่บอกว่าโหมด infinity ได้เปิดใช้งานจริงหรือไม่ ยืนยันได้ด้วย Time Status: ที่อยู่จะรายงาน status: "active" และ mode: "infinity" และ order id จะอยู่ในคำตอบนั้น อย่าใช้ code: 0 จาก endpoint นี้เป็นหลักฐานว่าโหมดกำลังทำงานอยู่
ตัวอย่างคำขอ
cURL
curl -X POST https://netts.io/apiv2/time/add \
-H "Content-Type: application/json" \
-d '{
"api_key": "YOUR_API_KEY_HERE",
"address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"callback_url": "https://your-server.com/webhook"
}'Python
import requests
url = "https://netts.io/apiv2/time/add"
data = {
"api_key": "YOUR_API_KEY_HERE",
"address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"callback_url": "https://your-server.com/webhook", # ไม่บังคับ
# "infinity": True, # ไม่บังคับ: เปลี่ยนที่อยู่เข้าสู่โหมด infinity ทันทีด้วย
}
resp = requests.post(url, json=data, timeout=30)
result = resp.json()
if result["code"] == 0:
print("Added:", result["data"]["address"])
else:
print("Error:", result["msg"])Node.js
const axios = require('axios');
const data = {
api_key: 'YOUR_API_KEY_HERE',
address: 'TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE',
// callback_url: 'https://your-server.com/webhook', // ไม่บังคับ
// infinity: true, // ไม่บังคับ: เปลี่ยนที่อยู่เข้าสู่โหมด infinity ทันทีด้วย
};
axios.post('https://netts.io/apiv2/time/add', data)
.then(({ data: result }) => {
if (result.code === 0) console.log('Added:', result.data.address);
else console.error('Error:', result.msg);
})
.catch(err => console.error('Request failed:', err.response?.data || err.message));การตอบกลับ
สำเร็จ (ที่อยู่ใหม่)
{
"code": 0,
"msg": "Address added to Host Mode successfully",
"data": {
"address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"callback_url": "https://your-server.com/webhook",
"timestamp": "2026-07-13T05:30:15.123456"
}
}สำเร็จ (อัปเดต callback URL สำหรับที่อยู่ที่มีอยู่แล้ว)
{
"code": 0,
"msg": "Address callback URL updated successfully",
"data": {
"address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"callback_url": "https://new-webhook.com/endpoint",
"timestamp": "2026-07-13T05:35:20.789012"
}
}ฟิลด์การตอบกลับ
| ฟิลด์ | ชนิด | คำอธิบาย |
|---|---|---|
| code | integer | 0 = สำเร็จ, ค่าลบ = ข้อผิดพลาด |
| msg | string | ข้อความที่มนุษย์อ่านได้ |
| data.address | string | ที่อยู่ที่ถูกเพิ่ม/อัปเดต |
| data.callback_url | string | null | callback URL ที่ลงทะเบียนไว้ (null หากไม่มี) |
| data.timestamp | string | การประทับเวลาแบบ ISO ของการทำงาน |
การตอบกลับข้อผิดพลาด
ข้อผิดพลาดทั้งหมดใช้ code = -1 และอธิบายปัญหาใน msg:
| msg | สาเหตุ |
|---|---|
API key required in X-API-KEY header or request body | ไม่ได้ระบุ API key |
Invalid API key or IP not in whitelist | การยืนยันตัวตนล้มเหลว |
Invalid TRC-20 address format | ที่อยู่ไม่ตรงกับรูปแบบที่กำหนด |
Invalid callback URL. Only public HTTP/HTTPS URLs are allowed | Callback URL ถูกปฏิเสธจากการตรวจสอบความถูกต้อง |
Address belongs to another user | ที่อยู่นี้ถูกลงทะเบียนไว้ภายใต้บัญชีอื่น |
Database error adding/updating address | ข้อผิดพลาดชั่วคราวฝั่งเซิร์ฟเวอร์ — ให้ลองใหม่ |
Internal server error | ข้อผิดพลาดที่ไม่คาดคิด — ให้ลองใหม่หรือติดต่อฝ่ายสนับสนุน |
{ "code": -1, "msg": "Invalid API key or IP not in whitelist", "data": null }รหัสสถานะ HTTP
ข้อผิดพลาดของ endpoint จะถูกส่งคืนพร้อมกับ HTTP 200 และ code ที่เป็นค่าลบ — ให้ตรวจสอบ code ไม่ใช่สถานะ HTTP เนื้อหาข้อผิดพลาดจะมี "data": null เสมอ
ข้อผิดพลาดบางอย่างจะถูกส่งคืน ก่อนที่ คำขอจะไปถึง endpoint ซึ่งจะใช้สถานะที่ไม่ใช่ 200 และรูปแบบเนื้อหาที่แตกต่างออกไป:
| HTTP | เนื้อหา | สาเหตุ |
|---|---|---|
| 402 | {"detail": {"code": 1004, "msg": "Insufficient funds. Minimum balance is 4 TRX. Please top up your account."}} | ยอดคงเหลือในบัญชีต่ำเกินไป |
| 403 | {"detail": {"code": 1005, "msg": "API key is blocked. Contact support."}} | API key ถูกระงับ — ติดต่อฝ่ายสนับสนุน |
| 422 | {"detail": [ … ]} | เนื้อหาคำขอล้มเหลวในการตรวจสอบความถูกต้อง: ฟิลด์ที่จำเป็นขาดหายไปหรือมีชนิดไม่ถูกต้อง โปรดทราบว่าไม่มีฟิลด์ code ในการตอบกลับนี้ |
ที่อยู่ปลายทางไม่ได้รับอนุญาต (403)
ที่อยู่จะได้รับการตรวจสอบก่อนที่จะถูกเพิ่ม หากไม่อนุญาตให้มอบสิทธิ์ทรัพยากรไปยังที่อยู่นั้น คำขอจะถูกปฏิเสธด้วย HTTP 403 และไม่มีการบันทึกข้อมูลใด ๆ — ที่อยู่จะไม่ถูกเพิ่มและไม่ถูกเปิดใช้งาน เนื้อหาจะใช้รูปแบบ detail:
| code | msg | ความหมาย |
|---|---|---|
| 1006 | Address is blocked. Contact support. | ที่อยู่ถูกระงับ |
| 1007 | Energy rental to smart contracts is not supported. | ที่อยู่เป็น smart contract (ที่อยู่กระเป๋าเงิน GasFree ก็เป็น smart contract เช่นกัน) |
| 1010 | Resource delegation to this address is not available. | การมอบสิทธิ์ทรัพยากรไปยังที่อยู่นี้ไม่พร้อมใช้งาน |
| 1011 | This address is frozen and cannot receive resource delegation. | ที่อยู่ถูกระงับการทำงาน (frozen) และไม่สามารถรับการมอบสิทธิ์ทรัพยากรได้ |
{ "detail": { "code": 1007, "msg": "Energy rental to smart contracts is not supported." } }Callbacks (webhooks)
หากคุณลงทะเบียน callback_url ไว้ ระบบจะเรียกใช้ URL นั้นในแต่ละครั้งที่มีการ มอบสิทธิ์ Energy ไปยังที่อยู่ (กล่าวคือ หนึ่งครั้งต่อรอบการมอบสิทธิ์ตามที่ได้รับการประมวลผล) และหนึ่งครั้งในแต่ละครั้งที่ Host Mode สำหรับที่อยู่นั้นถูก ปิดการทำงาน — ดูที่ เหตุการณ์การหยุดโฮสต์ชั่วคราว
รูปแบบคำขอ
ระบบจะส่งคำขอ HTTP GET พร้อมพารามิเตอร์คิวรี:
รอบที่เกิดขึ้นจากการโอน USDT — มี energy_used แสดงอยู่:
GET https://your-server.com/webhook?address=TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE&order_id=T149936&hash=97b4eb0257088aefcb286229aa42ec750f27554390dd4e186f55efe273666577&balance_after=142.3500&idle_cycle=0&energy_used=65k&charged=2.0000รอบที่ไม่มีการโอนก่อนหน้า — ละเว้น energy_used:
GET https://your-server.com/webhook?address=TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE&order_id=T149937&hash=97b4eb0257088aefcb286229aa42ec750f27554390dd4e186f55efe273666577&balance_after=138.3500&idle_cycle=0&charged=4.0000| พารามิเตอร์ | คำอธิบาย |
|---|---|
| address | ที่อยู่ TRON ที่ได้รับการมอบสิทธิ์ Energy |
| order_id | ตัวระบุการมอบสิทธิ์ (T + รหัสการมอบสิทธิ์ภายใน) — ไม่ซ้ำกันในแต่ละการมอบสิทธิ์ |
| hash | แฮชธุรกรรมบนเชน (on-chain transaction hash) ของการมอบสิทธิ์ Energy |
| balance_after | ยอดคงเหลือในบัญชีของคุณในหน่วย TRX ทันทีหลังจากการเรียกเก็บเงินนี้ (สแนปช็อต ณ เวลาที่เรียกเก็บเงิน ซึ่งอาจเปลี่ยนแปลงไปแล้วในตอนที่ callback มาถึง) |
| idle_cycle | 1 — การมอบสิทธิ์นี้ออกหลังจากไม่มีการโอนเป็นเวลา 24 ชั่วโมง (การมอบสิทธิ์ซ้ำเมื่อไม่ได้ใช้งาน), 0 — รอบปกติที่เกิดจากการโอนหรือการเปิดใช้งานของคุณ |
| energy_used | แถบอัตราค่าบริการของ Energy ที่ใช้ไปจากการโอนที่ทำให้เกิดรอบนี้: 65k (65,000 Energy หรือน้อยกว่า → 2 TRX) หรือ 131k (มากกว่า 65,000 → 4 TRX) ไม่บังคับ — คีย์นี้จะถูกละเว้นออกจากสตริงคิวรีทั้งหมด (ไม่ได้ส่งเป็นค่าว่าง) เมื่อไม่มีการโอนก่อนหน้าให้วัดผล: การมอบสิทธิ์ครั้งแรกของการเปิดใช้งาน, ทุกการมอบสิทธิ์ซ้ำเมื่อไม่ได้ใช้งาน และที่อยู่ที่ยังไม่มีประวัติการใช้งาน ทั้งหมดนี้จะถูกคิดค่าบริการในอัตรา 4 TRX |
| charged | จำนวนเงินในหน่วย TRX ที่เรียกเก็บสำหรับรอบนี้ — 2.0000 หรือ 4.0000 ตรงกับอัตราค่าบริการใน energy_used ปรากฏอยู่เสมอ รวมถึงเมื่อละเว้น energy_used ด้วย ดูที่ Host Mode → Cycles and Pricing |
ใช้ order_id และ hash เพื่อแยกความแตกต่างระหว่างการมอบสิทธิ์แต่ละรายการและเพื่อกระทบยอดกับบันทึกของคุณเอง — callback สองรายการสำหรับที่อยู่เดียวกันจะแตกต่างกันตามค่าเหล่านี้ ใช้ charged เพื่อติดตามการใช้จ่ายต่อรอบโดยไม่ต้องทำโพลล์ /apiv2/time/status และใช้ energy_used เพื่อดูว่าการโอนก่อนหน้าตกอยู่ในอัตราค่าบริการใด อ่าน energy_used ในฐานะพารามิเตอร์ที่ไม่บังคับ — คีย์ที่ขาดหายไปหมายถึง "ไม่มีการโอนให้วัดผล" ไม่ใช่ข้อผิดพลาด และอย่าตั้งสมมติฐานค่าเริ่มต้นสำหรับคีย์นี้
เหตุการณ์การหยุดโฮสต์ชั่วคราว
callback_url เดียวกันนี้จะถูกเรียกเมื่อ Host Mode สำหรับที่อยู่นั้นถูก ปิดการทำงาน (กลายเป็นไม่ใช้งาน) ไม่ว่าจะด้วยเหตุผลใดก็ตาม:
GET https://your-server.com/webhook?event=host_paused&address=TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE&reason=idle&paused_at=2026-09-13T11:16:58Z&balance=418.0000| พารามิเตอร์ | คำอธิบาย |
|---|---|
| event | เป็น host_paused เสมอสำหรับการแจ้งเตือนนี้ |
| address | ที่อยู่ TRON ที่ Host Mode ถูกปิดการทำงาน |
| reason | สาเหตุที่โหมดถูกปิดการทำงาน — ดูตารางด้านล่าง |
| paused_at | เวลาที่โหมดถูกปิดการทำงาน, ISO-8601 UTC |
| balance | ยอดคงเหลือในบัญชีของคุณในหน่วย TRX ณ ขณะนั้น ทศนิยม 4 ตำแหน่ง |
| reason | ความหมาย |
|---|---|
idle | ไม่ได้ใช้งาน 2 วันติดต่อกัน — สองรอบ 24 ชั่วโมงปิดลงโดยไม่มีการโอน (ดูที่ Host Mode → Idle shutdown) |
cycles_exhausted | รอบที่สั่งซื้อทั้งหมดถูกใช้หมดแล้ว |
no_balance | ยอดคงเหลือของคุณไม่เพียงพอสำหรับการเรียกเก็บเงินหนึ่งรอบหรือการเติมเงิน ขั้นต่ำรายวัน |
stopped | โหมดถูกหยุดด้วย /apiv2/time/stop หรือถูกปิดการทำงานด้วยเหตุผลอื่นใด |
วิธีแยกความแตกต่างระหว่างการแจ้งเตือนทั้งสองแบบ: เฉพาะการแจ้งเตือนการหยุดชั่วคราวเท่านั้นที่มีพารามิเตอร์ event; เฉพาะการแจ้งเตือนการมอบสิทธิ์เท่านั้นที่มี order_id และ hash รูปแบบการแจ้งเตือนการมอบสิทธิ์จะไม่มีการเปลี่ยนแปลง
หลังจากการหยุดชั่วคราว ที่อยู่จะยังคงอยู่ใน Host Mode พร้อมกับ callback URL ของมัน เปิดใช้งานอีกครั้งด้วย /apiv2/time/order หรือ /apiv2/time/infinitystart การจัดส่งทำงานในลักษณะเดียวกับการแจ้งเตือนการมอบสิทธิ์
ตัวอย่างตัวจัดการ (Python / Flask)
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook', methods=['GET'])
def energy_delegation_webhook():
address = request.args.get('address')
order_id = request.args.get('order_id')
tx_hash = request.args.get('hash')
charged = request.args.get('charged') # TRX ที่เรียกเก็บสำหรับรอบนี้
energy_used = request.args.get('energy_used') # '65k' | '131k' | None (คีย์อาจไม่มีอยู่)
if not address:
return jsonify({"error": "Missing address parameter"}), 400
if request.args.get('event') == 'host_paused':
# Host Mode ถูกปิดการทำงาน: reason = idle | cycles_exhausted | no_balance | stopped
print(f"Host Mode paused: address={address} reason={request.args.get('reason')} "
f"paused_at={request.args.get('paused_at')} balance={request.args.get('balance')}")
return jsonify({"status": "success"}), 200
# ตรรกะทางธุรกิจของคุณ (idempotent โดย order_id / hash)
print(f"Energy delegated: address={address} order_id={order_id} hash={tx_hash} "
f"charged={charged} energy_used={energy_used}")
return jsonify({"status": "success"}), 200พฤติกรรมการจัดส่ง
- วิธีการ: GET, หมดเวลา ~10 วินาที ส่งคืน HTTP 200 เพื่อรับทราบ
- การลองใหม่: มีการพยายามสูงสุด 3 ครั้งหากคำขอล้มเหลว หากล้มเหลวทั้งหมด callback จะถูกทิ้งไป (การมอบสิทธิ์ Energy จะยังคงเกิดขึ้นตามปกติ)
- ไม่มีลายเซ็น: คำขอไม่ได้ลงนามโดย Netts ค่าความลับ (ถ้ามี) คือสิ่งที่คุณฝังไว้ใน
callback_urlของคุณเอง - การกระทบยอด: เนื่องจาก callback อาจสูญหายได้ ให้ทำโพลล์
/apiv2/time/statusร่วมด้วย และทำให้ตัวจัดการของคุณรองรับ idempotent
การอัปเดต / การลบ callback
- อัปเดต: เรียก
/apiv2/time/addอีกครั้งด้วยที่อยู่เดิมและcallback_urlใหม่ - ลบ: เรียก
/apiv2/time/deleteเพื่อลบที่อยู่ออก (การดำเนินการนี้จะลบ callback ของที่อยู่นั้นด้วย) เพิ่มที่อยู่อีกครั้งโดยไม่มีcallback_urlหากต้องการ
Endpoint ที่เกี่ยวข้อง
- POST /apiv2/time/order — ซื้อรอบ (เปิดใช้งานที่อยู่)
- POST /apiv2/time/infinitystart — เปิดใช้งานโหมด infinity
- POST /apiv2/time/status — ตรวจสอบสถานะและรอบ
- POST /apiv2/time/stop — หยุด Host Mode
- POST /apiv2/time/delete — ลบที่อยู่ออก
หมายเหตุ
- ที่อยู่ใหม่จะเริ่มต้นด้วยสถานะ ไม่ใช้งาน ให้เปิดใช้งานด้วยคำสั่งซื้อ ด้วยการเริ่ม infinity หรือโดยการส่ง
"infinity": trueที่นี่ - ไม่สามารถลงทะเบียนที่อยู่เดียวกันภายใต้สองบัญชีที่ต่างกันได้
- ควรเปิดใช้งานที่อยู่นั้นบนเครือข่าย TRON ก่อนที่จะเพิ่ม
- ไม่สามารถเพิ่ม Smart contract ได้ — รวมถึงที่อยู่กระเป๋าเงิน GasFree (HTTP 403,
code 1007)