Bom de Lance

Integração de estoque

Referência para gestores de estoque e integradores de anúncios.

Documentação para gestores de estoque e integradores de anúncios publicarem o estoque das lojas clientes no Bom de Lance.

Base: https://www.bomdelance.com.br/api/integracao/v1

Tudo é JSON, em UTF-8. Todas as respostas trazem sucesso (booleano) e, quando algo não deu certo, erro com uma frase em português explicando o que fazer.


Autenticação

O lojista gera um código de acesso dentro do painel dele, em Meus anúncios → Conectar meu sistema de estoque, e cola no sistema de vocês.

Authorization: Bearer bdl_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

O código identifica a loja. Não existe campo de identificação de loja em nenhuma chamada — quem manda o código já disse de qual pátio está falando.

O lojista pode gerar outro código ou desligar o recebimento a qualquer momento. Nos dois casos, as chamadas passam a responder 401.


O modelo: remessa

Uma remessa é o estoque completo da loja naquele momento, não um delta.

1. abre a remessa           POST /remessas
2. envia os veículos        POST /remessas/{uuid}/veiculos     (repita quantas vezes precisar)
3. fecha declarando o total POST /remessas/{uuid}/fechar
4. consulta o resultado     GET  /remessas/{uuid}

Veículo que estava na remessa anterior e não está nesta é considerado vendido e sai do ar. Não é preciso mandar exclusão.

Por que declarar o total no fechamento

É a única forma de sabermos que a remessa chegou inteira. Uma conexão que caiu no lote 3 de 7 é, do nosso lado, idêntica a uma loja que ficou com 400 carros a menos — e a segunda leitura apagaria os anúncios que se perderam no caminho.

Se total_declarado não bater com o número de veículos distintos recebidos, a remessa fica inconsistente e nada é aplicado ao estoque.


1. Abrir remessa

POST /remessas
Authorization: Bearer <código>
Idempotency-Key: 2026-08-10T03:00:00Z-loja42      (opcional, recomendado)
{
  "sucesso": true,
  "remessa": "9f1c8f2e-...",
  "situacao": "aberta",
  "itens_por_lote": 500,
  "veiculos_por_remessa": 5000,
  "expira_em_horas": 6
}

Use o Idempotency-Key. Com ele, repetir a chamada devolve a mesma remessa em vez de criar outra. Sem ele, um timeout na resposta faz vocês reabrirem — e a segunda remessa, vazia porque os carros foram para a primeira, seria lida como "a loja esvaziou o pátio".

Só existe uma remessa aberta por vez por loja. Se houver outra em aberto, a resposta é 409 com o identificador dela. Remessas abandonadas expiram em 6 horas.

2. Enviar veículos

POST /remessas/{uuid}/veiculos
{
  "veiculos": [
    {
      "id_externo": "12345",
      "marca": "FIAT",
      "modelo": "ARGO",
      "versao": "1.0 FIREFLY FLEX DRIVE MANUAL",
      "ano_fabricacao": 2022,
      "ano_modelo": 2023,
      "preco": "74.900,00",
      "km": 32000,
      "combustivel": "Flex",
      "cambio": "Manual",
      "cor": "Branco",
      "portas": 4,
      "tipo": "carro",
      "zero_km": false,
      "descricao": "Único dono, revisões na concessionária.",
      "opcionais": ["Ar-condicionado", "Direção elétrica", "Câmera de ré"],
      "unico_dono": true,
      "ipva_pago": true,
      "aceita_troca": true,
      "blindado": false,
      "fotos": [
        "https://cdn.exemplo.com/12345-1.jpg",
        "https://cdn.exemplo.com/12345-2.jpg"
      ]
    }
  ]
}

Os campos

Campo Obrigatório Observação
id_externo sim O identificador do veículo no sistema de vocês. É por ele que sabemos se o carro é novo, mudou ou sumiu.
marca, modelo sim Texto.
versao não, mas decisivo É o que faz o carro casar com a versão certa da tabela FIPE. Sem ela, a chance de recusa sobe muito.
ano_modelo sim Sem o ano não há como achar a versão na FIPE.
ano_fabricacao não
preco sim Aceita "74.900,00", "74900.00" e 74900.
km não Número ou texto com pontuação.
combustivel não, mas ajuda É o desempate quando duas versões da FIPE são igualmente parecidas.
tipo não carro, moto ou caminhao. Sem ele, uma moto pode casar com um carro da mesma marca.
fotos não Até 50 endereços por veículo; publicamos até 20.
descricao não Ver a regra de preço na descrição, mais abaixo.

Não mandem placa, chassi, CPF, CNPJ nem nome de proprietário. Não usamos, e não guardamos.

Cada chamada aceita até 500 veículos. Mandem quantos lotes precisarem dentro da mesma remessa. O mesmo id_externo repetido na mesma remessa substitui o anterior e conta como um.

{ "sucesso": true, "recebidos_nesta_chamada": 500, "total_na_remessa": 500 }

3. Fechar

POST /remessas/{uuid}/fechar
{ "total_declarado": 500 }
{
  "sucesso": true,
  "remessa": "9f1c8f2e-...",
  "situacao": "recebendo",
  "total_declarado": 500,
  "total_recebido": 500,
  "explicacao": "Fechada e conferida. Os veículos estão sendo publicados."
}

A publicação acontece em segundo plano (baixamos e convertemos as fotos de cada veículo). Consultem a remessa alguns minutos depois para ver o resultado.

4. Consultar

GET /remessas/{uuid}
{
  "sucesso": true,
  "situacao": "aplicada",
  "explicacao": "Publicada: 487 no ar, 13 recusados, 4 removidos.",
  "importados": 487,
  "recusados": 13,
  "removidos": 4,
  "recusas": [
    {
      "id_externo": "12876",
      "veiculo": "FIAT ARGO 1.0 2023",
      "motivo": "Encontrei 2 versões parecidas na FIPE e não dá para saber qual é a certa."
    }
  ]
}

As situações

situacao O que significa
aberta Aceitando veículos.
recebendo Fechada e conferida, publicando.
aplicada Publicada.
inconsistente A contagem não bateu. Nada foi alterado. Reenviem a remessa inteira.
bloqueada Os novos entraram e nenhuma remoção foi feita — ver as salvaguardas.
expirada Ficou aberta mais de 6 horas. Abram outra.
falha Quebrou do nosso lado. O que já entrou continua no ar; reenviem.

As salvaguardas de remoção

Gravar é seguro, remover é perigoso. Um envio que falhou no meio e uma loja que vendeu meio pátio chegam aqui com a mesma cara. Na dúvida, gravamos o que veio e não removemos nada.

Situação O que acontece
Remessa vazia com estoque no ar Bloqueia. Nem com autorização do lojista.
Sumiram mais de 30% dos veículos Bloqueia até o lojista autorizar na tela dele.
Sumiram menos de 5 veículos O percentual não se aplica (loja pequena vende 2 de 6).
Anúncio com negociação em andamento Nunca é removido, nem com autorização.

Quando bloqueia, os veículos novos entram normalmente — só as remoções ficam pendentes, e o lojista vê o motivo e o botão de autorizar no painel dele.


Por que um veículo é recusado

O casamento com a tabela FIPE é obrigatório. O Bom de Lance vende análise de preço; um veículo sem código FIPE ocuparia vaga do plano da loja sem fazer a única coisa pela qual ela paga.

Como o código FIPE não costuma existir no cadastro de vocês, o casamento é por texto — marca, modelo, versão e ano. E ele recusa em vez de escolher o mais parecido: um Civic publicado como City é pior que um carro que não entrou.

Os motivos mais comuns, e o que resolve cada um:

Motivo O que fazer
"Não encontrei este veículo na tabela FIPE de 2023" Conferir marca, modelo e ano no cadastro.
"Encontrei N versões parecidas e não dá para saber qual é a certa" Mandar a versao completa, e o combustivel.
"Achei no catálogo, mas ainda está sem código FIPE aqui" É do nosso lado; o catálogo se completa sozinho.
"Limite de anúncios do plano atingido" O lojista precisa subir de plano.
"Já existe um anúncio idêntico" O mesmo veículo com o mesmo preço já está no ar.

Todas as recusas aparecem em GET /remessas/{uuid} e na tela do lojista, com o motivo escrito para ele ler.

Preço e parcela na descrição

Anúncio que estampa "R$ 890" e esconde no texto que é o valor da parcela é o golpe mais comum do mercado de usados, e recusamos. Não coloquem preço nem parcelamento no campo descricao — o preço vai no campo preco.


Fotos

Nós baixamos as imagens e as hospedamos. Não usamos hotlink: se a loja sair do sistema de vocês, os anúncios continuam com foto.

  • Só endereços https.
  • Endereços que apontem para rede interna são recusados (é defesa contra SSRF).
  • Não usamos redirecionamento: mandem o endereço final da imagem.
  • Até 15 MB por arquivo.

Limites

Envio (abrir, enviar, fechar) 60 chamadas por minuto, por código de acesso
Consulta 300 por minuto, por código de acesso
Veículos por chamada 500
Veículos por remessa 5.000

O limite é por código, não por endereço de rede: um servidor de vocês pode atender centenas de lojas sem uma atrapalhar a outra.


Sugestão de frequência

Uma remessa completa a cada 1 a 4 horas cobre com folga a operação de uma revenda. Não há ganho em sincronizar de minuto em minuto: a remessa é sempre o pátio inteiro.


Como testar

Peçam ao lojista o código de acesso dele (ou usem uma loja de teste). O fluxo inteiro funciona com curl:

BASE=https://www.bomdelance.com.br/api/integracao/v1
TOKEN=cole_o_codigo_aqui

R=$(curl -s -X POST $BASE/remessas -H "Authorization: Bearer $TOKEN" | jq -r .remessa)

curl -s -X POST $BASE/remessas/$R/veiculos \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"veiculos":[{"id_externo":"1","marca":"FIAT","modelo":"ARGO","versao":"1.0 DRIVE","ano_modelo":2023,"preco":"74.900,00","fotos":[]}]}'

curl -s -X POST $BASE/remessas/$R/fechar \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"total_declarado":1}'

curl -s $BASE/remessas/$R -H "Authorization: Bearer $TOKEN"

Para ver a conferência agindo, declarem um total errado no fechamento: a resposta volta inconsistente e nada é aplicado.


Falar com a gente

Dúvida técnica, ambiente de teste ou pedido de ajuste no contrato: [email protected].