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
/api/v1/storefront/checkout/{sessionId}/validateAutenticadaValida 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órioExemplo de requisição
curl -X POST "$BASE_URL/api/v1/storefront/checkout/$CHECKOUT_ID/validate" \
-H "X-Session-ID: $SESSION_ID"Resposta
{ "valid": true }{
"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
validbooleantrue quando o pedido passaria agora.errorsarrayvalid é true.errors[].fieldstringitemscouponpayment_methodshipping_methodsubtotalcarterrors[].codestringerrors[].messagestringmessage da resposta.code | O que significa | O que fazer |
|---|---|---|
price_changed | O preço de um item mudou desde que entrou no carrinho. | Reabrir o resumo e pedir nova confirmação. |
insufficient_stock | Nã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_user | O produto saiu do ar ou o cliente não pode comprá-lo. | Remover a linha. |
zero_price_purchase_disabled, zero_price_quote_required | Produto 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_step | A quantidade viola a regra do produto. | Ajustar a quantidade. |
box_unavailable | A embalagem exigida pelo produto não está disponível. | Remover a linha ou escolher outra embalagem. |
shipping_inactive, shipping_not_found | O frete escolhido não existe mais. | Escolher o frete de novo. |
payment_not_eligible, payment_eligibility_unavailable | A 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_unavailable | O pedido não atingiu o mínimo da loja ou de um seller. | Adicionar itens. |
coupon_invalid, coupon_validation_error | O cupom não vale mais. | Remover o cupom. |
empty_cart | O carrinho ficou sem itens. | Voltar ao carrinho. |
Erros
| Status | Quando | Corpo |
|---|---|---|
| 400 | Falha ao rodar as conferências | {"error":"..."} |
| 404 | Sessão inexistente ou de outro dono | {"error":"checkout session not found"} |
Fechar o pedido
/api/v1/storefront/checkout/{sessionId}/placeAutenticadaFinaliza 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órioCabeçalhos
Idempotency-KeystringX-Session-IDstringCorpo da requisição
share_ref_codestringvenddor_ref da requisição.Exemplo de requisição
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
{
"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.iduuidorder.order_numberstringorder.statusstringorder.totalintegertotal da sessão.order.discount_totalintegerorder.payment_methodstringorder.payment_statusstringpending até a confirmação.itemsarrayaddressesarraystatus_historyarraysub_ordersarrayErros
| Status | Quando | Corpo |
|---|---|---|
| 400 | Falta endereço, frete ou pagamento | {"error":"shipping address is required"} (ou shipping method is required, payment method is required) |
| 400 | Pedido mínimo da loja não atingido | {"error":"O pedido mínimo da loja é R$ 50,00. Adicione mais itens para continuar."} |
| 400 | Conferência falhou (estoque, regra do produto, cupom...) | {"error":"checkout_validation_failed","message":"...","errors":[{"field":"items","code":"insufficient_stock","message":"..."}]} |
| 403 | Checkout de visitante foi desligado depois de abrir a sessão | {"error":"guest checkout is not enabled"} |
| 404 | Sessão inexistente, expirada ou de outro dono | {"error":"checkout session not found"} |
| 409 | O 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",...}]} |
| 409 | O carrinho já virou pedido | {"error":"cart_already_ordered","message":"Este carrinho já foi transformado em pedido. ..."} |
| 409 | Outra chamada deste mesmo pedido está em andamento | {"error":"order_in_progress","retry_after_ms":1500} ou {"error":"in_progress","retry_after_ms":1500} |
| 409 | Pedido igual feito há poucos minutos | {"error":"duplicate_order","minutes_remaining":3,"order_number":"..."} |
| 409 | O frete precisa ser cotado de novo | {"error":"shipping_requote_required","message":"..."} |
| 409 | O seller já recebeu pedido de outro cliente deste IP no prazo configurado | {"error":"vendor_ip_restricted","vendor_name":"..."} |
| 409 | Moeda estrangeira sem gateway internacional | {"error":"no_international_gateway","currency":"USD","fallback":"BRL"} |
| 412 | Falta verificar o e-mail por código | {"error":"otp_required","scope":"checkout"} |
| 412 | Limite de crédito B2B estourado | {"error":"credit_limit_exceeded","limit":500000,"available":120000} |
| 412 | Cliente B2B inadimplente | {"error":"finance_delinquent"} |
| 422 | Idempotency-Key já usada em outra sessão | {"error":"idempotency key reused with a different checkout session"} |
| 500 | Falha 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.