POST /apiv2/order1h
Crea una orden de alquiler de Energy de 1 hora a través de múltiples proveedores de Energy con conmutación por error automática.
URL del endpoint
POST https://netts.io/apiv2/order1hEncabezados de solicitud
| Encabezado | Requerido | Descripción |
|---|---|---|
| Content-Type | Sí | application/json |
| X-API-KEY | Sí | Su clave API del panel de Netts |
| X-Real-IP | Sí | Dirección IP de su lista blanca |
Cuerpo de la solicitud
{
"amount": 131000,
"receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"
}Parámetros
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
| amount | entero | Sí | Cantidad de Energy a alquilar (mínimo: 61000, máximo: 3000000) |
| receiveAddress | cadena | Sí | Dirección TRON que recibirá la Energy (formato TRC-20) |
Selección de proveedor
La API selecciona automáticamente el proveedor de Energy óptimo en función de:
- Rentabilidad - Siempre encuentra el precio más bajo disponible
- Disponibilidad - Garantiza reservas de Energy suficientes
- Fiabilidad - Utiliza proveedores con altas tasas de éxito
- Velocidad - Prioriza los tiempos de entrega más rápidos
Solicitudes de ejemplo
cURL
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
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)}")Respuesta
Respuesta exitosa (200 OK)
{
"detail": {
"code": 10000,
"msg": "Successful, 2.23 TRX deducted",
"data": {
"orderId": "1H123456",
"paidTRX": 2.23,
"hash": "a1b2c3d4e5f6789...",
"delegateAddress": "TDelegatePoolAddress...",
"energy": 131050
}
}
}Campos de respuesta
| Campo | Tipo | Descripción |
|---|---|---|
| detail.code | entero | Siempre 10000 para órdenes exitosas |
| detail.msg | cadena | Mensaje de éxito con la cantidad deducida |
| detail.data.orderId | cadena | ID unificado de la orden (formato: 1H{request_id}) |
| detail.data.paidTRX | número | Costo total en TRX (incluye tarifa de activación si la dirección no estaba activada) |
| detail.data.hash | cadena | null | Hash de la transacción. El campo siempre está presente pero puede estar vacío - algunos proveedores no devuelven el hash de inmediato. Use /apiv2/order_check después de 1 minuto para obtener el hash |
| detail.data.delegateAddress | cadena | Dirección del pool que delegó la Energy |
| detail.data.energy | entero | Cantidad de Energy + margen (típicamente +50) |
Respuestas de error
Error de autenticación (401)
{
"detail": "Invalid API key or IP not in whitelist"
}Saldo insuficiente (403)
{
"code": 1004,
"msg": "Insufficient funds. Required: 2.23 TRX, Available: 1.50 TRX"
}Servicio no disponible (503)
{
"code": 5003,
"msg": "Service temporarily unavailable. All energy providers are currently unavailable."
}Errores del proveedor (503)
{
"code": 5001,
"msg": "Energy provider temporarily unavailable"
}{
"code": 5002,
"msg": "Energy provider temporarily unavailable"
}{
"code": 5004,
"msg": "Energy provider requires higher minimum amount"
}Error interno del servidor (500)
{
"code": 5000,
"msg": "Internal server error occurred"
}Referencia de códigos de error
| Código | Descripción | Estado HTTP |
|---|---|---|
10000 | Éxito | 200 |
10000 | Éxito (respuesta en caché) | 208 |
- | Solicitud duplicada aún en procesamiento | 409 |
1004 | Saldo insuficiente | 403 |
5000 | Error interno del servidor | 500 |
5001 | Proveedor de Energy no disponible | 503 |
5002 | Proveedor de Energy no disponible | 503 |
5003 | Servicio de Energy no disponible | 503 |
5004 | No se alcanzó el mínimo del proveedor de Energy | 503 |
Límites de tasa
Los siguientes límites de tasa se aplican a este endpoint (por dirección IP):
| Periodo | Límite | Descripción |
|---|---|---|
| 1 segundo | 50 solicitudes | Máximo 50 solicitudes por segundo |
Encabezados de límite de tasa
RateLimit-Limit: 50
RateLimit-Remaining: 49
RateLimit-Reset: 1
X-RateLimit-Limit-Second: 50
X-RateLimit-Remaining-Second: 49Límite de tasa excedido (429)
{
"message": "API rate limit exceeded"
}Idempotencia
La API admite la idempotencia para evitar el procesamiento de órdenes duplicadas. Cuando envía múltiples solicitudes idénticas, el sistema garantiza que la orden se procese solo una vez.
Cómo funciona la idempotencia
La singularidad de la solicitud se determina mediante una combinación de:
- Marca de tiempo de la solicitud (ventana de 1 segundo)
- Cantidad de Energy
- Dirección del receptor
- Clave API
A cada solicitud se le asigna una ventana de singularidad de 1 segundo. Para proteger el sistema de abusos y garantizar un procesamiento adecuado, las solicitudes con parámetros idénticos no se pueden enviar con una frecuencia mayor a una vez por segundo.
Comportamiento actual: El sistema protege automáticamente a los clientes de reintentos erróneos sobre Energy ya solicitada. Si accidentalmente envía la misma solicitud dos veces, no se le cobrará dos veces.
Proporcionar su propia clave
Puede tomar la idempotencia en sus propias manos enviando el encabezado X-Idempotency-Key. Cuando está presente, ese valor por sí solo decide si una solicitud es una repetición, y no se utiliza la combinación automática anterior. Cuando está ausente, nada cambia: el servidor deriva la clave por usted.
| Encabezado | X-Idempotency-Key |
| Formato | Exactamente 64 caracteres hexadecimales en minúsculas — un resumen SHA-256 |
| Duración | 24 horas a partir de la primera solicitud que incluya esa clave |
| Alcance | Su cuenta. El mismo valor enviado por una cuenta diferente nunca devuelve su resultado |
Una clave con cualquier otra forma (un UUID con guiones, base64, hexadecimal en mayúsculas) se rechaza con 400 antes de que se realice la orden y antes de que se cobre nada:
{
"detail": "Invalid idempotency key format. Must be 64-character hexadecimal string."
}El formato difiere de otros endpoints.
/apiv2/withdraw,/apiv2/bandwidthy el orquestador aceptan una clave base64 de 16 a 64 caracteres. Este endpoint solo acepta un resumen hexadecimal de 64 caracteres, por lo que el código de generación de claves copiado de esos endpoints devuelve 400 aquí.
Cómo formar la clave
Derívela de su clave API. Eso hace que el valor sea único para su cuenta, reproducible en un reintento e imposible de alcanzar para cualquier otra persona:
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()El
noncepertenece a la orden, no a la solicitud. Elíjalo una sola vez, cuando se cree la orden en su lado, y pase ese mismo valor en cada envío de esa orden, tanto en el primer intento como en cada reintento. Generar un valor nuevo dentro de la función de envío (str(uuid.uuid4())en cada llamada) le da a cada intento una clave diferente, por lo que un reintento tras un tiempo de espera se acepta como una segunda orden y se cobra nuevamente. La opción correcta más simple es el id de orden que ya tiene: existe antes del primer intento y sobrevive al reinicio de su proceso.
# una sola vez, cuando la orden aparece en su sistema
order = create_order(address="TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE", amount=131000)
# en el primer intento y en cada reintento — las mismas tres entradas, la misma clave
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,
}Una clave dura 24 horas. Después de eso, el mismo nonce queda libre de nuevo e inicia una nueva orden.
No use un valor al que cualquiera pudiera llegar: 64 ceros, el resumen de una palabra fija. Las claves comparten un único espacio entre cuentas. Tal colisión nunca expone la orden de otra cuenta, pero su solicitud se rechazará con 409 hasta que expire la clave de ellos, lo cual no es la respuesta que desea a mitad de un reintento.
Realizar dos órdenes idénticas
A veces realmente desea la misma orden dos veces: la misma cantidad de Energy para la misma dirección, una tras otra. La clave automática no puede distinguir eso de un reintento: las dos solicitudes son idénticas byte por byte, y lo único que las separa es el momento en que llegan.
Sin una clave propia, el resultado depende del intervalo entre ellas:
| Intervalo entre las dos solicitudes | Qué sucede |
|---|---|
| Dentro de la misma ventana de 1 segundo | La segunda solicitud se toma como una repetición. No se ejecuta: obtiene 208 y la respuesta de la primera orden, incluido el orderId. No se cobra nada por ella |
| Con más de un segundo de diferencia | Dos claves diferentes — ambas órdenes se realizan y ambas se cobran |
Por lo tanto, si confía en la clave automática, deje más de un segundo entre dos órdenes idénticas y lea el código de estado: 208 significa que la orden que acaba de enviar no se realizó.
Una pausa es una solución temporal, no definitiva. Separa cada solicitud, incluidas las que nunca tuvo la intención de repetir: un reintento tras un tiempo de espera, un doble clic, un mensaje reenviado por su cola. Estas también llegan después de la ventana, por lo que se realizan como órdenes separadas y se cobran por separado. El tiempo de espera de respuesta de este endpoint es de 10 segundos, lo que ya está muy por fuera de la ventana: la clave automática no protege un reintento que sigue a un tiempo de espera agotado.
Su propia clave elimina las suposiciones, porque la decisión pasa al único lado que sabe la respuesta:
| Qué está haciendo | Qué envía | Resultado |
|---|---|---|
| Una segunda orden genuinamente nueva | Un nuevo nonce | Una nueva clave — la orden se realiza |
| Un reintento de una orden cuyo resultado desconoce | El nonce del primer intento | La misma clave — 208, la respuesta original, ningún segundo cargo |
La segunda fila es la razón por la que existe el encabezado, y es donde las implementaciones suelen fallar: consulte la nota debajo de Cómo formar la clave.
Códigos de estado HTTP para solicitudes duplicadas
| Código de estado | Nombre | Descripción |
|---|---|---|
| 200 | OK | Orden procesada exitosamente (primera solicitud) |
| 208 | Already Reported | La orden ya fue procesada, devolviendo respuesta en caché |
| 409 | Conflict | La solicitud se está procesando actualmente, no reintente |
Solicitud duplicada - Ya procesada (208)
Cuando se recibe una solicitud duplicada para una orden ya completada:
{
"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"
}
}El cuerpo de la respuesta es idéntico a la respuesta exitosa original, con un objeto idempotency adicional que indica que se trata de una respuesta en caché.
Solicitud duplicada - Aún en procesamiento (409)
Cuando llega una solicitud duplicada mientras la original todavía se está procesando:
{
"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
}Recomendación: Espere el tiempo especificado en retry_after_seconds antes de verificar el estado de la orden.
Buenas prácticas
- No envíe solicitudes paralelas con los mismos parámetros: espere cada respuesta
- Utilice un nuevo
noncepara cada nueva orden, y elnoncedel primer intento para cada reintento de la misma - Nunca reconstruya el
nonceen el momento del envío: un reintento debe reproducir la clave del primer intento, no una nueva - Maneje las respuestas 409 esperando, no reintentando de inmediato
- Verifique el campo
idempotency.cachedpara identificar respuestas en caché: un208significa que la orden que acaba de enviar no se realizó
Notas
- La Energy se entrega instantáneamente tras una orden exitosa (típicamente entre 0.5 y 10 segundos)
- Tiempo de espera de respuesta de la API: Máximo 10 segundos, típicamente responde en hasta 2 segundos
- Activación de dirección: Si la dirección del receptor no está activada, Netts la activa a precio de costo
- Demora de activación: Para direcciones no activadas, la respuesta de la API puede tardar hasta 6 segundos debido al proceso de activación
- Las órdenes se procesan 24/7 con conmutación por error automática de proveedores
- Cantidad mínima de Energy: 61,000 unidades
- Cantidad máxima de Energy: 3,000,000 unidades por orden
- Margen de Energy: +50 unidades agregadas automáticamente para compensación del proveedor (sin costo)
- Hash de transacción: El campo siempre está presente pero puede estar vacío si el proveedor no lo devuelve de inmediato. Para recuperar el hash, llame a /apiv2/order_check no antes de 1 minuto después de realizar la orden
- Selección de proveedor: Automática basada en costo y disponibilidad
- Formato de ID de orden:
1H{request_id}para seguimiento unificado - Precios: Dinámicos según la hora del día y la cantidad de Energy
- Duración: Fija de 1 hora (3600 segundos)
- Límite de tasa: 50 solicitudes por segundo por dirección IP