Pular para o conteúdo

Idempotency-Key

POST /orders e POST /orders/{id}/renew exigem um cabeçalho Idempotency-Key único para cada operação. Em caso de timeout, é seguro tentar de novo com o mesmo valor: a requisição concluída é retornada novamente (meta.idempotent_replay: true) e a cobrança nunca é feita duas vezes.

Idempotency-Key: 3f7a1c9e-2b48-4d51-9c3a-8e6f0d215b47

Gere a chave uma única vez

Para cada novo pedido ou renovação, gere um UUID e guarde-o em uma variável.

Em caso de timeout, repita com a mesma chave

Se a resposta não chegar, envie a requisição de novo com a mesma chave. Gerar uma chave nova para a nova tentativa abre um segundo pedido.

409 e Retry-After

Uma repetição que chega enquanto a primeira requisição ainda está em processamento recebe 409 conflict e Retry-After; aguarde e tente de novo com a mesma chave.

import { randomUUID } from "node:crypto";

const key = randomUUID(); // o MESMO valor em cada nova tentativa

async function createOrder(body) {
  for (let attempt = 0; attempt < 3; attempt++) {
    const res = await fetch("https://api.proxynet.io/api/v1/orders", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.PROXYNET_TOKEN}`,
        "Idempotency-Key": key,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(body),
    });
    if (res.status === 409 && res.headers.get("retry-after")) {
      await new Promise((r) => setTimeout(r, Number(res.headers.get("retry-after")) * 1000));
      continue;
    }
    return res.json();
  }
}
import os, time, uuid, requests

key = str(uuid.uuid4())  # o MESMO valor em cada nova tentativa

def create_order(body):
    for _ in range(3):
        res = requests.post(
            "https://api.proxynet.io/api/v1/orders",
            headers={
                "Authorization": f"Bearer {os.environ['PROXYNET_TOKEN']}",
                "Idempotency-Key": key,
            },
            json=body,
        )
        if res.status_code == 409 and "Retry-After" in res.headers:
            time.sleep(int(res.headers["Retry-After"]))
            continue
        return res.json()

Quando a chave é liberada

  • A chave só é liberada se a tentativa com certeza não gerou cobrança: uma recusa 4xx ou um erro do provedor com o valor reembolsado (details.refunded: true). Nesse caso, a mesma chave inicia uma tentativa nova.
  • Uma chave serve para uma única operação. Enviar a mesma chave com um corpo diferente (incluindo destinos, nome e opções) ou usá-la para outro pedido ou outra renovação retorna400 invalid_request. Uma chave que abriu um pedido não é aceita em uma renovação, e uma chave usada em uma renovação não é aceita em um pedido.
  • Um 409 conflict com details.order_id indica que o pedido aberto com essa chave não está mais ativo (falhou sem que o reembolso automático fosse possível ou foi cancelado). Use uma chave nova; se houve cobrança, entre em contato com o suporte.

O pedido está pronto?

meta.ready informa se o pedido já está ativo, também na resposta de uma repetição. Em caso de pré-venda, ativação agendada ou atraso do provedor, vale false emeta.warning vem preenchido. Não coloque o pedido em uso ainda; consulte GET /orders/{id} até que state seja active.

Credenciais

O nome de usuário e a senha são opcionais. Se você não os enviar, o sistema os gera; eles são retornados na resposta se o token também tiver proxies:read. Para escolhê-los você mesmo, o seu plano precisa permitir: veja o campo plan.custom_credentials na resposta de /me.

Campos do pedido por tipo

✓ aceito, ✓* obrigatório, — não usado neste tipo; o valor entre parênteses é o padrão usado quando o campo não é enviado. Campos desconhecidos são rejeitados; um erro de digitação não é ignorado em silêncio.

CampoISP / DatacenterGamingResidential / Mobile
orderType✓*✓*✓*
locationId✓*✓*—
quantity✓*✓*—
unlimitedAccess / targetUrls✓*——
protocol✓ (auto)✓ (socks5)—
highConnection✓✓✓
extraIpWhitelist✓✓—
nonSequentialIps✓✓—
highSpeed✓✓—
countryCode——✓
gbLimit——✓
username / password / gateName✓✓✓

Alterações de configuração

Alterações de configuração, como o nome do serviço e o limite de tráfego, não geram cobrança e são feitas com um escopo próprio (proxies:write). Elas não exigem Idempotency-Key.