> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fretatech.app.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Busca de Veículos

> Consulte disponibilidade e preços em tempo real

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**.

<Note>
  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`.
</Note>

***

## Iniciar busca

**Ida simples:**

```bash theme={null}
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:**

```bash theme={null}
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

```json theme={null}
{
  "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)

```bash theme={null}
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

```json theme={null}
{
  "success": true,
  "data": {
    "search_id": "Ox2VB6xxOL4HOVae",
    "status": "pending",
    "total_vehicles": 0,
    "vehicles": []
  }
}
```

### Resposta quando status = partial ou complete

```json theme={null}
{
  "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    |

<Note>
  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](/partner/quotes) para mais detalhes.
</Note>

***

## Exemplo de polling em JavaScript

```javascript theme={null}
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.');
}
```
