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
- O cliente monta o carrinho na sua loja.
- Ao clicar em finalizar, ele é levado ao checkout do Nextout com o carrinho.
- O servidor do Nextout confere o preço de cada item. O navegador nunca decide o valor. É isso que impede fraude.
- O cliente paga (PIX ou cartão). O pedido nasce na sua loja e recebe a baixa quando o pagamento cai.
Shopify
Conexão em um clique, via instalação do app.
- 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).
- 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
- Em WooCommerce → Configurações → Avançado → API REST, crie uma chave com permissão Leitura/Escrita. Guarde a Consumer Key e a Consumer Secret.
- No painel Nextout, Integrações → WooCommerce, cole a URL da loja e as duas chaves.
- Baixe e instale o plugin: nextout-woocommerce.zip (WordPress → Plugins → Enviar plugin → Ativar).
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 1 · Link e botão sem código
No painel, em Produtos, cadastre um produto (nome, preço, foto). O Nextout gera:
- Um link curto pra jogar na bio, story ou anúncio:
https://nextout.com.br/p/abc123(ou no seu domínio, se você tiver um). - Um botão HTML pronto pra colar no seu site.
O link abre o checkout com aquele produto, no preço que você cadastrou. Se você mudar o preço, o mesmo link já reflete o novo. Ele nunca fica desatualizado.
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
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).
- No painel, Produtos → Integração via API, gere a chave (começa com
nx_sk_). Ela é mostrada uma vez. Guarde. - No servidor do seu site, chame a API de checkout (abaixo) com os itens do carrinho.
- Redirecione o cliente para a
urlque a API devolve.
Reference completa em API de checkout.
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.
| Gateway | Aceita | Como conectar |
|---|---|---|
| AFEX Pay | PIX + cartão até 12× | Cole a chave secreta (ak_live_…) e a chave pública (pk_…). |
| pagou.ai | PIX + cartão | Chave secreta + pública (v1) ou chave única (v2). |
| Appmax em breve | — | Integração em homologação. |
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.
- Baixe e instale: nextout-envios.zip (WordPress → Plugins → Enviar plugin → Ativar).
- Vá em WooCommerce → Configurações → Entrega, abra a sua zona de entrega e clique em Adicionar método → Nextout Envios.
- 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.
- No painel, item Domínio, digite o endereço (recomendamos um subdomínio, ex.:
checkout.sualoja.com.br). - Crie o registro DNS que o painel indicar, no seu provedor de domínio:
| Tipo | Quando | Valor |
|---|---|---|
CNAME | subdomínio (checkout.sualoja.com.br) | cname.vercel-dns.com |
A | domínio raiz (sualoja.com.br) | 76.76.21.21 |
O HTTPS é emitido sozinho quando o DNS propaga (de alguns minutos a algumas horas).
Rastreamento · UTMify
Saiba qual anúncio trouxe cada venda. O Nextout envia sozinho cada pedido (pendente e pago) para a UTMify, com as UTMs.
- Na UTMify: Integrações → Webhooks → Credenciais de API → Criar.
- 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
| Evento | Quando dispara |
|---|---|
pedido.criado | O cliente fechou o pedido no checkout. Ainda não pagou. |
pedido.pago | O pagamento foi aprovado. É o evento que a maioria usa. |
pedido.recusado | O cartão do cliente foi negado. Estorno não entra aqui. |
pedido.enviado | A 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.
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();
});
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.
id do evento e ignore repetido, que é o que se chama de tratamento idempotente.Regras do endereço
- Precisa ser
https. Recusamoshttpporque 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é-requisito | Onde | Se 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)
| Campo | Tipo | Descrição |
|---|---|---|
items | array | Itens do carrinho. Ao menos 1. |
items[].name | string | Nome do produto. |
items[].amount | número | Preço unitário em centavos (R$ 99,00 = 9900). |
items[].quantity | número | Quantidade. Opcional: sem ela, assumimos 1. |
items[].image | string | Opcional. 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. |
utm | objeto | Opcional, 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). |
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.
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.
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
| HTTP | error | O que houve |
|---|---|---|
401 | Chave de API inválida. | A chave está errada, faltando ou foi revogada. Gere outra no painel. |
400 | Envie items… | Faltou items no corpo. |
400 | Itens inválidos… | Nenhum item tem name e amount > 0. Lembre que amount é em centavos. |
400 | Configure 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). |
429 | Muitas requisições. | O limite é de 120 chamadas por minuto por chave (e 240/min por IP). Aguarde e tente de novo. |
405 | Use 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.