VenddorDocumentação API
API atualAPI legada
Guia rápidoReferência completa
Carregando índice…
API atual/Referência completa/Checkout

Validar e fechar o pedido

Confere a sessão de checkout sem criar nada e, depois, transforma a sessão em pedido de forma segura contra reenvio.

Estas são as duas últimas chamadas do checkout. Validar roda todas as conferências do fechamento (estoque, preço, frete, pagamento, cupom, pedido mínimo, regras do produto) e devolve a lista de problemas sem criar o pedido, então serve para avisar o comprador antes do clique final. Fechar (place) repete essas conferências, cria o pedido, baixa o estoque, registra o uso de cupom e esvazia as linhas do carrinho.

O fechamento não cobra o cartão por si só: ele cria o pedido com a forma de pagamento escolhida. O pagamento em si segue o fluxo da forma escolhida (PIX gera o QR, cartão passa pelo gateway da loja) e é tratado pela seção de pagamentos.

Validar a sessão

POST/api/v1/storefront/checkout/{sessionId}/validateAutenticada

Valida a sessão de checkout sem finalizar o pedido

Sem corpo. Responde sempre 200 quando a sessão existe; o campo valid diz se o pedido passaria. Os erros vêm em lista, cada um com o campo, um código estável e uma mensagem.

Parâmetros de caminho

sessionIduuidobrigatório
Id da sessão.

Exemplo de requisição

bash
curl -X POST "$BASE_URL/api/v1/storefront/checkout/$CHECKOUT_ID/validate" \
  -H "X-Session-ID: $SESSION_ID"

Resposta

200Sessão válida
json
{ "valid": true }
200Sessão com problemas
json
{
  "valid": false,
  "errors": [
    { "field": "items", "code": "insufficient_stock", "message": "Insufficient stock for 'Camisa do Flamengo': requested 1, available 0" },
    { "field": "subtotal", "code": "min_order_not_met", "message": "Minimum order amount is R$50.00, your cart total is R$30.00" }
  ]
}

O segundo exemplo ilustra o formato; as mensagens variam por situação.

Campos da resposta

validboolean
true quando o pedido passaria agora.
errorsarray
Problemas encontrados. Ausente quando valid é true.
errors[].fieldstring
itemscouponpayment_methodshipping_methodsubtotalcart
Parte da sessão afetada.
errors[].codestring
Código estável. Veja a tabela abaixo. Use o código para decidir a ação, não a mensagem.
errors[].messagestring
Texto para o desenvolvedor, em inglês ou português conforme a regra. Não exiba ao comprador; no fechamento do pedido use a message da resposta.
codeO que significaO que fazer
price_changedO preço de um item mudou desde que entrou no carrinho.Reabrir o resumo e pedir nova confirmação.
insufficient_stockNão há estoque para a quantidade pedida.Reduzir a quantidade ou remover a linha.
product_not_found, product_inactive, product_not_visible, product_not_available_for_userO produto saiu do ar ou o cliente não pode comprá-lo.Remover a linha.
zero_price_purchase_disabled, zero_price_quote_requiredProduto sem preço, que a loja não vende direto.Remover a linha ou pedir cotação.
qty_below_minimum, qty_above_maximum, qty_not_multiple_of_stepA quantidade viola a regra do produto.Ajustar a quantidade.
box_unavailableA embalagem exigida pelo produto não está disponível.Remover a linha ou escolher outra embalagem.
shipping_inactive, shipping_not_foundO frete escolhido não existe mais.Escolher o frete de novo.
payment_not_eligible, payment_eligibility_unavailableA forma de pagamento não vale para este pedido.Escolher outra forma de pagamento.
min_order_not_met, vendor_min_order_not_met, vendor_minimum_unavailableO pedido não atingiu o mínimo da loja ou de um seller.Adicionar itens.
coupon_invalid, coupon_validation_errorO cupom não vale mais.Remover o cupom.
empty_cartO carrinho ficou sem itens.Voltar ao carrinho.

Erros

StatusQuandoCorpo
400Falha ao rodar as conferências{"error":"..."}
404Sessão inexistente ou de outro dono{"error":"checkout session not found"}

Fechar o pedido

POST/api/v1/storefront/checkout/{sessionId}/placeAutenticada

Finaliza o pedido a partir da sessão de checkout

Exige endereço, frete (exceto carrinho só digital) e pagamento (exceto pedido totalmente coberto por vale-presente). Em seguida passa pelas barreiras da loja (código de verificação por e-mail, limite de crédito B2B, inadimplência, pedido mínimo, regras de produto), recalcula o preço e cria o pedido. O corpo é opcional.

Mande sempre um cabeçalho Idempotency-Key (UUID v4 novo para cada tentativa de compra). Se a mesma chave chegar de novo para a mesma sessão, a API devolve o mesmo pedido com status 200, sem criar outro. Se a primeira chamada ainda estiver em andamento, responde 409 com retry_after_ms. Reusar a chave com outra sessão é recusado com 422.

Parâmetros de caminho

sessionIduuidobrigatório
Id da sessão.

Cabeçalhos

Idempotency-Keystring
UUID v4 gerado pelo seu front-end, um por tentativa de compra. Recomendado.
X-Session-IDstring
Identificador do visitante, quando não há token.

Corpo da requisição

share_ref_codestring
Código de indicação do link compartilhado que trouxe o comprador. Opcional. Se faltar, a API usa o cookie venddor_ref da requisição.

Exemplo de requisição

bash
curl -X POST "$BASE_URL/api/v1/storefront/checkout/$CHECKOUT_ID/place" \
  -H "X-Session-ID: $SESSION_ID" \
  -H "Idempotency-Key: 3b241101-e2bb-4255-8caf-4136c566a962" \
  -H "Content-Type: application/json" \
  -d '{}'

Resposta

201Pedido criado
json
{
  "order": {
    "id": "6af86ed3-d949-474d-8e04-513c6e83bfe4",
    "order_number": "PEDIDO-20261011-0009",
    "customer_id": "264a70c1-9c69-458d-ac73-838543f87da2",
    "status": "O",
    "status_text": "pending",
    "subtotal": 30000,
    "shipping_total": 0,
    "tax_total": 0,
    "discount_total": 8625,
    "total": 21375,
    "currency": "BRL",
    "payment_method": "pix",
    "payment_status": "pending",
    "sales_channel": "web",
    "shipping_method": "Entrega Padrão",
    "customer_email": "maria.souza@example.com",
    "is_guest": true,
    "created_at": "2026-10-11T20:55:25.558277Z"
  },
  "items": [
    {
      "id": "a43b9f10-5590-424b-87c8-dffa34bae43d",
      "product_id": "22fbd12a-1b6e-41ea-a84f-4d9cf06c8766",
      "product_name": "Camisa do Flamengo Masculina I 26 Adidas",
      "product_sku": "FLA-I-26",
      "unit_price": 30000,
      "quantity": 1,
      "discount": 8625,
      "total": 21375
    }
  ],
  "addresses": [
    { "address_type": "shipping", "first_name": "Maria", "address_line1": "Av Paulista, 1000", "city": "São Paulo", "state": "SP", "postal_code": "01310-100", "country": "BR" }
  ],
  "status_history": []
}

O corpo é o detalhe do pedido, o mesmo formato de GET de pedido da API de loja (resumido acima). Os campos principais:

Campos da resposta

order.iduuid
Id do pedido. Guarde para acompanhar e para a tela de confirmação.
order.order_numberstring
Número mostrado ao comprador.
order.statusstring
Letra do status inicial (cada loja tem o seu alfabeto de status).
order.totalinteger
Total em centavos, igual ao total da sessão.
order.discount_totalinteger
Soma de todos os descontos em centavos (catálogo, cupom, PIX).
order.payment_methodstring
Código da forma de pagamento.
order.payment_statusstring
Estado do pagamento. Um PIX nasce pending até a confirmação.
itemsarray
Itens do pedido com preço unitário, desconto e total por linha, todos em centavos.
addressesarray
Endereços de entrega e de cobrança gravados no pedido.
status_historyarray
Histórico de status do pedido.
sub_ordersarray
Presente quando o carrinho tinha vários sellers: um sub-pedido por seller.

Erros

StatusQuandoCorpo
400Falta endereço, frete ou pagamento{"error":"shipping address is required"} (ou shipping method is required, payment method is required)
400Pedido mínimo da loja não atingido{"error":"O pedido mínimo da loja é R$ 50,00. Adicione mais itens para continuar."}
400Conferência falhou (estoque, regra do produto, cupom...){"error":"checkout_validation_failed","message":"...","errors":[{"field":"items","code":"insufficient_stock","message":"..."}]}
403Checkout de visitante foi desligado depois de abrir a sessão{"error":"guest checkout is not enabled"}
404Sessão inexistente, expirada ou de outro dono{"error":"checkout session not found"}
409O preço de um item mudou{"error":"checkout_validation_failed","message":"O preço de um item mudou. Confira o total e confirme o pedido de novo.","errors":[{"code":"price_changed",...}]}
409O carrinho já virou pedido{"error":"cart_already_ordered","message":"Este carrinho já foi transformado em pedido. ..."}
409Outra chamada deste mesmo pedido está em andamento{"error":"order_in_progress","retry_after_ms":1500} ou {"error":"in_progress","retry_after_ms":1500}
409Pedido igual feito há poucos minutos{"error":"duplicate_order","minutes_remaining":3,"order_number":"..."}
409O frete precisa ser cotado de novo{"error":"shipping_requote_required","message":"..."}
409O seller já recebeu pedido de outro cliente deste IP no prazo configurado{"error":"vendor_ip_restricted","vendor_name":"..."}
409Moeda estrangeira sem gateway internacional{"error":"no_international_gateway","currency":"USD","fallback":"BRL"}
412Falta verificar o e-mail por código{"error":"otp_required","scope":"checkout"}
412Limite de crédito B2B estourado{"error":"credit_limit_exceeded","limit":500000,"available":120000}
412Cliente B2B inadimplente{"error":"finance_delinquent"}
422Idempotency-Key já usada em outra sessão{"error":"idempotency key reused with a different checkout session"}
500Falha ao registrar a chave de idempotência{"error":"..."}

As message dos erros 409 e 400 que a API escreve para o comprador saem em português; o error é um código estável em inglês. Mostre a message ao comprador e use o error na sua lógica.

Trate o 409 price_changed como fluxo normal

Entre a abertura da sessão e o clique final o preço pode mudar (promoção que acabou, tabela de preços atualizada). A API recusa em vez de cobrar um valor que o comprador não viu. Reabra o resumo com GET /checkout/{sessionId}, mostre o novo total e permita fechar de novo.

Idempotência evita pedido duplicado

Gere o Idempotency-Key ao montar a tela de revisão e mantenha o mesmo valor em reenvios (timeout, rede caiu, duplo clique). Troque a chave só quando começar uma nova tentativa depois de uma recusa definitiva. Uma resposta 200 com o pedido, em vez de 201, indica que a chamada foi um reenvio reconhecido.

Sessão consumida

Depois do fechamento, o carrinho perde as linhas pedidas. Para uma nova compra comece de novo pelo carrinho. O pagamento de PIX e cartão do pedido já criado é tratado na seção de pagamentos, não aqui.

Veja também

  • Endereço, frete e pagamento
  • Iniciar e ler o checkout
  • Comprar de novo um pedido
Anterior
Cupom e vale-presente no checkout
Próxima
Verificação KYC
Nesta página
  • Validar a sessão
  • Exemplo de requisição
  • Resposta
  • Erros
  • Fechar o pedido
  • Exemplo de requisição
  • Resposta
  • Erros
  • Veja também