Appearance
POST /apiv2/order1h
Crie um pedido de aluguel de energy de 1 hora através de múltiplos provedores de energy com failover automático.
URL do endpoint
POST https://netts.io/apiv2/order1hCabeçalhos da requisição
| Header | Obrigatório | Descrição |
|---|---|---|
| Content-Type | Sim | application/json |
| X-API-KEY | Sim | Sua chave de API do painel da Netts |
| X-Real-IP | Sim | Endereço IP da sua lista de permissões (whitelist) |
Corpo da requisição
json
{
"amount": 131000,
"receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"
}Parâmetros
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| amount | integer | Sim | Quantidade de energy a alugar (mínimo: 61000, máximo: 3000000) |
| receiveAddress | string | Sim | Endereço TRON que receberá a energy (formato TRC-20) |
Seleção de Provedor
A API seleciona automaticamente o provedor de energy ideal com base em:
- Custo-benefício - Sempre encontra o menor preço disponível
- Disponibilidade - Garante reservas suficientes de energy
- Confiabilidade - Utiliza provedores com altas taxas de sucesso
- Velocidade - Prioriza os tempos de entrega mais rápidos
Exemplos de Requisição
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)}")Resposta
Resposta de Sucesso (200 OK)
json
{
"detail": {
"code": 10000,
"msg": "Successful, 2.23 TRX deducted",
"data": {
"orderId": "1H123456",
"paidTRX": 2.23,
"hash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
"delegateAddress": "TNp5gsJhBmZFXgCdgjMgr8pEZ8fHgXUHDq",
"energy": 131050
}
}
}Campos da Resposta
| Campo | Tipo | Descrição |
|---|---|---|
| detail.code | integer | Sempre 10000 para pedidos bem-sucedidos |
| detail.msg | string | Mensagem de sucesso com o valor deduzido |
| detail.data.orderId | string | ID unificado do pedido (formato: 1H{request_id}) |
| detail.data.paidTRX | number | Custo total em TRX (inclui taxa de ativação se o endereço não estiver ativado) |
| detail.data.hash | string | null | Hash da transação. O campo está sempre presente, mas pode estar vazio - alguns provedores não retornam o hash imediatamente. Use /apiv2/order_check após 1 minuto para obter o hash |
| detail.data.delegateAddress | string | Endereço do pool que delegou a energy |
| detail.data.energy | integer | Quantidade de energy + margem de buffer (tipicamente +50) |
Respostas de Erro
Erro de Autenticação (401)
json
{
"detail": "Invalid API key or IP not in whitelist"
}Saldo Insuficiente (403)
json
{
"code": 1004,
"msg": "Insufficient funds. Required: 2.23 TRX, Available: 1.50 TRX"
}Serviço Indisponível (503)
json
{
"code": 5003,
"msg": "Service temporarily unavailable. All energy providers are currently unavailable."
}Erros de Provedor (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"
}Erro Interno do Servidor (500)
json
{
"code": 5000,
"msg": "Internal server error occurred"
}Referência de Códigos de Erro
| Código | Descrição | Status HTTP |
|---|---|---|
10000 | Sucesso | 200 |
10000 | Sucesso (resposta em cache) | 208 |
- | Pedido duplicado ainda em processamento | 409 |
1004 | Saldo insuficiente | 403 |
5000 | Erro interno do servidor | 500 |
5001 | Provedor de energy indisponível | 503 |
5002 | Provedor de energy indisponível | 503 |
5003 | Serviço de energy indisponível | 503 |
5004 | Valor mínimo do provedor de energy não atingido | 503 |
Limites de Taxa
Os seguintes limites de taxa se aplicam a este endpoint (por endereço IP):
| Período | Limite | Descrição |
|---|---|---|
| 1 segundo | 50 requisições | Máximo de 50 requisições por segundo |
Headers de Limite de Taxa
http
RateLimit-Limit: 50
RateLimit-Remaining: 49
RateLimit-Reset: 1
X-RateLimit-Limit-Second: 50
X-RateLimit-Remaining-Second: 49Limite de Taxa Excedido (429)
json
{
"message": "API rate limit exceeded"
}Idempotência
A API suporta idempotência para evitar o processamento duplicado de pedidos. Quando você envia múltiplas requisições idênticas, o sistema garante que o pedido seja processado apenas uma vez.
Como Funciona a Idempotência
A unicidade da requisição é determinada por uma combinação de:
- Timestamp da requisição (janela de 1 segundo)
- Quantidade de energy
- Endereço de recebimento
- Chave de API
Cada requisição recebe uma janela de unicidade de 1 segundo. Para proteger o sistema contra abusos e garantir o processamento correto, requisições com parâmetros idênticos não podem ser enviadas com frequência superior a uma vez por segundo.
Comportamento atual: O sistema protege automaticamente os clientes de novas tentativas errôneas para energy já solicitada. Se você enviar acidentalmente a mesma requisição duas vezes, não será cobrado em duplicidade.
Fornecendo Sua Própria Chave
Você pode assumir o controle da idempotência enviando o header X-Idempotency-Key. Quando ele está presente, esse valor sozinho decide se uma requisição é uma repetição, e a combinação automática acima não é utilizada. Quando está ausente, nada muda — o servidor deriva a chave para você.
| Header | X-Idempotency-Key |
| Formato | Exatamente 64 caracteres hexadecimais em minúsculas — um hash SHA-256 |
| Tempo de vida | 24 horas a partir da primeira requisição contendo essa chave |
| Escopo | Sua conta. O mesmo valor enviado por uma conta diferente nunca retorna o seu resultado |
Uma chave em qualquer outro formato — um UUID com hifens, base64, hexadecimal em maiúsculas — é rejeitada com 400 antes que o pedido seja criado e antes que qualquer valor seja cobrado:
json
{
"detail": "Invalid idempotency key format. Must be 64-character hexadecimal string."
}O formato difere de outros endpoints.
/apiv2/withdraw,/apiv2/bandwidthe o orquestrador aceitam uma chave em base64 de 16 a 64 caracteres. Este endpoint aceita apenas um hash hexadecimal de 64 caracteres; portanto, códigos de geração de chave copiados desses endpoints retornarão 400 aqui.
Como formar a chave
Derive-a da sua chave de API. Isso torna o valor exclusivo para a sua conta, reproduzível em uma nova tentativa e impossível de ser gerado por terceiros:
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()O
noncepertence ao pedido, não à requisição. Defina-o uma única vez, quando o pedido for criado do seu lado, e envie esse mesmo valor em cada envio desse pedido — tanto na primeira tentativa quanto em todas as repetições. Gerar um novo valor dentro da função de envio (str(uuid.uuid4())a cada chamada) atribui uma chave diferente a cada tentativa, de modo que uma nova tentativa após um timeout seja aceita como um segundo pedido e cobrada novamente. A escolha correta mais simples é o ID do pedido que você já possui: ele existe antes da primeira tentativa e sobrevive à reinicialização do seu processo.
python
# uma vez, quando o pedido aparece no seu sistema
order = create_order(address="TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE", amount=131000)
# na primeira tentativa e em todas as repetições — as mesmas três entradas, a mesma chave
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,
}Uma chave dura 24 horas. Após esse período, o mesmo nonce fica livre novamente e inicia um novo pedido.
Não use um valor que qualquer outra pessoa possa gerar — 64 zeros, o hash de uma palavra fixa. As chaves compartilham um único espaço entre as contas. Essa colisão nunca expõe o pedido de outra conta, mas sua requisição será recusada com 409 até que a chave deles expire, o que não é a resposta desejada durante uma nova tentativa.
Criando Dois Pedidos Idênticos
Às vezes, você realmente deseja o mesmo pedido duas vezes — a mesma quantidade de energy para o mesmo endereço, um após o outro. A chave automática não consegue distinguir isso de uma nova tentativa: as duas requisições são idênticas byte a byte, e a única coisa que as separa é o momento em que chegam.
Sem uma chave própria, o resultado depende do intervalo entre elas:
| Intervalo entre as duas requisições | O que acontece |
|---|---|
| Dentro da mesma janela de 1 segundo | A segunda requisição é considerada uma repetição. Ela não é executada: você recebe 208 e a resposta do primeiro pedido, incluindo o orderId. Nada é cobrado por ela |
| Com mais de um segundo de intervalo | Duas chaves diferentes — ambos os pedidos são criados e ambos são cobrados |
Portanto, se você depende da chave automática, deixe mais de um segundo entre dois pedidos idênticos e verifique o código de status: 208 significa que o pedido que você acabou de enviar não foi criado.
Uma pausa é um contorno temporário, não uma solução definitiva. Ela separa todas as requisições, incluindo aquelas que você nunca teve a intenção de repetir — uma nova tentativa após um timeout, um clique duplo, uma mensagem reenviada pela sua fila. Elas também chegam fora da janela, portanto são criadas como pedidos separados e cobradas individualmente. O tempo limite de resposta (timeout) deste endpoint é de 10 segundos, o que já está muito além da janela: a chave automática não protege uma nova tentativa decorrente de um timeout.
Sua própria chave elimina as incertezas, pois a decisão passa para o único lado que conhece a resposta:
| O que você está fazendo | O que você envia | Resultado |
|---|---|---|
| Um segundo pedido, genuinamente novo | Um novo nonce | Uma nova chave — o pedido é criado |
| Uma nova tentativa de um pedido cujo resultado você não conhece | O nonce da primeira tentativa | A mesma chave — 208, a resposta original, sem cobrança duplicada |
A segunda linha é a razão pela qual o header existe, e é onde as implementações normalmente falham: consulte a observação em Como formar a chave.
Códigos de Status HTTP para Requisições Duplicadas
| Código de Status | Nome | Descrição |
|---|---|---|
| 200 | OK | Pedido processado com sucesso (primeira requisição) |
| 208 | Already Reported | O pedido já foi processado; retornando resposta em cache |
| 409 | Conflict | A requisição está sendo processada no momento, não tente novamente |
Requisição Duplicada - Já Processada (208)
Quando uma requisição duplicada é recebida para um pedido já concluído:
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"
}
}O corpo da resposta é idêntico à resposta de sucesso original, com um objeto idempotency adicional indicando que se trata de uma resposta em cache.
Requisição Duplicada - Ainda em Processamento (409)
Quando uma requisição duplicada chega enquanto a original ainda está sendo processada:
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
}Recomendação: Aguarde o tempo especificado em retry_after_seconds antes de verificar o status do pedido.
Melhores Práticas
- Não envie requisições paralelas com os mesmos parâmetros — aguarde cada resposta
- Use um novo
noncepara cada novo pedido e ononceda primeira tentativa para cada repetição dele - Nunca recrie o
nonceno momento do envio — uma nova tentativa deve reproduzir a chave da primeira tentativa, não gerar uma nova - Trate respostas 409 aguardando, e não tentando novamente de forma imediata
- Verifique o campo
idempotency.cachedpara identificar respostas em cache — um status208indica que o pedido que você acabou de enviar não foi criado
Contas Pós-pagas
Contas no faturamento pós-pago utilizam o mesmo endpoint, URL, headers e corpo de requisição que todas as outras. A diferença reside na forma como o pedido é pago:
- Nada é deduzido do seu depósito. Cada pedido bem-sucedido é adicionado ao saldo devedor da sua conta na moeda de liquidação acordada em seu contrato. Você efetua o pagamento via fatura, conforme o seu acordo.
- Sua conta possui um limite de crédito. Enquanto o valor devido estiver dentro do limite, os pedidos serão aceitos mesmo com saldo de depósito zerado.
- Apenas os serviços efetivamente entregues são faturados. Um pedido rejeitado ou não executado não gera custos.
- Caso o endereço de recebimento precise ser ativado, a ativação fará parte do mesmo pedido e será faturada como uma cobrança separada.
O faturamento pós-pago é ativado pela Netts para uma conta mediante solicitação. Cada resposta informa como o pedido foi pago: paymentMode é postpaid ou prepaid.
Campos de requisição adicionais
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| test | boolean | Não | true — calcula apenas o preço. Nada é pedido, entregue ou faturado |
| freezePrice | boolean | Não | true — fixa o preço sob o seu contrato por 60 segundos. Nada é pedido ou faturado |
| quoteId | string | Não | Cria o pedido com o preço de uma cotação emitida por freezePrice |
| priceCurrency | string | Não | TRX (padrão) ou a moeda do seu contrato, conforme em settlement.asset. Para contas pós-pagas, os valores na moeda do seu contrato são sempre incluídos |
quoteId não pode ser combinado com test ou freezePrice. Qualquer outro campo no corpo da requisição será rejeitado.
Consulta de preço (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"
}
}
}| Campo | Descrição |
|---|---|
| unitPriceSun | Preço por unidade de energy em SUN, incluindo seu desconto pessoal se possuir |
| discount | Seu desconto pessoal (type, value) ou null |
| energyTRX / activationTRX / wouldCostTRX | Energy, ativação (se o endereço precisar) e total, em TRX |
| activationCheck | inactive — o endereço será ativado e faturado; active — sem ativação; unknown — não foi possível verificar no momento |
alt.<currency> | Os mesmos valores na moeda do seu contrato |
| fxAt | Momento da taxa de câmbio utilizada para os valores na moeda do seu contrato |
Cotação de preço fixo (freezePrice: true)
Utilize uma cotação para fixar o preço sob o seu contrato antes de realizar o pedido.
- Envie o pedido com
"freezePrice": true. A resposta conterá o código10011(Quote issued), os mesmos campos de uma consulta de preço, além dequoteIdeexpiresAt. - Dentro de 60 segundos, envie o pedido com
"quoteId": "<quoteId>"e os mesmosamountereceiveAddress. - O pedido é faturado pelo preço cotado — o preço sob o seu contrato no momento da cotação — mesmo que o preço se altere nesse intervalo.
Uma cotação pode ser usada uma única vez e apenas para o mesmo produto: uma cotação de 1 hora não pode pagar por um pedido de 5 minutos. Uma cotação expirada ou já utilizada é rejeitada e nada é solicitado.
json
{
"amount": 65000,
"receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"quoteId": "q_4f540f16a2c94b7f8e3d1a6b5c0e9d72"
}Pedido bem-sucedido
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"
}
}
}| Campo | Descrição |
|---|---|
| paidTRX | Custo do serviço em TRX. Para contas pós-pagas, ele não é deduzido do depósito |
| paymentMode | postpaid |
| energyTRX / activationTRX / totalTRX | Valores exatos, com 6 casas decimais |
| quoteId, alt | Presentes quando o pedido foi realizado com uma cotação: o ID da cotação e os valores cotados |
| activationFinal | Presente e false apenas quando o valor da ativação for preliminar; o valor final constará em sua fatura |
Todos os outros campos são os mesmos dos pedidos pré-pagos.
Limite de crédito atingido (402)
json
{
"detail": {
"code": 1004,
"msg": "Postpaid credit limit reached.",
"paymentMode": "postpaid",
"reason": "limit_reached"
}
}O pedido não é executado e nada é faturado. Novos pedidos serão aceitos novamente assim que o seu pagamento for registrado ou o seu limite for aumentado.
Códigos de erro pós-pago
| Código | HTTP | Descrição |
|---|---|---|
10010 | 200 | Resultado da consulta de preço (test) |
10011 | 200 | Cotação emitida (freezePrice) |
1004 | 402 | Limite de crédito pós-pago atingido |
4100 | 400 | Requisição inválida |
4101 | 400 | priceCurrency não suportada |
4102 | 400 | quoteId combinado com test ou freezePrice |
4103 | 409 | Cotação já utilizada |
4104 | 409 | Cotação expirada |
4105 | 409 | Chave de idempotência já utilizada para uma requisição diferente |
4106 | 404 | Cotação não encontrada |
4107 | 409 | Os parâmetros do pedido diferem da cotação |
4108 | 400 | Formato inválido de quoteId |
4109 | 422 | Não disponível para subcontas |
5032 | 503 | Preço temporariamente indisponível |
5033 | 503 | Taxa de câmbio temporariamente indisponível |
5034 | 503 | Faturamento temporariamente indisponível — o pedido não foi aceito |
5036 | 503 | Verificação de crédito temporariamente indisponível — tente novamente mais tarde |
Para todas as respostas 4xx e 503 acima, nada é solicitado e nada é faturado.
Observações
- A energy é entregue instantaneamente após a conclusão do pedido (normalmente dentro de 0,5 a 10 segundos)
- Tempo limite de resposta da API: Máximo de 10 segundos, respondendo tipicamente em até 2 segundos
- Ativação de endereço: Se o endereço de recebimento não estiver ativado, a Netts o ativa pelo preço de custo
- Atraso de ativação: Para endereços não ativados, a resposta da API pode levar até 6 segundos devido ao processo de ativação
- Os pedidos são processados 24/7 com failover automático de provedores
- Quantidade mínima de energy: 61.000 unidades
- Quantidade máxima de energy: 3.000.000 unidades por pedido
- Buffer de energy: +50 unidades adicionadas automaticamente para compensação do provedor (sem custo adicional)
- Hash da transação: O campo está sempre presente, mas pode estar vazio se o provedor não o retornar imediatamente. Para consultar o hash, chame /apiv2/order_check no mínimo 1 minuto após a criação do pedido
- Seleção de provedor: Automática com base no custo e na disponibilidade
- Formato do ID do pedido:
1H{request_id}para rastreamento unificado - Preços: Dinâmicos com base na hora do dia e na quantidade de energy
- Duração: Fixa em 1 hora (3600 segundos)
- Limitação de taxa: 50 requisições por segundo por endereço IP