Documentação ← Site

Documentação Nextout

Checkout multi-loja para e-commerce. Conecte sua loja e o Nextout assume o pagamento: PIX e cartão, frete real dos Correios, e o preço sempre validado no servidor.

Introdução

O Nextout é um checkout hospedado. Você continua com a sua loja (Shopify, WooCommerce ou um site próprio); quando o cliente vai finalizar a compra, ele cai no checkout do Nextout, que cuida de PIX, cartão, frete e do pedido.

O que você configura uma vez: a loja (de onde vem o carrinho), o gateway (por onde o dinheiro entra) e, opcionalmente, frete, domínio próprio e rastreamento. O resto é automático.

Como funciona

  1. O cliente monta o carrinho na sua loja.
  2. Ao clicar em finalizar, ele é levado ao checkout do Nextout com o carrinho.
  3. O servidor do Nextout confere o preço de cada item. O navegador nunca decide o valor. É isso que impede fraude.
  4. O cliente paga (PIX ou cartão). O pedido nasce na sua loja e recebe a baixa quando o pagamento cai.
Preço à prova de fraude. Em toda plataforma, o preço é reconferido no servidor: contra a API da loja (Shopify/Woo) ou contra o cadastro do Nextout (Site próprio). Um cliente não consegue editar o valor pelo navegador.

Shopify

Conexão em um clique, via instalação do app.

  1. No painel Nextout, vá em Integrações → Shopify e siga o passo a passo (ele mostra o endereço de instalação da sua loja).
  2. Autorize o app na Shopify. Pronto. O Nextout injeta sozinho o script que sequestra o botão "Finalizar compra" e leva o cliente ao checkout.

Produtos com variação (tamanho/cor) funcionam: o preço é validado na Storefront API da sua loja.

WooCommerce

  1. Em WooCommerce → Configurações → Avançado → API REST, crie uma chave com permissão Leitura/Escrita. Guarde a Consumer Key e a Consumer Secret.
  2. No painel Nextout, Integrações → WooCommerce, cole a URL da loja e as duas chaves.
  3. Baixe e instale o plugin: nextout-woocommerce.zip (WordPress → Plugins → Enviar plugin → Ativar).
As chaves ficam cifradas e valem só para essa loja. O plugin injeta o loader que leva o cliente ao checkout.

Site próprio

Não tem plataforma? Vende por um site de código próprio, link na bio ou infoproduto? O Nextout tem três formas de integrar, da mais simples (zero código) à mais poderosa (API no seu servidor). Todas guardam o preço no servidor, então ninguém frauda pelo navegador.

FORMA 1Link e botão por produtoCadastre o produto no painel e copie o link (ou um botão pronto). Zero código.
FORMA 2Carrinho no seu siteUm snippet que junta vários produtos cadastrados e leva ao checkout. Pouco código.
FORMA 3APIO servidor do seu site cria o checkout com os produtos e preços dele. Para quem tem programador.

Forma 2 · Carrinho no seu site um pouco de código

Quer que o cliente junte vários produtos no seu site e feche numa compra só? Cole este script uma vez no <head> do site (o data-loja aparece no painel, em Produtos):

<script src="https://nextout.com.br/nextout-loja.js" data-loja="nx:SEU_ID"></script>

Depois, use os ids dos produtos (que aparecem no painel) de dois jeitos:

Botão simples (1 produto)

<a href="#" data-nextout-produto="ID_DO_PRODUTO" data-nextout-qtd="1">Comprar</a>

Carrinho (vários produtos)

No seu botão "Finalizar compra", chame:

Nextout.checkout([
  { id: "ID_DO_PRODUTO", qty: 2 },
  { id: "OUTRO_ID",     qty: 1 }
])
// leva o cliente pro checkout com esses itens
O preço vem sempre do seu cadastro no Nextout. O site manda só quais produtos e quantos, nunca o valor. Por isso o cliente não consegue fraudar.

Forma 3 · API servidor + programador

É a integração "de verdade" para site de código próprio: o servidor do seu site cria o checkout com uma chave secreta, mandando os produtos e preços que só existem no seu site, sem precisar cadastrar nada no Nextout.

Funciona porque a chave secreta prova que a chamada veio do seu servidor confiável, não do navegador do cliente (que poderia forjar preço).

  1. No painel, Produtos → Integração via API, gere a chave (começa com nx_sk_). Ela é mostrada uma vez. Guarde.
  2. No servidor do seu site, chame a API de checkout (abaixo) com os itens do carrinho.
  3. Redirecione o cliente para a url que a API devolve.

Reference completa em API de checkout.

🔴 A chave nx_sk_ é secreta: só no servidor, nunca no navegador. Se ela vazar, qualquer um cria cobranças na sua conta. Se acontecer, revogue e gere outra no painel.

Pagamento (gateways)

O gateway é por onde o dinheiro entra. Conecte um em Integrações. Só um fica ativo por loja.

GatewayAceitaComo conectar
AFEX PayPIX + cartão até 12×Cole a chave secreta (ak_live_…) e a chave pública (pk_…).
pagou.aiPIX + cartãoChave secreta + pública (v1) ou chave única (v2).
Appmax em breveIntegração em homologação.
O cartão é tokenizado no navegador pelo SDK do gateway. O número e o CVV nunca passam pelo servidor do Nextout.

Frete

Em Fretes, você escolhe como o frete é calculado:

  • Next Envios: Correios pelo contrato da plataforma (PAC e SEDEX), com etiqueta, DACE e rastreio no painel. O frete real aparece no checkout pelo CEP do cliente.
  • Melhor Envio: sua própria conta do Melhor Envio, com os seus preços. Cole o token (fica cifrado).
  • Frete manual: até 6 faixas fixas (nome, preço, prazo) definidas por você.

Só o frete no WooCommerce, sem trocar o checkout

Se você quer o frete do Next Envios mas prefere manter o seu checkout do WooCommerce, instale o plugin Nextout Envios. Ele acrescenta PAC e SEDEX na tela de entrega que a sua loja já mostra, e não mexe em mais nada.

  1. Baixe e instale: nextout-envios.zip (WordPress → Plugins → Enviar plugin → Ativar).
  2. Vá em WooCommerce → Configurações → Entrega, abra a sua zona de entrega e clique em Adicionar métodoNextout Envios.
  3. Cole o ID da loja (está no painel da Nextout, em Integrações) e salve.

Ao abrir a configuração, o plugin faz uma cotação de teste de verdade e mostra o resultado ali mesmo. Se o ID estiver errado ou faltar o CEP de origem, você descobre na hora, e não quando um cliente não encontrar entrega nenhuma.

Duas coisas que valem saber: se a cotação falhar, o plugin não cria opção de entrega em vez de chutar um preço, e a sua loja continua mostrando os outros métodos que você tiver. E ele guarda cada cotação por 10 minutos, porque num site WordPress todas as consultas saem do mesmo endereço de rede.

Este plugin é independente do Nextout Checkout. Dá pra usar um, o outro, ou os dois.

Domínio próprio

Deixe o checkout no seu endereço (ex.: checkout.sualoja.com.br) em vez do nosso. O cliente confia mais e, mais importante, a sua loja fica isolada: um problema em outra loja não derruba o seu checkout.

  1. No painel, item Domínio, digite o endereço (recomendamos um subdomínio, ex.: checkout.sualoja.com.br).
  2. Crie o registro DNS que o painel indicar, no seu provedor de domínio:
TipoQuandoValor
CNAMEsubdomínio (checkout.sualoja.com.br)cname.vercel-dns.com
Adomínio raiz (sualoja.com.br)76.76.21.21

O HTTPS é emitido sozinho quando o DNS propaga (de alguns minutos a algumas horas).

Cada loja no seu próprio domínio. Recomendamos configurar antes de escalar as vendas.

Rastreamento · UTMify

Saiba qual anúncio trouxe cada venda. O Nextout envia sozinho cada pedido (pendente e pago) para a UTMify, com as UTMs.

  1. Na UTMify: Integrações → Webhooks → Credenciais de API → Criar.
  2. No painel Nextout, Integrações → UTMify, cole a credencial. A gente testa antes de salvar; ela fica cifrada.

Funciona com qualquer gateway: a atribuição é enviada pelo Nextout, não depende do meio de pagamento.

Webhooks avisamos o seu sistema

Em vez de o seu sistema ficar perguntando "já pagou?", nós avisamos ele no momento em que acontece. Serve para dar baixa no estoque, emitir nota, alimentar uma planilha ou disparar uma mensagem. Funciona com ERP próprio, Make, Zapier, n8n ou um bot no Telegram.

Configure em Painel → Integrações → Automação → Webhooks. Cada loja tem os seus.

Eventos

EventoQuando dispara
pedido.criadoO cliente fechou o pedido no checkout. Ainda não pagou.
pedido.pagoO pagamento foi aprovado. É o evento que a maioria usa.
pedido.recusadoO cartão do cliente foi negado. Estorno não entra aqui.
pedido.enviadoA etiqueta saiu. Traz o código de rastreio.

O que chega

Sempre um POST com Content-Type: application/json. O desenho é o mesmo em todos os eventos, então você escreve um tratamento só:

{
  "id": "evt_9f2c1a7b40e3",
  "evento": "pedido.pago",
  "criado_em": "2026-07-31T18:20:11.000Z",
  "dados": {
    "pedido_id": "ch_a1b2c3",
    "loja": "sualoja.myshopify.com",
    "plataforma": "shopify",
    "status": "paid",
    "metodo": "pix",
    "valor_centavos": 12990,
    "moeda": "BRL",
    "frete_centavos": 2190,
    "frete_nome": "PAC",
    "criado_em": "2026-07-31T18:19:02.000Z",
    "cliente": {
      "nome": "Cliente Exemplo",
      "email": "cliente@exemplo.com.br",
      "telefone": "11999999999",
      "cpf": "00000000000"
    },
    "endereco": {
      "cep": "01000000", "rua": "Rua das Flores", "numero": "123",
      "bairro": "Centro", "cidade": "São Paulo/SP"
    },
    "produtos": [
      { "nome": "Camiseta Oversized", "variacao": "Tam. M", "qtd": 1, "valor_centavos": 12990 }
    ]
  }
}

No pedido.enviado vêm três campos a mais dentro de dados: rastreio, transportadora e rastreio_url.

Valor sempre em centavos, número inteiro. 12990 é R$ 129,90. Campo novo pode aparecer com o tempo; campo que já existe não muda de nome nem de tipo.

Conferir a assinatura

Todo aviso leva o cabeçalho X-Nextout-Assinatura:

X-Nextout-Assinatura: t=1785531611,v1=8a1f...c07d

O v1 é um HMAC-SHA256 de t + "." + corpo, calculado com o segredo daquele webhook. O segredo aparece uma vez, quando você cria (ou gera outro), e começa com whsec_.

// Node/Express
const crypto = require("crypto");
const SEGREDO = process.env.NEXTOUT_WEBHOOK_SECRET;

app.post("/nextout", express.raw({ type: "application/json" }), (req, res) => {
  const cab = req.header("X-Nextout-Assinatura") || "";
  const t  = (cab.match(/t=(\d+)/) || [])[1];
  const v1 = (cab.match(/v1=([a-f0-9]+)/) || [])[1];

  const esperado = crypto.createHmac("sha256", SEGREDO)
                         .update(t + "." + req.body.toString()).digest("hex");

  // timingSafeEqual e não ===: comparar string vaza o segredo pelo tempo de resposta
  const ok = v1 && esperado.length === v1.length &&
             crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(v1));
  if (!ok) return res.status(401).end();

  // recusa aviso velho (alguém reenviando algo que capturou antes)
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return res.status(401).end();

  const evt = JSON.parse(req.body.toString());
  if (evt.evento === "pedido.pago") {
    // evt.dados.pedido_id, .valor_centavos, .cliente, .produtos, .endereco
  }
  res.status(200).end();
});
🔴 Confira a assinatura antes de confiar no aviso. Sem isso, qualquer um que descubra o seu endereço manda um "pedido.pago" e o seu sistema dá baixa numa venda que não existiu.

Como tratamos a resposta

  • Responda 200 (qualquer 2xx) e o mais rápido que der. O corpo da sua resposta é ignorado.
  • Se falhar ou demorar mais de 8 segundos, tentamos de novo: 3 tentativas, com pausa entre elas.
  • Respondeu 4xx? Paramos na hora. É erro de endereço ou de rota, e repetir não resolve. A exceção é 429, que tratamos como "tente de novo".
  • A situação da última entrega aparece no painel, com o código de resposta ou o motivo da falha.
O mesmo evento pode chegar mais de uma vez (uma retentativa depois de um tempo limite que na verdade funcionou). Guarde o id do evento e ignore repetido, que é o que se chama de tratamento idempotente.

Regras do endereço

  • Precisa ser https. Recusamos http porque o aviso leva dados do seu cliente.
  • Endereço de rede interna não é aceito, e não seguimos redirecionamento.
  • Até 10 webhooks por loja.

Referência · API de checkout

Cria um checkout a partir dos itens que o seu servidor manda. Use com a chave secreta do Site próprio (Forma 3). Não precisa cadastrar produto nenhum aqui. Os itens vão soltos, com nome e preço, direto do seu sistema.

Antes de começar

Dois pré-requisitos. Sem eles a chamada é recusada mesmo com o corpo perfeito:

Pré-requisitoOndeSe faltar
Domínio de checkout cadastrado Painel → Domínio 400 pedindo pra configurar o domínio. O checkout roda no seu endereço, não no da Nextout. Por isso ele é obrigatório antes da primeira cobrança.
Gateway conectado Painel → Integrações O link é criado normalmente, mas o cliente não consegue pagar no fim. Vale testar o caminho todo, não só a resposta da API.

Criar checkout

POSThttps://nextout.com.br/api/checkout

Autenticação: header Authorization: Bearer nx_sk_…

Corpo (JSON)

CampoTipoDescrição
itemsarrayItens do carrinho. Ao menos 1.
items[].namestringNome do produto.
items[].amountnúmeroPreço unitário em centavos (R$ 99,00 = 9900).
items[].quantitynúmeroQuantidade. Opcional: sem ela, assumimos 1.
items[].imagestringOpcional. URL https da foto, alcançável pela internet (endereço local ou de rede interna não vale, porque nosso servidor precisa abrir). Sem ela, o item aparece no checkout sem foto.
utmobjetoOpcional, mas leia o aviso abaixo. De qual anúncio veio a venda: source, medium, campaign, content, term. É o que credita a venda à campanha certa no seu relatório (UTMify e afins).
🔴 Sem o utm, TODA venda entra sem origem — e nada avisa. A UTM está no navegador do cliente (?utm_source=… na sua página) e esta chamada sai do seu servidor, que não a enxerga. Se o seu site não fizer o repasse, a venda entra normal e o seu relatório mostra a campanha vendendo zero. É o erro mais comum nesta integração.

São duas linhas no seu site. Guarde a UTM quando o cliente chega e mande junto quando ele fecha:

// 1) na carga de QUALQUER página do seu site
//    (o anúncio cai na home, mas a compra costuma acontecer noutra página)
const p = new URLSearchParams(location.search);
if (p.get("utm_source")) sessionStorage.setItem("utm", location.search);

// 2) no seu "Finalizar compra", manda pro SEU servidor junto com os itens
const q = new URLSearchParams(sessionStorage.getItem("utm") || "");
body.utm = { source: q.get("utm_source"), medium: q.get("utm_medium"), campaign: q.get("utm_campaign") };
// … e o seu servidor repassa esse mesmo objeto no POST /api/checkout

Alternativa mais simples, se preferir não mexer no servidor: acrescente os utm_* na url que a gente devolve, antes de redirecionar. O checkout também lê da própria URL.

const u = new URL(url);   // a url que o /api/checkout devolveu
new URLSearchParams(location.search).forEach((v, k) => {
  if (/^utm_|^gclid$|^fbclid$/.test(k)) u.searchParams.set(k, v);
});
location.href = u.toString();

Usando o snippet nextout-loja.js (Forma 2) você não precisa fazer nada disso: ele já guarda a atribuição sozinho.

🔴 O valor que você manda é o valor cobrado. A gente confia no amount porque só o seu servidor tem a chave secreta. Então o preço tem que ser calculado no seu servidor, nunca lido do carrinho que o navegador mandou. Se o preço vier do navegador, o cliente escolhe quanto vai pagar.

Exemplo

curl -X POST https://nextout.com.br/api/checkout \
  -H "Authorization: Bearer nx_sk_SUACHAVE" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"name":"Camiseta","amount":9900,"quantity":2}]}'

Resposta 200

{ "url": "https://nextout.com.br/?c=…" }

Redirecione o cliente para essa url. O checkout mostra os itens no valor que você mandou e cobra por PIX ou cartão. O link não expira: os itens e os preços ficam congelados nele como estavam na hora da criação.

⚠️ Confirmação de pagamento ainda não é automática. A API devolve o link e para aí: hoje não há webhook, nem campo pra você mandar o número do seu pedido, nem URL de retorno. Ou seja, o seu sistema não fica sabendo sozinho que o cliente pagou. Acompanhe pelo painel (aba Pedidos) até isso existir. Se você precisa disso pro seu fluxo, fale com a gente pelo painel.

Link curto

GEThttps://nextout.com.br/p/{codigo} redireciona para o checkout do produto/carrinho daquele código. O preço é sempre o atual do cadastro.

Erros da API

HTTPerrorO que houve
401Chave de API inválida.A chave está errada, faltando ou foi revogada. Gere outra no painel.
400Envie items…Faltou items no corpo.
400Itens inválidos…Nenhum item tem name e amount > 0. Lembre que amount é em centavos.
400Configure o domínio do seu checkout…A conta ainda não tem domínio de checkout cadastrado. É o erro mais comum na primeira integração, e não tem nada a ver com os itens. Resolva em Painel → Domínio (ver Antes de começar).
429Muitas requisições.O limite é de 120 chamadas por minuto por chave (e 240/min por IP). Aguarde e tente de novo.
405Use POST.O método tem que ser POST.

Segurança

  • Preço sempre no servidor. Shopify/Woo: reconferido na API da loja. Site próprio: vem do cadastro ou (na API) autenticado pela chave secreta. O navegador nunca decide o valor.
  • Cartão tokenizado no navegador. Número e CVV vão direto do browser para o gateway; o servidor do Nextout recebe só um token.
  • Credenciais cifradas. Chaves de gateway, de loja e de rastreamento ficam cifradas (AES-256-GCM). A chave de API do Site próprio é guardada só como hash.
  • Isolamento por loja. Cada seller só vê e usa o que ele mesmo conectou.