Buscar en la documentación
ctrl+4K
Módulos
Authentication
Merchant
Catalog
Order
Events
Logistics
Shipping
Review
Financial
Soluciones

Erros e troubleshooting

Diagnostique, resolva e previna problemas comuns ao integrar com a API de Promotion.
CódigoStatusSignificadoAção
202AcceptedRequisição enfileirada para processamentoConsulte GET com aggregationId para status real
400Bad RequestErro de validação no payloadRevise campos obrigatórios e formato
401UnauthorizedToken JWT inválido ou expiradoRenovar token de acesso
404Not FoundLoja (merchantId) ou agregação não existeVerificar os IDs
412Precondition FailedValidação falhou (ex: formato de data)Verificar campos e formatos
429Too Many RequestsLimite de requisições excedidoImplementar backoff exponencial
500Internal Server ErrorErro no backendContatar suporte com aggregationId

Quando uma promoção tem status ERROR, o campo error contém um código específico:
CódigoSignificadoSolução
DATE_INVALIDData em formato inválido ou finalDate < initialDateUse ISO 8601 (YYYY-MM-DD) e garanta initialDatefinalDate
PROMOTION_TYPE_INVALIDTipo não reconhecidoUsar PERCENTAGE, LXPY ou PERCENTAGE_PER_X_UNITS
DISCOUNT_INVALIDDesconto > 70% ou campos faltantesVerificar regras de validação por tipo
ITEM_NOT_FOUNDEAN não existe ou produto inativoValidar EAN e confirmar que produto está ativo
DUPLICATE_ITEMMesmo EAN e período já existeVerificar promoções existentes com GET ou usar reset=true
INVALID_CHANNELCanal não válidoUsar canais válidos (ex: IFOOD-APP)
INTERNAL_ERRORFalha no backendAguardar e reenviar. Se persistir, contatar suporte
Cada cenário abaixo inclui sintomas, diagnóstico e solução prática com exemplos de código.Sintomas: Você criou uma promoção, mas ela não aparece no aplicativo do cliente.Diagnóstico:Verifique o status da promoção:
curl -X GET "https://merchant-api.ifood.com.br/promotion/v1.0/merchants/{merchantId}/promotions/{aggregationId}/items" \
  -H "Authorization: Bearer {TOKEN}"
Analise o campo status:
  • PROCESSING → Ainda sendo validada. Aguarde 2-3 segundos.
  • ERROR → Verifique campo error para código específico.
  • ACTIVE → Validada, mas pode não estar visível em pedidos.
Solução:
  1. Se PROCESSING: Aguarde alguns segundos e consulte novamente
    sleep 3
    curl -X GET "https://merchant-api.ifood.com.br/promotion/v1.0/merchants/{merchantId}/promotions/{aggregationId}/items" \
      -H "Authorization: Bearer {TOKEN}"
  2. Se ERROR: Consulte o código no campo error
    {
      "promotions": [
        {
          "status": "ERROR",
          "error": "DATE_INVALID"
        }
      ]
    }
  3. Se ACTIVE: Prossiga para "Desconto não aparece em pedidos" abaixo.
Sintomas: A requisição POST retorna 202 (sucesso), mas o status permanece PROCESSING ou ERROR indefinidamente.Causas prováveis:
  • Processamento assíncrono ainda em andamento (primeiras tentativas)
  • EAN incorreto ou não existe no catálogo
  • Data em formato inválido
  • Desconto superior a 70%
  • Campos obrigatórios para o tipo de promoção faltando
Solução:
  1. Aguarde tempo adequado após POST
    • Primeiras tentativas (0-10s): Pode estar em PROCESSING
    • Após 30s: Se ainda PROCESSING, investigar
    sleep 10
    curl -X GET "https://merchant-api.ifood.com.br/promotion/v1.0/merchants/{merchantId}/promotions/{aggregationId}/items" \
      -H "Authorization: Bearer {TOKEN}"
  2. Se o status for ERROR, verifique o código:
    curl -X GET "https://merchant-api.ifood.com.br/promotion/v1.0/merchants/{merchantId}/promotions/{aggregationId}/items?status=ERROR" \
      -H "Authorization: Bearer {TOKEN}"
  3. Corrija o payload baseado no código de erro
    curl -X POST "https://merchant-api.ifood.com.br/promotion/v1.0/merchants/{merchantId}/promotions" \
      -H "Authorization: Bearer {TOKEN}" \
      -H "Content-Type: application/json" \
      -d '{
        "aggregationTag": "promo-corrigido-001",
        "promotions": [ ... ]
      }'
  4. Use novo aggregationTag para cada tentativa (não reutilize anterior).
Sintomas: A promoção tem status ACTIVE, mas o cliente não vê o desconto aplicado ao fazer uma compra.Causas prováveis:
  • Outra promoção com desconto maior está ativa para o mesmo item
  • Regras de elegibilidade da loja excluem o item
  • Desconto não foi aplicado à categoria correta
Diagnóstico:
  1. Verifique se há múltiplas promoções ativas para este EAN
    curl -X GET "https://merchant-api.ifood.com.br/promotion/v1.0/merchants/{merchantId}/promotions/{aggregationId}/items?ean=7891234567890&status=ACTIVE" \
      -H "Authorization: Bearer {TOKEN}"
  2. Crie um pedido de teste e verifique o benefício aplicado
    # Consultar detalhes do pedido
    curl -X GET "https://merchant-api.ifood.com.br/order/v1.0/merchants/{merchantId}/orders/{orderId}/virtual-bag" \
      -H "Authorization: Bearer {TOKEN}"
  3. Analise a resposta procurando por:
    {
      "bag": {
        "benefits": {
          "benefits": [
            {
              "target": "ITEM",
              "targetId": "7891234567890",
              "sponsorships": [
                {
                  "liability": "PARTNER",
                  "amount": {
                    "value": 5.00
                  }
                }
              ]
            }
          ]
        }
      }
    }
Solução:
  1. Se múltiplas promoções: A plataforma aplica o desconto maior automaticamente
    • Remova promoções conflitantes usando reset=true
    • Ou ajuste os descontos para não competir
  2. Se desconto não aparece: Verifique regras de negócio
Sintomas: Requisições retornam 429 Too Many Requests.Causa: Limite de requisições por unidade de tempo foi excedido.Solução:Implemente backoff exponencial para retries:
#!/bin/bash

# Exemplo de retry com backoff exponencial
function call_api_with_retry() {
  local url="$1"
  local data="$2"
  local attempt=1
  local max_attempts=5

  while [ $attempt -le $max_attempts ]; do
    # Fazer a requisição
    response=$(curl -s -w "\n%{http_code}" -X POST "$url" \
      -H "Authorization: Bearer {TOKEN}" \
      -H "Content-Type: application/json" \
      -d "$data")

    # Extrair código HTTP
    http_code=$(echo "$response" | tail -n1)
    body=$(echo "$response" | head -n-1)

    if [ "$http_code" != "429" ]; then
      echo "$body"
      return 0
    fi

    # Calcular tempo de espera: 2^attempt segundos
    wait_time=$((2 ** attempt))
    echo "Rate limited. Aguardando ${wait_time}s antes da tentativa $((attempt + 1))..." >&2
    sleep "$wait_time"

    ((attempt++))
  done

  echo "Falha após $max_attempts tentativas" >&2
  return 1
}
Prevenção:
  • Não faça requisições em paralelo em massa
  • Implemente fila com delay entre requisições
  • Monitore a taxa de requisições da sua aplicação
Sintomas: Todas as requisições retornam 401 Unauthorized.Causas:
  • Token JWT expirou
  • Token foi revogado
  • Token não tem escopo necessário
Solução:
  1. Renove o token de acesso
    curl -X POST "https://oauth.ifood.com.br/oauth/authorize" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "grant_type=client_credentials&client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}"
  2. Reenvie com novo token
    curl -X GET "https://merchant-api.ifood.com.br/promotion/v1.0/merchants/{merchantId}/promotions/{aggregationId}/items" \
      -H "Authorization: Bearer {NEW_TOKEN}"
Prevenção:
  • Renove token antes de expiração (ex: 5 minutos antes)
  • Configure alertas de expiração próxima
  • Não reutilize tokens por muito tempo

Valide dados antes de fazer a requisição:
function validatePromotion(promo) {
  // Validar formato de data
  const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
  if (!dateRegex.test(promo.initialDate)) {
    throw new Error('Data inválida: use YYYY-MM-DD');
  }

  // Validar datas lógicas
  if (new Date(promo.initialDate) > new Date(promo.finalDate)) {
    throw new Error('initialDate não pode ser posterior a finalDate');
  }

  // Validar desconto
  if (promo.discountValue > 70) {
    throw new Error('Desconto não pode exceder 70%');
  }

  // Validar tipo de promoção
  const validTypes = ['PERCENTAGE', 'LXPY', 'PERCENTAGE_PER_X_UNITS'];
  if (!validTypes.includes(promo.promotionType)) {
    throw new Error(`Tipo inválido. Use: ${validTypes.join(', ')}`);
  }

  return true;
}
Registre informações úteis para troubleshooting:
function logPromotion(action, data, response) {
  console.log(JSON.stringify({
    timestamp: new Date().toISOString(),
    action: action,
    aggregationId: data.aggregationTag || response.aggregationId,
    merchantId: data.merchantId,
    itemCount: data.promotions?.[0]?.items?.length || 0,
    httpCode: response.status,
    errorCode: response.error,
  }, null, 2));
}
const retryConfig = {
  maxAttempts: 3,
  initialDelayMs: 1000,
  backoffMultiplier: 2,
  retryableStatusCodes: [429, 500, 502, 503, 504],
};

async function makeRequestWithRetry(fn, config = retryConfig) {
  let attempt = 1;
  let delayMs = config.initialDelayMs;

  while (attempt <= config.maxAttempts) {
    try {
      return await fn();
    } catch (error) {
      if (!config.retryableStatusCodes.includes(error.statusCode)) {
        throw error; // Não é retentável
      }

      if (attempt === config.maxAttempts) {
        throw error; // Última tentativa
      }

      await sleep(delayMs);
      delayMs *= config.backoffMultiplier;
      attempt++;
    }
  }
}
Configure alertas para:
  • Taxa de erros acima de X%
  • Latência de resposta acima de limite
  • Erros 5xx ou 429 recorrentes
  • Promoções que ficam em PROCESSING por muito tempo
Após resolver erros:
¿Esta página fue útil?
Evalúa tu experiencia en el nuevo portal de desarrolladores: