JusPilot
API

Busca de Voos

Buscar voos em tempo real através da API

Busca de Voos

Busque voos em tempo real em múltiplos fornecedores. A API oferece dois modos de busca: REST (resposta única) e SSE (streaming em tempo real).

Dois Modos de Busca

Use REST (/search) para obter resultado completo de uma vez, ou SSE (/stream) para receber resultados progressivamente em tempo real.

POST /api/v1/flights/search

Busca voos com resposta única contendo todos os resultados.

Request

{
  "type": "round_trip",
  "slices": [
    {
      "origin": "GRU",
      "destination": "MIA",
      "departureDate": "2026-03-15"
    },
    {
      "origin": "MIA",
      "destination": "GRU",
      "departureDate": "2026-03-22"
    }
  ],
  "passengers": [
    { "type": "adult", "count": 2 },
    { "type": "child", "count": 1 }
  ],
  "cabinClass": "economy",
  "maxConnections": 2,
  "suppliers": ["latam", "gol", "azul"],
  "enableDeduplication": true,
  "searchType": "pagante"
}

Parâmetros do Request

CampoTipoObrigatórioDescrição
typestringSimTipo de viagem: one_way (só ida) ou round_trip (ida e volta)
slicesarraySimTrechos da viagem (veja detalhes abaixo)
passengersarraySimLista de passageiros por tipo
cabinClassstringNãoClasse da cabine (padrão: economy)
maxConnectionsnumberNãoFiltro de conexões: 0 = apenas voos diretos, qualquer outro valor = ignora o filtro
suppliersarrayNãoLista de fornecedores específicos (opcional)
enableDeduplicationbooleanNãoRemover voos duplicados (padrão: true)
searchTypestringNãoTipo de pesquisa: milhas ou pagante. Se omitido, retorna todos os tipos

Objeto Slice

CampoTipoObrigatórioDescrição
originstringSimCódigo IATA do aeroporto/cidade de origem (ex: GRU, SAO)
destinationstringSimCódigo IATA do aeroporto/cidade de destino (ex: MIA, NYC)
departureDatestringSimData de partida no formato YYYY-MM-DD

Você pode usar códigos de aeroporto (ex: GRU, JFK) ou códigos de cidade (ex: SAO, NYC). Códigos de cidade retornam voos de todos os aeroportos da cidade.

Limitação: Filtro de Conexões

O parâmetro maxConnections funciona de forma binária:

  • maxConnections: 0 = apenas voos diretos (sem escalas)
  • Qualquer outro valor (1, 2, 3...) = ignora o filtro e retorna todos os voos

Não é possível filtrar especificamente por "até 1 conexão" ou "até 2 conexões".

Objeto Passenger

CampoTipoObrigatórioDescrição
typestringSimTipo: adult, child, infant_without_seat
countnumberSimQuantidade de passageiros deste tipo

Regras de Passageiros:

  • adult: 12+ anos na data do voo
  • child: 2-11 anos na data do voo
  • infant_without_seat: 0-1 ano (viaja no colo de um adulto)

Classes de Cabine

ValorDescrição
economyClasse Econômica
premium_economyEconômica Premium
businessClasse Executiva
firstPrimeira Classe

Tipos de Pesquisa

ValorDescrição
milhasBuscar apenas voos com programa de milhas
paganteBuscar apenas voos pagantes (dinheiro)
(omitido)Usa configuração padrão da sua conta (pode incluir ambos)

Response

{
  "success": true,
  "requestId": "req_123abc",
  "flightGroups": [
    {
      "id": "group_1",
      "totalPrice": {
        "amount": 2500.00,
        "currency": "BRL"
      },
      "slices": [
        {
          "segments": [
            {
              "departureAirport": {
                "iata": "GRU",
                "name": "Aeroporto Internacional de São Paulo/Guarulhos",
                "city": "São Paulo"
              },
              "arrivalAirport": {
                "iata": "MIA",
                "name": "Miami International Airport",
                "city": "Miami"
              },
              "departureTime": "2026-03-15T08:00:00",
              "arrivalTime": "2026-03-15T16:30:00",
              "duration": "9h 30m",
              "airline": {
                "code": "LA",
                "name": "LATAM Airlines"
              },
              "flightNumber": "LA8084",
              "aircraft": "Boeing 787-9"
            }
          ]
        }
      ],
      "offers": [
        {
          "provider": "latam",
          "price": {
            "amount": 2500.00,
            "currency": "BRL"
          },
          "deepLink": "https://..."
        }
      ]
    }
  ],
  "totalResults": 45,
  "providers": [
    {
      "id": "latam",
      "name": "LATAM",
      "status": "completed",
      "offersCount": 15
    },
    {
      "id": "gol",
      "name": "GOL",
      "status": "completed",
      "offersCount": 18
    }
  ]
}

Campos da Resposta

FlightGroup

CampoTipoDescrição
idstringID único do grupo de voos
totalPriceobjectPreço total (amount + currency)
slicesarrayTrechos da viagem com segmentos
offersarrayOfertas de diferentes fornecedores

Segment

CampoTipoDescrição
departureAirportobjectAeroporto de partida (iata, name, city)
arrivalAirportobjectAeroporto de chegada (iata, name, city)
departureTimestringData/hora de partida (ISO 8601)
arrivalTimestringData/hora de chegada (ISO 8601)
durationstringDuração do voo
airlineobjectCompanhia aérea (code, name)
flightNumberstringNúmero do voo
aircraftstringTipo de aeronave

POST /api/v1/flights/stream

Busca voos com streaming de resultados via Server-Sent Events (SSE).

Resultados em Tempo Real

Com SSE, você recebe os voos conforme são encontrados, sem aguardar a busca completa. Ideal para melhor UX.

Request

O request é idêntico ao endpoint /search.

Response (Server-Sent Events)

A resposta é um stream de eventos. Cada evento tem um tipo (event:) e dados (data:).

Evento: search-initialized

Enviado quando a busca inicia:

event: search-initialized
data: {"requestId":"req_123abc","providers":["latam","gol","azul"]}

Evento: provider-progress

Enviado quando um fornecedor atualiza seu status:

event: provider-progress
data: {"provider":"latam","status":"searching","progress":50}

Evento: flight-update

Enviado quando novos voos são encontrados:

event: flight-update
data: {
  "newGroups": [
    {
      "id": "group_1",
      "totalPrice": {"amount": 2500.00, "currency": "BRL"},
      "slices": [...]
    }
  ],
  "updatedGroups": []
}

Evento: search-complete

Enviado quando a busca termina:

event: search-complete
data: {
  "requestId": "req_123abc",
  "totalGroups": 45,
  "totalOffers": 120,
  "duration": "8.5s"
}

Evento: search-error

Enviado em caso de erro:

event: search-error
data: {
  "error": {
    "code": "SEARCH_ERROR",
    "message": "Failed to search flights",
    "timestamp": "2026-01-10T12:00:00Z"
  }
}

Exemplo de Uso (JavaScript)

const response = await fetch('/api/v1/flights/stream', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sua_chave_aqui',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    type: 'round_trip',
    slices: [
      { origin: 'GRU', destination: 'MIA', departureDate: '2026-03-15' },
      { origin: 'MIA', destination: 'GRU', departureDate: '2026-03-22' }
    ],
    passengers: [{ type: 'adult', count: 1 }],
    cabinClass: 'economy'
  })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  
  const text = decoder.decode(value);
  const lines = text.split('\n');
  
  for (const line of lines) {
    if (line.startsWith('event:')) {
      const eventType = line.slice(7).trim();
    } else if (line.startsWith('data:')) {
      const data = JSON.parse(line.slice(6));
      
      if (eventType === 'flight-update') {
        console.log('Novos voos:', data.newGroups.length);
        // Atualizar UI com novos voos
      } else if (eventType === 'search-complete') {
        console.log('Busca completa!');
        break;
      }
    }
  }
}

Exemplos de Busca

{
  "type": "one_way",
  "slices": [
    {
      "origin": "GRU",
      "destination": "LIS",
      "departureDate": "2026-06-15"
    }
  ],
  "passengers": [
    { "type": "adult", "count": 1 }
  ],
  "cabinClass": "economy"
}
{
  "type": "round_trip",
  "slices": [
    {
      "origin": "GRU",
      "destination": "CDG",
      "departureDate": "2026-07-10"
    },
    {
      "origin": "CDG",
      "destination": "GRU",
      "departureDate": "2026-07-25"
    }
  ],
  "passengers": [
    { "type": "adult", "count": 2 }
  ],
  "cabinClass": "economy"
}
{
  "type": "round_trip",
  "slices": [
    {
      "origin": "GRU",
      "destination": "JFK",
      "departureDate": "2026-04-20"
    },
    {
      "origin": "JFK",
      "destination": "GRU",
      "departureDate": "2026-04-27"
    }
  ],
  "passengers": [
    { "type": "adult", "count": 1 }
  ],
  "cabinClass": "business",
  "maxConnections": 0,
  "suppliers": ["latam", "united"],
  "enableDeduplication": true
}
{
  "type": "round_trip",
  "slices": [
    {
      "origin": "BSB",
      "destination": "FOR",
      "departureDate": "2026-02-15"
    },
    {
      "origin": "FOR",
      "destination": "BSB",
      "departureDate": "2026-02-22"
    }
  ],
  "passengers": [
    { "type": "adult", "count": 1 }
  ],
  "cabinClass": "economy",
  "searchType": "milhas"
}
{
  "type": "one_way",
  "slices": [
    {
      "origin": "GRU",
      "destination": "MIA",
      "departureDate": "2026-03-10"
    }
  ],
  "passengers": [
    { "type": "adult", "count": 2 }
  ],
  "cabinClass": "business",
  "searchType": "pagante"
}

Limitações Conhecidas

Tipos de Viagem

  • Suportado: one_way (só ida), round_trip (ida e volta)
  • Não suportado: multi_city (múltiplos destinos)

Para viagens com múltiplos destinos, faça múltiplas buscas one_way separadas.

Filtro de Conexões

O parâmetro maxConnections tem comportamento binário:

  • maxConnections: 0 → Retorna apenas voos diretos (sem escalas)
  • maxConnections: 1, 2, 3...Ignora o filtro e retorna todos os voos

Não é possível filtrar especificamente por "até 1 conexão" ou "até 2 conexões". A API subjacente só suporta filtro de voos diretos.

Mapeamento de Classes

As classes de cabine são mapeadas internamente:

Classe na APIMapeamento Interno
economyEconômica
premium_economyExecutiva
businessExecutiva
firstPrimeira Classe

Note que premium_economy e business são mapeados para a mesma classe internamente.


Troubleshooting

Resposta Vazia (flightGroups: [])

Se você receber uma resposta válida mas sem voos, pode ser por:

1. Nenhum fornecedor encontrou voos

  • Tente datas diferentes (evite datas muito próximas ou muito distantes)
  • Experimente aeroportos alternativos (ex: CGH ao invés de GRU)

2. Filtros muito restritivos

  • Remova suppliers para buscar em todos os fornecedores
  • Remova maxConnections: 0 para incluir voos com escalas

3. Rota não operada

  • Verifique se a rota existe (ex: algumas rotas internacionais não têm voos diretos)
  • Use o endpoint de autocomplete para validar códigos IATA

Exemplo de request de teste (rota doméstica garantida):

{
  "type": "one_way",
  "slices": [
    {
      "origin": "GRU",
      "destination": "GIG",
      "departureDate": "2026-02-15"
    }
  ],
  "passengers": [
    { "type": "adult", "count": 1 }
  ]
}

Tokens de Checkout

A resposta inclui tokens importantes para finalizar a reserva:

{
  "requestId": "...",
  "flightGroups": [...],
  "tokens": {
    "tokenConsultaIda": "1_V2_087d1b63a998...",
    "tokenConsultaVolta": "1_V2_a35b962a5da2...",
    "tokenExpiration": "2026-01-12T16:15:13.5288101Z"
  }
}

Importante

Guarde estes tokens! Você precisará deles para:

  • Validar disponibilidade no momento da reserva
  • Processar o checkout via API Reservei

Os tokens expiram conforme tokenExpiration (geralmente 30 minutos).

Resposta Real vs Documentada

A resposta real contém campos adicionais úteis:

CampoDescrição
flightGroups[].signatureHash único do grupo de voos
flightGroups[].humanSignatureIdentificador legível (ex: "GRU-GIG-3366-LA-20260215")
tokens.tokenConsultaIdaToken para checkout do trecho de ida
tokens.tokenConsultaVoltaToken para checkout do trecho de volta (se aplicável)
tokens.tokenExpirationValidade dos tokens em formato ISO 8601

Códigos IATA Comuns (Brasil)

CódigoAeroporto/Cidade
GRUSão Paulo - Guarulhos
CGHSão Paulo - Congonhas
SAOSão Paulo (todos aeroportos)
GIGRio de Janeiro - Galeão
SDURio de Janeiro - Santos Dumont
RIORio de Janeiro (todos aeroportos)
BSBBrasília
CNFBelo Horizonte - Confins
SSASalvador
RECRecife
FORFortaleza
POAPorto Alegre
CWBCuritiba
FLNFlorianópolis

Erros Comuns

CódigoErroSolução
400Invalid request parametersVerifique os campos obrigatórios
400Invalid airport codeUse códigos IATA válidos
400Invalid date formatUse formato YYYY-MM-DD
400Departure date in the pastData deve ser futura
401UnauthorizedVerifique sua API key
429Quota exceededAdicione créditos no dashboard

Dicas de Performance

  1. Use SSE para melhor UX: Exiba resultados progressivamente conforme chegam
  2. Cache local: Resultados podem ser cacheados por 5-10 minutos (mas não os tokens!)
  3. Limite fornecedores: Use suppliers para buscar apenas em fornecedores específicos e reduzir tempo de resposta
  4. Use códigos específicos: Aeroportos (GRU) são mais rápidos que cidades (SAO)
  5. Salve os tokens: Guarde tokenConsultaIda e tokenConsultaVolta para usar no checkout

Os preços e disponibilidade são dinâmicos. Os resultados refletem informações em tempo real no momento da consulta. Os tokens expiram em ~30 minutos - inicie o checkout rapidamente.

On this page