A busca de veículos é assíncrona: você inicia a busca e depois consulta os resultados por polling. Isso acontece porque o CGD consulta múltiplos fornecedores em paralelo, e cada um pode levar alguns segundos para responder.
O CGD resolve os endereços automaticamente via FretaMaps — você não precisa fornecer coordenadas, basta enviar o endereço em texto livre.
Endpoints
| Método | Endpoint | Descrição |
|---|
POST | /search | Iniciar busca de veículos |
GET | /search/{search_id} | Consultar resultados (polling) |
Como funciona o fluxo
1. POST /search → recebe search_id (status: pending)
|
| (aguarde 2-5 segundos)
v
2. GET /search/{search_id} → status: pending | partial | complete | failed
|
| (repita enquanto status = pending ou partial)
v
3. Quando status = complete → lista completa de veículos disponível
Recomendamos polling a cada 2 segundos, com timeout máximo de 30 segundos.
O status partial indica que alguns fornecedores já responderam, mas a busca ainda está em andamento. Você pode exibir os veículos parciais imediatamente e continuar o polling até complete.
Iniciar busca
Ida simples:
curl -X POST https://gds.fretatech.com.br/api/partner/v1/search \
-H "Authorization: Bearer SUA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"origin": "Peruíbe, SP",
"destination": "Aparecida de Goiânia, GO",
"trip_date": "2026/04/15",
"trip_time": "10:00",
"trip_type": "onewaytrip",
"passengers": 40
}'
Ida e volta:
curl -X POST https://gds.fretatech.com.br/api/partner/v1/search \
-H "Authorization: Bearer SUA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"origin": "São Paulo, SP",
"destination": "Rio de Janeiro, RJ",
"trip_date": "2026/04/15",
"trip_time": "08:00",
"trip_type": "roundtrip",
"return_date": "2026/04/18",
"return_time": "08:00",
"passengers": 44
}'
Campos da requisição
| Campo | Tipo | Obrigatório | Descrição |
|---|
origin | string | Sim | Endereço de origem em texto livre |
destination | string | Sim | Endereço de destino em texto livre |
trip_date | string | Sim | Data de ida no formato YYYY/MM/DD |
trip_time | string | Sim | Horário de partida no formato HH:MM |
trip_type | string | Sim | Tipo da viagem (veja tabela abaixo) |
passengers | integer | Não | Número de passageiros |
return_date | string | Só para roundtrip | Data de retorno no formato YYYY/MM/DD (deve ser ≥ trip_date) |
return_time | string | Não | Horário de retorno no formato HH:MM (padrão: mesmo que trip_time) |
Tipos de viagem
| Valor | Descrição |
|---|
onewaytrip | Ida simples |
roundtrip | Ida e volta |
hourtrip | Por hora (com franquia) |
customtrip | Roteiro personalizado (múltiplos trechos) |
Resposta
{
"success": true,
"data": {
"search_id": "Ox2VB6xxOL4HOVae",
"status": "pending",
"origin": {
"description": "Aeroporto Internacional de Guarulhos",
"lat": -23.4356,
"lng": -46.4731
},
"destination": {
"description": "Av. Paulista, 1000 - Bela Vista, São Paulo - SP",
"lat": -23.563,
"lng": -46.6543
},
"message": "Busca iniciada. Use GET /search/{search_id} para consultar."
}
}
A resposta inclui os endereços resolvidos pelo CGD (com coordenadas confirmadas) para você validar se o local foi interpretado corretamente.
Consultar resultados (polling)
curl -X GET "https://gds.fretatech.com.br/api/partner/v1/search/Ox2VB6xxOL4HOVae" \
-H "Authorization: Bearer SUA_API_KEY"
Valores de status
| Status | Descrição |
|---|
pending | Busca em andamento — nenhum fornecedor respondeu ainda |
partial | Alguns fornecedores responderam — continue o polling |
complete | Busca concluída — resultados completos disponíveis |
failed | Erro na busca — tente novamente |
Resposta quando status = pending
{
"success": true,
"data": {
"search_id": "Ox2VB6xxOL4HOVae",
"status": "pending",
"total_vehicles": 0,
"vehicles": []
}
}
Resposta quando status = partial ou complete
{
"success": true,
"data": {
"search_id": "Ox2VB6xxOL4HOVae",
"status": "partial",
"total_vehicles": 2,
"vehicles": [
{
"id": 28,
"name": "Ônibus Semi-Leito 45 Lugares Motor Traseiro - Bela Vista",
"capacity": 44,
"available_quantity": 100,
"type": {
"value": "onibus",
"label": "Ônibus"
},
"class": "Semi-Leito",
"wifi": true,
"bathroom": true,
"bilingual": false,
"air_conditioning": true,
"attributes": [
{ "id": 10, "name": "Cobertor" },
{ "id": 6, "name": "Geladeira" },
{ "id": 8, "name": "Tomada" },
{ "id": 1, "name": "TV" }
],
"image_url": "https://example.com/storage/fleet/onibus.jpg",
"gallery": [
"https://example.com/storage/fleet/gallery/onibus-interior.jpg"
],
"price_cents": 41460.67,
"tenant_id": "fb4a8f4c-617a-45f8-a2e9-0aebbc5cd0f5",
"tenant_name": "Viação Exemplo - São Paulo",
"tenant_logo": "https://example.com/storage/logos/viacao-exemplo.jpg"
}
]
}
}
Estrutura do veículo
| Campo | Tipo | Descrição |
|---|
id | integer | Identificador do veículo (use para criar o orçamento) |
name | string | Nome/descrição completa do veículo |
capacity | integer | Capacidade de passageiros |
available_quantity | integer | Quantidade de unidades disponíveis desse veículo |
type | object | Tipo do veículo com value (chave) e label (texto legível) |
class | string | Classe do veículo (ex: "Semi-Leito", "Executivo", "Leito") |
wifi | boolean | Possui Wi-Fi a bordo |
bathroom | boolean | Possui banheiro a bordo |
bilingual | boolean | Motorista/guia bilíngue |
air_conditioning | boolean | Possui ar-condicionado |
attributes | array | Lista de atributos/comodidades (id e name) |
image_url | string | URL da foto principal do veículo |
gallery | array | URLs das fotos adicionais do veículo |
price_cents | number | Preço em reais do fornecedor, sem margem CGD (ex: 41586.16 = R$ 41.586,16) |
tenant_id | string | UUID do fornecedor |
tenant_name | string | Nome do fornecedor |
tenant_logo | string | URL do logotipo do fornecedor |
Valores possíveis de type.value
| Valor | Label |
|---|
onibus | Ônibus |
micro-onibus | Micro-ônibus |
minibus | Mini-ônibus |
van | Van |
suv | SUV |
sedan | Sedã |
executivo | Executivo |
O campo price_cents representa o valor bruto do fornecedor em reais (apesar do nome). Passe esse valor diretamente em selectedVehicle.priceCents ao criar o orçamento — o CGD converte para centavos internamente e aplica a margem. Veja Orçamentos para mais detalhes.
Exemplo de polling em JavaScript
async function waitForSearchResults(searchId, apiKey) {
const maxAttempts = 15; // 30 segundos com intervalo de 2s
for (let i = 0; i < maxAttempts; i++) {
const response = await fetch(
`https://gds.fretatech.com.br/api/partner/v1/search/${searchId}`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
);
const { data } = await response.json();
// Exibe veículos parciais imediatamente
if (data.vehicles.length > 0) {
renderVehicles(data.vehicles);
}
if (data.status === 'complete') return data.vehicles;
if (data.status === 'failed') throw new Error('Busca falhou. Tente novamente.');
await new Promise(resolve => setTimeout(resolve, 2000));
}
throw new Error('Timeout: busca não concluiu em 30 segundos.');
}