Cursos Magento

Guest checkout bloqueado na API REST do Magento 2? Confira isso.

,

Publicado em 07 de julho de 2026

Semana passada apareceu um caso clássico de “configuração certa, mas erro mesmo assim”.

Limpei caches, conferi opcache, core_config_data, e nada.

Checkout de visitantes habilitado no admin (Vendas → Checkout → Permitir compra sem login), carrinho guest criado normalmente via API, mas na hora de chamar o endpoint de shipping information… boom:

{
    "message": "Sinto muito, a compra por convidados não está disponível."
}

Se você integra Magento com PWA, app mobile ou qualquer checkout headless, provavelmente já passou por algo parecido — ou vai passar em breve, especialmente se estiver no Magento 2.4.8+.

Vou contar o que descobri, porque a mensagem engana, e como resolver de verdade.

O sintoma

Você cria o carrinho guest:

POST /rest/default/V1/guest-carts

Adiciona produtos, define endereço, e na sequência:

POST /rest/default/V1/guest-carts/{cartId}/shipping-information

A resposta vem com erro 400 e a mensagem traduzida acima.

No stack trace (se você olhar com calma), aparece algo assim:

Magento\Checkout\Plugin\Api\VerifyIsGuestCheckoutEnabledBeforeSaveShippingInformation
  ->beforeSaveAddressInformation(...)

Ou seja: não é bug do seu módulo de pagamento, nem do tema, nem do PWA. É validação nativa do Magento.

A primeira suspeita (e por que ela engana)

Obviamente a primeira coisa que todo mundo checa é a config:

Vendas → Checkout → Opções de Checkout → Permitir compra sem login

No banco, isso corresponde a:

checkout/options/guest_checkout

No meu caso:

  • Config no escopo default: 1
  • Config no escopo stores (store_id 1): 1
  • bin/magento config:show checkout/options/guest_checkout --scope=stores --scope-code=default → 1
  • Carrinho com store_id = 1customer_is_guest = 1

Tudo certo. E mesmo assim o erro persistia.

Aqui mora a pegadinha: existem duas regras diferentes, e só a primeira aparece na tela que todo mundo olha.

O que realmente acontece por baixo dos panos

A partir do Magento 2.4.8, o core passou a validar guest checkout também na REST API — não só no checkout tradicional do frontend.

O plugin responsável é o VerifyIsGuestCheckoutEnabledBeforeSaveShippingInformation, que roda antes de salvar o endereço de entrega em:

GuestShippingInformationManagement::saveAddressInformation()

A lógica é simples:

if (!$this->checkoutHelper->isAllowedGuestCheckout($quote)) {
    throw new CouldNotSaveException(__('Sorry, guest checkout is not available.'));
}

Até aqui, tudo previsível. O problema é o que entra dentro de isAllowedGuestCheckout().

Esse helper não olha só a config checkout/options/guest_checkout. Quando ela está habilitada, ele dispara o evento:

checkout_allow_guest

E é aí que entra o módulo Downloadable.

A mudança que pegou muita gente de surpresa (2.4.8+)

Em versões anteriores, o observer que bloqueia guest checkout por causa de produtos downloadáveis rodava basicamente no frontend.

No 2.4.8-p3, a Adobe registrou o observer também em:

  • etc/webapi_rest/events.xml
  • etc/graphql/events.xml

Ou seja: headless também passa por essa validação agora.

O observer é o Magento\Downloadable\Observer\IsAllowedGuestCheckoutObserver.

Ele percorre os itens do carrinho. Se encontrar produto do tipo downloadable, verifica:

  1. catalog/downloadable/disable_guest_checkout — por padrão vem 1 (Sim)
  2. Se os links do produto são shareable (compartilháveis)

Se qualquer condição falhar, ele faz:

$result->setIsAllowed(false);

E pronto: guest checkout bloqueado, mesmo com “Permitir compra sem login” habilitado no admin.

Por que a mensagem é tão genérica?

Porque o plugin lança sempre a mesma exceção:

Sorry, guest checkout is not available.

Traduzida no pt_BR:

Sinto muito, a compra por convidados não está disponível.

Não diz “seu carrinho tem produto downloadable”. Não aponta qual config resolver. Você fica caçando fantasma na config de checkout — exatamente o que aconteceu conosco.

Como diagnosticar em 2 minutos

1. Confirme se o carrinho tem produto downloadable

SELECT qi.item_id, qi.sku, qi.name, p.type_id

FROM quote_item qi

JOIN quote_id_mask m ON m.quote_id = qi.quote_id

JOIN catalog_product_entity p ON p.entity_id = qi.product_id

WHERE m.masked_id = ‘SEU_MASKED_CART_ID’;

Se aparecer type_id = downloadable, você achou o culpado.

2. Confira as configs do módulo Downloadable

bin/magento config:show catalog/downloadable/disable_guest_checkout --scope=stores --scope-code=default

bin/magento config:show catalog/downloadable/shareable --scope=stores --scope-code=default

Valores padrão do Magento:

ConfigPathDefault
Desabilitar guest checkout com downloadáveiscatalog/downloadable/disable_guest_checkout1 (Sim)
Links compartilháveiscatalog/downloadable/shareable0 (Não)

Ou seja: por padrão, guest checkout + downloadable = bloqueado. E isso é intencional.

3. Confirme que a config geral de guest checkout está OK (para descartar)

bin/magento config:show checkout/options/guest_checkout –scope=stores –scope-code=default

Se retornar 1 e o erro continuar com downloadable no carrinho, o caso está fechado.

Como resolver (depende da regra de negócio)

Opção A — Permitir guest checkout com produtos downloadáveis

Admin:

Catálogo → Opções de Produto para Download → Desabilitar checkout de convidado se o carrinho contiver itens para download → Não

Ou via CLI:

bin/magento config:set catalog/downloadable/disable_guest_checkout 0 --scope=stores --scope-code=default

bin/magento cache:flush config

Use isso se você quer vender arquivos digitais sem exigir cadastro.

Opção B — Exigir login para downloadáveis (padrão recomendado)

Mantenha disable_guest_checkout = 1 e oriente o cliente a criar conta ou fazer login antes do checkout.

Faz sentido quando:

  • O link de download precisa ficar associado a um customer
  • Você quer reduzir fraude ou abuso de links
  • A entrega digital depende de área logada do cliente

Se quiser manter a regra, mas liberar guest checkout para certos produtos:

  1. Catálogo → Opções de Produto para Download → Shareable → Sim
  2. No produto downloadable, configure os links como Shareable

É mais granular, porém exige atenção em cada produto.

Opção D — Testar checkout guest sem downloadable

Para isolar o problema durante desenvolvimento, monte um carrinho só com produtos simples/virtual. Se funcionar, confirma o diagnóstico.

Resumo das configs envolvidas

O que você olha no adminPathO que faz
Permitir compra sem logincheckout/options/guest_checkoutHabilita guest checkout em geral
Desabilitar guest checkout com downloadáveiscatalog/downloadable/disable_guest_checkoutBloqueia guest se o carrinho tiver downloadable
Shareablecatalog/downloadable/shareableDefine se links podem ser compartilháveis

Guest checkout habilitado ≠ guest checkout permitido para qualquer carrinho.

Lições aprendidas

  1. No 2.4.8+, REST e GraphQL validam guest checkout de verdade — não dá mais para assumir que “se funciona no frontend, funciona na API”.
  2. Mensagens genéricas custam horas de debug — essa aqui deveria mencionar downloadable ou apontar a config certa.
  3. Sempre olhe o stack trace — o plugin VerifyIsGuestCheckoutEnabledBeforeSaveShippingInformation entrega a pista imediata.
  4. Produto downloadable muda as regras do jogo — especialmente relevante para quem vende cursos, ebooks, plugins, temas, arquivos PDF, etc.

Conclusão

Se você habilitou checkout de visitantes, conferiu o banco, limpou cache, e o erro continua na API REST — olhe o carrinho.

Tem produto downloadable? Então o bloqueio provavelmente vem do módulo Downloadable, não da config de checkout que todo mundo checa primeiro.

No nosso caso, era exatamente isso. Config certa, carrinho certo, store certa — e um observer silencioso dizendo “não” por causa do tipo de produto.

Espero que esse post economize umas boas horas de debug na sua próxima integração headless.

Comentários