API v1 · REST · JSON
Documentação de Integração
Integre seu sistema de estoque com o Veículos no Sul via endpoints REST, autenticação por API Key e webhooks em tempo real.
Introdução
A API do Veículos no Sul permite que sistemas externos — como softwares de gestão de estoque (DMS), portais parceiros e ERPs — sincronizem anúncios de veículos diretamente no portal, de forma automática e em tempo real.
A integração funciona por meio de chamadas REST com JSON. Cada loja possui uma API Key própria, gerada no painel do revendedor. Com ela, é possível criar, atualizar e remover veículos, além de receber notificações via webhook.
Passo a passo para começar
Gere sua API Key
Acesse Configurações → Integração e crie uma nova chave. Copie-a imediatamente — ela só é exibida uma vez.
Construa o payload do veículo
Monte o JSON com os campos obrigatórios (externalId, brand, model, year, price) e os opcionais desejados.
Chame o endpoint de sync
Envie um POST para /integration/vehicles/sync. O sistema criará ou atualizará o veículo automaticamente.
(Opcional) Configure webhooks
Registre uma URL no painel para receber notificações em tempo real de eventos sobre seus veículos.
Autenticação
Todas as requisições devem ser autenticadas via API Key enviada no header X-API-Key.
X-API-Key: cds_live_sua_chave_de_32_caracteres_aquiNunca exponha sua API Key em código frontend, repositórios públicos ou logs. Trate-a como uma senha. Se comprometida, revogue e gere uma nova no painel imediatamente.
Como gerar sua API Key
Acesse o painel da loja e vá em Configurações → Integração.
Clique em Nova chave e defina um nome descritivo (ex: "Sistema ERP", "Integração DMS").
Copie a chave exibida imediatamente — ela é exibida apenas uma vez por segurança.
Armazene em variável de ambiente e use no header X-API-Key de cada requisição.
Formato da chave
cds_live_[32 caracteres a-z0-9]Ex: cds_live_k8mnp2xw...
Características
- Múltiplas chaves por loja
- Nomes descritivos por sistema
- Revogação instantânea
- Log de uso detalhado
Endpoints
Envia um único veículo. Se o externalId já existir para a sua loja, o veículo será atualizado; caso contrário, será criado. Imagens são baixadas, armazenadas e comparadas com as existentes automaticamente.
Exemplo de requisição
curl -X POST https://api.veiculosnosul.com.br/integration/vehicles/sync \
-H "X-API-Key: cds_live_sua_chave_aqui" \
-H "Content-Type: application/json" \
-d '{
"externalId": "SKU-00123",
"brand": "Toyota",
"model": "Corolla",
"year": 2022,
"price": 149900,
"km": 35000,
"fuel": "FLEX",
"transmission": "AUTOMATIC",
"images": [
{ "url": "https://seusite.com.br/fotos/carro-123-1.jpg", "order": 0 }
]
}'Resposta de sucesso (201 Created)
{
"success": true,
"action": "created",
"message": "Veículo criado com sucesso",
"data": {
"id": "clx9abc123def456",
"externalId": "SKU-00123",
"brand": "Toyota",
"model": "Corolla",
"year": 2022,
"price": 149900,
"status": "ACTIVE",
"createdAt": "2026-04-13T10:30:00.000Z"
}
}skipped: true e reason: "Conteúdo idêntico (idempotência)". Nenhuma alteração é feita no banco e nenhum webhook é disparado.Envia múltiplos veículos de uma vez. Cada veículo é processado individualmente — falhas em um item não interrompem os demais. Ideal para sincronização periódica do estoque completo.
Exemplo de requisição
curl -X POST https://api.veiculosnosul.com.br/integration/vehicles/sync/batch \
-H "X-API-Key: cds_live_sua_chave_aqui" \
-H "Content-Type: application/json" \
-d '{
"vehicles": [
{
"externalId": "SKU-00123",
"brand": "Toyota",
"model": "Corolla",
"year": 2022,
"price": 149900
},
{
"externalId": "SKU-00124",
"brand": "Honda",
"model": "Civic",
"year": 2021,
"price": 129900
}
]
}'Resposta de sucesso (200 OK)
{
"success": true,
"message": "Sincronização em lote concluída",
"data": {
"total": 2,
"created": 1,
"updated": 1,
"failed": 0,
"results": [
{ "externalId": "SKU-00123", "action": "created", "success": true, "vehicleId": "clx9abc123def456" },
{ "externalId": "SKU-00124", "action": "updated", "success": true, "vehicleId": "clx9def789ghi012" }
]
}
}Remove permanentemente o veículo com o externalId fornecido, incluindo todas as suas imagens armazenadas. Esta operação é irreversível.
Atenção: A remoção é permanente. As imagens também são apagadas do storage. Não há como desfazer esta ação.
Exemplo de requisição
curl -X DELETE https://api.veiculosnosul.com.br/integration/vehicles/sync/SKU-00123 \
-H "X-API-Key: cds_live_sua_chave_aqui"Resposta de sucesso (200 OK)
{ "success": true, "message": "Veículo removido com sucesso" }Schema do Veículo
| Campo | Tipo | Descrição |
|---|---|---|
externalIdobrigatório | string | ID único do veículo no seu sistema (até 100 chars). Usado para identificar CREATE vs UPDATE. |
brandobrigatório | string | Marca do veículo. Ex: "Toyota", "Volkswagen". |
modelobrigatório | string | Modelo do veículo. Ex: "Corolla", "Gol". |
yearobrigatório | integer | Ano do veículo. Mínimo: 1900. Máximo: ano atual + 1. |
priceobrigatório | number | Preço em reais (sem centavos). Ex: 149900. Máximo: R$ 10.000.000. |
version | string | Versão/trim do veículo. Ex: "XEi 2.0 Flex". |
modelYear | integer | Ano de fabricação, se diferente do ano do modelo. Não pode ser menor que year. |
vehicleType | enum | Tipo: CAR | MOTORCYCLE | TRUCK. Padrão: CAR. |
color | string | Cor do veículo. Ex: "Prata", "Preto Pérola". |
km | integer | Quilometragem do veículo. |
fuel | enum | GASOLINE | ETHANOL | FLEX | DIESEL | ELECTRIC | HYBRID | GNV. |
transmission | enum | MANUAL | AUTOMATIC | AUTOMATED | CVT. |
doors | integer | Número de portas. Entre 2 e 6. |
engineSize | string | Potência do motor. Ex: "1.0", "2.0". |
title | string | Título do anúncio (até 200 chars). Gerado automaticamente se omitido. |
description | string | Descrição detalhada (até 5000 chars). |
plate | string | Placa do veículo (não exibida publicamente). |
licensePlate | string | Placa de licenciamento (campo alternativo a plate, também não exibido publicamente). |
vin | string | Número do chassi (VIN). Deve ser único por loja — erro 400 se duplicado. |
features | string[] | Array de strings com características livres. Ex: ["Único dono", "Manual e chave reserva"]. |
externalUrl | string (URL) | URL do veículo no seu sistema externo (para referência). |
webhookUrl | string (URL) | URL de webhook específica para esta requisição. Sobrescreve a URL configurada na loja apenas para este sync. |
branchId | string (UUID) | ID da filial onde o veículo está localizado. Consulte sua equipe de suporte para obter os UUIDs das filiais da sua loja. |
images | VehicleImage[] | Array de imagens (ver seção Imagens). |
flags | VehicleFlag[] | Array de opcionais/equipamentos (ver seção Opcionais). |
Webhook por requisição
O campo webhookUrl permite sobrescrever a URL de webhook configurada na loja apenas para aquele sync específico. Útil quando diferentes sistemas ou filas precisam de endpoints de callback distintos.
Exemplo completo do payload
{
"externalId": "SKU-00123",
"brand": "Toyota",
"model": "Corolla",
"version": "XEi 2.0 Flex",
"year": 2022,
"modelYear": 2021,
"price": 149900,
"vehicleType": "CAR",
"color": "Prata",
"km": 35000,
"fuel": "FLEX",
"transmission": "AUTOMATIC",
"doors": 4,
"engineSize": "2.0",
"vin": "9BWZZZ377VT004251",
"plate": "ABC-1234",
"description": "Veículo em excelente estado, único dono, manual e chave reserva.",
"title": "Toyota Corolla XEi 2022 - Impecável",
"features": ["Único dono", "Manual e chave reserva", "IPVA 2026 pago"],
"externalUrl": "https://seusite.com.br/veiculos/corolla-sku-00123",
"webhookUrl": "https://seusite.com.br/webhook/veiculos",
"images": [
{ "url": "https://seusite.com.br/fotos/carro-123-1.jpg", "order": 0 },
{ "url": "https://seusite.com.br/fotos/carro-123-2.jpg", "order": 1 }
],
"flags": [
{ "type": "OPTIONAL", "name": "Ar Condicionado", "value": true },
{ "type": "OPTIONAL", "name": "Direção Elétrica", "value": true },
{ "type": "OPTIONAL", "name": "Vidros Elétricos", "value": true },
{ "type": "OPTIONAL", "name": "Trava Elétrica", "value": true },
{ "type": "OPTIONAL", "name": "Airbag", "value": true },
{ "type": "OPTIONAL", "name": "ABS", "value": true }
]
}Imagens
Você não precisa fazer upload manual das imagens. Basta enviar as URLs públicas no array images — a API baixa, processa e armazena automaticamente.
Formatos aceitos
- JPEG / JPG
- PNG
- WebP
- GIF
Limites por imagem
- Tamanho máximo: 10 MB
- Tamanho mínimo: 1 KB
- Download: timeout 30s, 3 tentativas
- URL deve ser publicamente acessível
"images": [
{ "url": "https://seusite.com.br/fotos/carro-123-1.jpg", "order": 0 },
{ "url": "https://seusite.com.br/fotos/carro-123-2.jpg", "order": 1 },
{ "url": "https://seusite.com.br/fotos/carro-123-3.jpg", "order": 2 }
]Comportamento no update
- Imagens novas → baixadas e adicionadas
- Imagens existentes → mantidas (sem re-download)
- Imagens removidas do array → apagadas do storage
Opcionais e Equipamentos
Opcionais são enviados via array flags. Cada item tem um type, um name e um value. A cada sync, as flags antigas são substituídas pelas novas.
"flags": [
{ "type": "OPTIONAL", "name": "Ar Condicionado", "value": true },
{ "type": "OPTIONAL", "name": "Direção Elétrica", "value": true },
{ "type": "OPTIONAL", "name": "Vidros Elétricos", "value": true },
{ "type": "OPTIONAL", "name": "Teto Solar", "value": false },
{ "type": "OPTIONAL", "name": "Câmera de Ré", "value": true },
{ "type": "OPTIONAL", "name": "Sensor de Estac.", "value": true },
{ "type": "OPTIONAL", "name": "Multimídia", "value": true },
{ "type": "OPTIONAL", "name": "Bancos em Couro", "value": false }
]O campo type pode ser qualquer string. Recomendamos usar OPTIONAL para equipamentos padrão. O name é exibido diretamente no anúncio.
Webhooks
Configure uma URL de webhook no painel da sua loja para receber notificações em tempo real sobre eventos de sincronização de veículos via API. Os webhooks são disparados exclusivamente pelas operações de sync — não cobrem outras ações do portal como leads ou visualizações.
Entrega best-effort: webhooks de sync são disparados sem retry automático. Se o seu endpoint retornar erro ou estiver indisponível, o evento não será reenviado. Para maior confiabilidade, confirme o processamento consultando a API.
vehicle.createdVeículo criado com sucessovehicle.updatedVeículo atualizado (ou sem mudanças)vehicle.failedFalha no sync (apenas batch)Payload enviado ao seu endpoint
// vehicle.created
{
"event": "vehicle.created",
"externalId": "SKU-00123",
"action": "created",
"timestamp": "2026-04-13T10:30:00.000Z"
}
// vehicle.updated
{
"event": "vehicle.updated",
"externalId": "SKU-00123",
"vehicleId": "clx9abc123def456",
"action": "updated",
"timestamp": "2026-04-13T10:31:00.000Z"
}
// vehicle.failed (apenas em batch)
{
"event": "vehicle.failed",
"externalId": "SKU-00999",
"error": "Preço inválido",
"timestamp": "2026-04-13T10:32:00.000Z"
}Verificando a assinatura
Cada requisição de webhook inclui o header X-Webhook-Signature com a assinatura HMAC-SHA256 do corpo. Sempre valide a assinatura antes de processar o evento.
import crypto from 'crypto';
// No seu servidor que recebe o webhook:
app.post('/webhook/veiculosnosul', (req, res) => {
const sigHeader = req.headers['x-webhook-signature'];
const rawBody = JSON.stringify(req.body);
// Extrair timestamp e assinatura do header (formato: t=<ts>,v1=<hex>)
const parts = Object.fromEntries(sigHeader.split(',').map(p => p.split('=')));
const timestamp = parts['t'];
const received = parts['v1'];
// Rejeitar mensagens com mais de 5 minutos (proteção contra replay)
const age = Math.floor(Date.now() / 1000) - parseInt(timestamp, 10);
if (age > 300) return res.status(401).json({ error: 'Requisição expirada' });
// Recriar a assinatura esperada: timestamp.rawBody
const expected = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
// Comparação segura contra timing attacks
if (!crypto.timingSafeEqual(Buffer.from(received, 'hex'), Buffer.from(expected, 'hex'))) {
return res.status(401).json({ error: 'Assinatura inválida' });
}
const { event, externalId, vehicleId, action, error } = req.body;
if (event === 'vehicle.created') {
console.log('Veículo criado:', externalId);
} else if (event === 'vehicle.updated') {
console.log('Veículo atualizado:', externalId, '| ação:', action);
} else if (event === 'vehicle.failed') {
console.error('Falha no sync:', externalId, '| erro:', error);
}
res.json({ received: true });
});Leads — Recebimento na sua plataforma
Quando um usuário do portal demonstra interesse em um veículo da sua loja (clicando em “Entrar em contato”, WhatsApp ou enviando uma mensagem), o portal gera um lead e o encaminha para o seu sistema via webhook.
Para receber leads, é necessário ter uma URL de webhook e um Integration Token configurados no painel da loja em Configurações → Integração.
Payload do webhook de lead
lead.createdX-Webhook-Signature (HMAC-SHA256){
"event": "lead.created",
"timestamp": "2026-04-13T10:30:00.000Z",
"data": {
"id": "clx9abc123def456",
"name": "João Silva",
"phone": "51999990000",
"email": "joao@email.com",
"message": "Tenho interesse nesse veículo. Ainda está disponível?",
"origin": "whatsapp",
"status": "NEW",
"storeId": "uuid-da-loja",
"vehicleId": "uuid-do-veiculo",
"utmSource": "google",
"utmMedium": "cpc",
"utmCampaign": "carros-sul",
"createdAt": "2026-04-13T10:30:00.000Z",
"vehicle": {
"id": "uuid-do-veiculo",
"brand": "Toyota",
"model": "Corolla",
"version": "XEi 2.0 Flex",
"year": 2022,
"slug": "toyota-corolla-xei-2022"
}
}
}Campos do lead
| Campo | Tipo | Descrição |
|---|---|---|
id | string | ID único do lead no portal (UUID). |
name | string | Nome do interessado. |
phone | string | Telefone do interessado. |
email | string | null | E-mail do interessado (opcional). |
message | string | null | Mensagem enviada pelo interessado. |
origin | string | null | Canal de origem: whatsapp, form, phone, etc. |
status | string | Status do lead: NEW | READ | CONTACTED | QUALIFIED | CONVERTED | LOST. |
storeId | string | ID da loja dona do veículo. |
vehicleId | string | ID do veículo de interesse. |
utmSource | string | null | Parâmetro UTM da campanha (source). |
utmMedium | string | null | Parâmetro UTM da campanha (medium). |
utmCampaign | string | null | Parâmetro UTM da campanha (name). |
createdAt | string (ISO 8601) | Data e hora de criação do lead. |
vehicle | object | null | Dados resumidos do veículo: id, brand, model, version, year, slug. |
Verificando a assinatura do lead
O header X-Webhook-Signature usa HMAC-SHA256 com o seu Integration Token como chave secreta. O formato da assinatura é t=<unix_ts>,v1=<hex>.
import crypto from 'crypto';
app.post('/webhook/leads', (req, res) => {
const sigHeader = req.headers['x-webhook-signature'];
const rawBody = JSON.stringify(req.body);
// Extrair timestamp e assinatura do header (formato: t=<ts>,v1=<hex>)
const parts = Object.fromEntries(sigHeader.split(',').map(p => p.split('=')));
const timestamp = parts['t'];
const received = parts['v1'];
// Rejeitar mensagens com mais de 5 minutos (proteção contra replay)
const age = Math.floor(Date.now() / 1000) - parseInt(timestamp, 10);
if (age > 300) return res.status(401).json({ error: 'Requisição expirada' });
// Recriar a assinatura esperada: timestamp.rawBody
const signed = crypto
.createHmac('sha256', process.env.INTEGRATION_TOKEN)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
// Comparação segura contra timing attacks
if (!crypto.timingSafeEqual(Buffer.from(received, 'hex'), Buffer.from(signed, 'hex'))) {
return res.status(401).json({ error: 'Assinatura inválida' });
}
const { event, data } = req.body;
if (event === 'lead.created') {
console.log('Novo lead:', data.name, data.phone, '| Veículo:', data.vehicle?.model);
// salvar no seu CRM / DMS aqui
}
res.json({ received: true });
});O secret utilizado para assinar o webhook de leads é o Integration Token da loja (não confundir com a API Key usada no sync de veículos). Guarde-o em variável de ambiente.
Também recebemos por e-mail
Além do webhook, o portal envia automaticamente um e-mail de notificação para o endereço cadastrado na loja a cada novo lead, com os dados do interessado e um link direto para o veículo. Nenhuma configuração adicional é necessária para isso.
Rate Limits
| Endpoint | Limite | Janela | Recomendação |
|---|---|---|---|
POST /sync | 100 req | por minuto | Use batch para grandes volumes |
POST /sync/batch | 10 req | por minuto | Até 50 veículos por request |
DELETE /sync/:id | 100 req | por minuto | — |
Ao atingir o limite, a API retorna 429 Too Many Requests com o header Retry-After indicando quantos segundos aguardar.
Códigos de Erro
| Código | Nome | Descrição |
|---|---|---|
400 | Bad Request | Payload inválido ou campos obrigatórios ausentes. |
401 | Unauthorized | API Key ausente, inválida ou expirada. |
403 | Forbidden | A chave não tem permissão para esta operação. |
404 | Not Found | Veículo com o externalId fornecido não encontrado. |
429 | Too Many Requests | Limite de requisições excedido. Aguarde antes de tentar novamente. |
500 | Internal Server Error | Erro interno. Tente novamente em alguns instantes. |
Exemplo de resposta de erro
{
"statusCode": 400,
"message": [
"externalId should not be empty",
"price must be a number conforming to the specified constraints"
],
"error": "Bad Request"
}Ambiente de Homologação (Sandbox)
Antes de integrar em produção, você pode testar livremente usando uma API Key de teste (prefixo cds_test_). Chaves de teste aceitam os mesmos endpoints e payload da produção, mas os veículos criados ficam marcados internamente como sandbox e não impactam dados reais.
Produção
- Chave:
cds_live_... - Veículos publicados no portal
- Webhooks disparados normalmente
- Imagens armazenadas em definitivo
Sandbox (teste)
- Chave:
cds_test_... - Mesmos endpoints e payload
- Sem impacto em dados de produção
- Ideal para validar sua integração
Exemplo com chave de teste
Produção
https://api.veiculosnosul.com.brSandbox / Teste
https://sandbox.api.veiculosnosul.com.brcurl -X POST https://sandbox.api.veiculosnosul.com.br/integration/vehicles/sync \
-H "X-API-Key: cds_test_sua_chave_de_teste_aqui" \
-H "Content-Type: application/json" \
-d '{
"externalId": "SANDBOX-001",
"brand": "Toyota",
"model": "Corolla",
"year": 2022,
"price": 149900
}'Solicite sua chave de teste pelo painel da loja em Configurações → Integração → Nova chave. Chaves de teste podem ser revogadas e recriadas livremente.
Boas práticas para homologação
Teste o ciclo completo
Crie, atualize e delete o mesmo veículo para validar todos os fluxos antes de ir a produção.
Valide as imagens
Envie URLs de imagens reais e confirme que são baixadas e salvas corretamente.
Use um webhook de teste
Ferramentas como webhook.site ou smee.io permitem inspecionar webhooks sem configurar um servidor.
Teste o batch com dados variados
Inclua veículos com campos opcionais ausentes para garantir que sua integração trata bem os casos limite.
Próximo passo
Pronto para integrar?
Solicite sua API Key e comece a sincronizar veículos com o Veículos no Sul.
