API Reference

Integre o Viagilize com seus sistemas através da nossa API RESTful.

Base URL

https://{tenant}.viagilize.com.br/api/v1

Autenticação

A API utiliza autenticação via Bearer Token. Você pode gerar tokens de acesso no painel administrativo em Configurações → API.

Importante

Mantenha seu token seguro. Nunca compartilhe ou exponha em código público. Cada token tem permissões específicas (scopes) definidas no momento da criação.

Exemplo de requisição

curl
curl -X GET 'https://{tenant}.viagilize.com.br/api/v1/excursoes' \
  -H 'Authorization: Bearer seu_token_aqui' \
  -H 'Accept: application/json'

Escopos (Scopes)

Cada token pode ter permissões específicas. Ao criar um token, selecione apenas os escopos necessários.

excursoes:read Visualizar excursões
excursoes:write Criar e editar excursões
excursoes:delete Excluir excursões
passageiros:read Visualizar passageiros
passageiros:write Gerenciar passageiros
clientes:read Visualizar clientes
clientes:write Criar e editar clientes
clientes:delete Excluir clientes
financeiro:read Visualizar dados financeiros
financeiro:write Registrar pagamentos
checkin:write Realizar check-in
guias:read Visualizar guias
guias:write Gerenciar guias
veiculos:read Visualizar veículos
veiculos:write Gerenciar veículos
transportes:read Visualizar transportes
transportes:write Gerenciar transportes
webhooks:manage Configurar webhooks (CRUD via API)

Excursões

Gerenciamento de excursões e pacotes de viagem

Retorna uma lista paginada de excursões/pacotes com filtros.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
page integer query Número da página
per_page integer query Itens por página (max: 100)
status string query rascunho, publicada, cancelada, finalizada
tipo_excursao string query excursao ou pacote_viagem
categoria_id integer query Filtrar por categoria
search string query Busca por nome, cidade ou destino
data_inicio_de date query Data de início mínima (Y-m-d)
data_inicio_ate date query Data de início máxima (Y-m-d)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 45,
            "nome": "Gramado - Natal Luz 2025",
            "slug": "gramado-natal-luz-2025",
            "tipo_excursao": "excursao",
            "cidade": "Gramado",
            "estado": "RS",
            "pais": "Brasil",
            "local": "Gramado\/RS",
            "data_inicio": "2025-12-20",
            "data_fim": "2025-12-24",
            "hora_inicio": "06:00",
            "hora_fim": "22:00",
            "status": "publicada",
            "vagas_maximas": 46,
            "imagem": "https:\/\/...\/gramado.jpg",
            "categorias": [
                {
                    "id": 1,
                    "nome": "Adulto"
                }
            ],
            "embarques": [
                {
                    "id": 12,
                    "nome": "Terminal Tietê",
                    "cidade": "São Paulo",
                    "hora_embarque": "06:00"
                }
            ]
        }
    ],
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 45,
        "last_page": 3
    }
}

Retorna a excursão/pacote com categorias, embarques, preços, guias, transportes, paradas. Use include=... para carregar relações adicionais (voos, cruzeiro, componentes, itinerario, cotacoes, allotments, vouchers).

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da excursão
include string query CSV: voos,cruzeiro,componentes,itinerario,cotacoes,allotments,vouchers

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 45,
        "nome": "Gramado - Natal Luz 2025",
        "slug": "gramado-natal-luz-2025",
        "tipo_excursao": "excursao",
        "descricao": "Viagem completa com hospedagem...",
        "pais": "Brasil",
        "estado": "RS",
        "cidade": "Gramado",
        "data_inicio": "2025-12-20",
        "data_fim": "2025-12-24",
        "hora_inicio": "06:00",
        "hora_fim": "22:00",
        "status": "publicada",
        "vagas_maximas": 46,
        "permitir_escolha_assento": true,
        "escolha_assento_dias_antes": 30,
        "parcelas_max": 10,
        "acrescimo_tipo": "percentual",
        "acrescimo_parcela": 2.99,
        "duracao_noites": 4,
        "destino_cidade": "Gramado",
        "destino_estado": "RS",
        "destino_pais": "Brasil",
        "regime_hospedagem": "meia_pensao",
        "categoria_hotel": "4_estrelas",
        "nome_hotel": "Hotel Laghetto",
        "incluso": [
            "Hospedagem",
            "Café da manhã",
            "Transfer",
            "Passeios"
        ],
        "nao_incluso": [
            "Passeios opcionais",
            "Refeições extras"
        ],
        "documentos_necessarios": "RG ou CNH original",
        "categorias": [
            {
                "id": 1,
                "nome": "Adulto"
            },
            {
                "id": 2,
                "nome": "Criança (6-11)"
            }
        ],
        "embarques": [
            {
                "id": 12,
                "nome": "Terminal Tietê",
                "endereco": "Av. Cruzeiro do Sul, 1800",
                "cidade": "São Paulo",
                "estado": "SP",
                "hora_embarque": "06:00",
                "vagas_max": 46
            }
        ],
        "precos": [
            {
                "id": 77,
                "categoria_id": 1,
                "embarque_id": 12,
                "valor": 1450,
                "ativo": true
            }
        ],
        "transportes": [
            {
                "id": 9,
                "veiculo_id": 5,
                "nome": "Ônibus 1",
                "tipo": "onibus_leito",
                "vagas_total": 46,
                "veiculo": {
                    "id": 5,
                    "modelo": "Paradiso 1600",
                    "placa": "ABC-1234",
                    "capacidade_total": 46
                }
            }
        ],
        "paradas": [
            {
                "id": 3,
                "nome": "Café da manhã",
                "latitude": -26.9,
                "longitude": -49.07
            }
        ],
        "created_at": "2024-10-05T14:32:00Z",
        "updated_at": "2024-11-20T09:14:22Z"
    }
}

Retorna estatísticas agregadas: vagas, valores, confirmações.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "total_passageiros": 45,
        "passageiros_confirmados": 38,
        "vagas_total": 46,
        "vagas_ocupadas": 38,
        "vagas_disponiveis": 8,
        "preco_minimo": 1450,
        "preco_maximo": 1650
    }
}

Cria uma excursão (rodoviária) ou pacote de viagem. Pode receber arrays aninhados (transportes, embarques, precos) para criar tudo em uma única chamada, similar ao wizard do admin.

Escopo necessário excursoes:write

Corpo da requisição

Campo Tipo Descrição
nome * string Nome da excursão/pacote
slug string Slug (gerado automaticamente se omitido)
tipo_excursao string excursao (default) ou pacote_viagem
descricao string Descrição longa
imagem string URL da imagem principal
galeria array Array de URLs de imagens
pais string País
estado string Estado/UF
cidade string Cidade
local string Local/destino
data_inicio * date Data de início (Y-m-d)
data_fim date Data de fim (Y-m-d)
hora_inicio string Hora de início (H:i)
hora_fim string Hora de fim (H:i)
vagas_maximas integer Limite total de vagas
permitir_escolha_assento boolean Cliente escolhe assento
escolha_assento_dias_antes integer Dias antes do embarque para liberar escolha
permitir_troca_transporte boolean Permite trocar de transporte
status string rascunho (default), publicada, cancelada, finalizada
categoria_ids array Array de IDs de categorias de passageiro
parcelas_max integer Máximo de parcelas no checkout
acrescimo_tipo string percentual ou fixo
acrescimo_parcela number Taxa de parcelamento
observacoes string Observações gerais
duracao_noites integer Pacote: duração em noites
destino_cidade string Pacote: cidade destino
destino_estado string Pacote: estado destino
destino_pais string Pacote: país destino
regime_hospedagem string Pacote: cafe_da_manha, meia_pensao, all_inclusive...
categoria_hotel string Pacote: 3_estrelas, 4_estrelas, 5_estrelas
nome_hotel string Pacote: nome do hotel
incluso array Pacote: itens inclusos (array de strings)
nao_incluso array Pacote: itens não inclusos
documentos_necessarios string Pacote: documentos para embarque
observacoes_pacote string Pacote: observações específicas
mostrar_site boolean Publicar na vitrine pública
mostrar_vagas_disponiveis boolean Mostrar "X vagas restantes" no público
vagas_alerta_poucas integer Alerta amarelo "últimas N" (gatilho urgência)
vagas_alerta_ultimas integer Alerta vermelho "últimas N" (urgência crítica)
vagas_reservadas integer Vagas pré-reservadas (debitam de vagas_maximas)
desativar_vendas_dias_antes integer Dias antes da viagem para fechar vendas
prazo_pagamento_minutos integer Minutos para expirar reserva sem pagamento
observacoes_internas string Observações privadas (não vão pro cliente)
exigir_contrato boolean Forçar aceite de contrato no checkout
exigir_documentos boolean Exigir upload de documentos antes do embarque
incluir_observacoes_no_cartao boolean Incluir observações no cartão de embarque
duracao_dias integer Duração em dias (display)
recorrencia_config object Config de série semanal/mensal
recorrencia_ativa boolean Toggle de geração automática da série
endereco string Endereço completo
latitude number Latitude (-90..90)
longitude number Longitude (-180..180)
video string URL de vídeo (YouTube/Vimeo)
contrato_template_id integer ID do template de contrato a usar
whatsapp string Número WhatsApp para esta excursão (ex: 5511999999999)
mostrar_whatsapp boolean Exibir botão WhatsApp na página pública
modo_venda string Modo de venda (ex: aberta, b2b, fechada)
modo_preco string fixo (mostra preço), sob_consulta (esconde), hibrido
preco_display_modo string Como exibir o preço público (a_partir_de, fixo, ate)
preco_display_intervalo boolean Exibir intervalo mín-máx no público
escolha_assento_a_partir_de date Data a partir da qual cliente pode escolher assento
guias_contam_vaga boolean Guias ocupam vaga no transporte
publicar_em date Publicar automaticamente nesta data
despublicar_em date Despublicar automaticamente nesta data
seguro_link string URL do seguro viagem (afiliado)
seguro_label string Texto do botão de seguro
external_ref string ID/código do seu sistema origem (ex: iBus-123)
external_source string Nome do sistema origem (ex: ibus, sagtur)
categorias array Lista de categorias a criar: [{nome*, descricao, idade_min, idade_max, ordem, ref}] — use `ref` como rótulo para referenciar em precos
transportes array Lista de transportes a criar: [{veiculo_id*, nome, numero, tipo, vagas_total}]
embarques array Lista de embarques: [{nome*, endereco, cidade, estado, hora_embarque, vagas_max, ref}] — use `ref` para referenciar em precos
precos array Lista de preços: [{categoria_id|categoria_ref*, embarque_id|embarque_ref, valor*}] — pode usar ref das categorias/embarques criados na mesma chamada
conteudo object Conteúdo da vitrine pública (page builder). Aceita: titulo, subtitulo, resumo, descricao_completa, atracoes[], o_que_esperar (string) ou o_que_esperar_items[], regras/regras_items[], o_que_levar/o_que_levar_items[], inclusos/inclusos_items[], nao_inclusos/nao_inclusos_items[], videos[], links[{titulo,url}], capa_url, banner_display_mode (hero|vitrine|split|minimal), meta_title, meta_description, status (rascunho|publicado). Detalhes em /excursoes/{id}/conteudo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Excursão criada com sucesso.",
    "data": {
        "id": 123,
        "nome": "Nova Excursão",
        "slug": "nova-excursao-xyz123",
        "tipo_excursao": "excursao",
        "status": "rascunho",
        "data_inicio": "2026-05-10",
        "vagas_maximas": 46,
        "categorias": [
            {
                "id": 1,
                "nome": "Adulto"
            }
        ],
        "transportes": [
            {
                "id": 101,
                "veiculo_id": 5,
                "vagas_total": 46
            }
        ],
        "embarques": [
            {
                "id": 210,
                "nome": "Terminal Tietê",
                "hora_embarque": "06:00"
            }
        ],
        "precos": [
            {
                "id": 305,
                "categoria_id": 1,
                "valor": 1450
            }
        ]
    }
}

Atualiza parcialmente uma excursão. **Aceita todos os campos do POST** (todos opcionais). Envie só os que deseja alterar. Também aceita `conteudo` inline pra atualizar a vitrine pública na mesma chamada.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
nome string Nome
slug string Slug
tipo_excursao string excursao ou pacote_viagem
descricao string Descrição
imagem string URL da imagem principal
galeria array Array de URLs
pais string País
estado string Estado
cidade string Cidade
local string Local
endereco string Endereço
latitude number Latitude
longitude number Longitude
data_inicio date Data início
data_fim date Data fim
hora_inicio string Hora início
hora_fim string Hora fim
status string rascunho, publicada, cancelada, finalizada
publicar_em date Publicar nesta data
despublicar_em date Despublicar nesta data
vagas_maximas integer Vagas máximas
vagas_reservadas integer Vagas pré-reservadas
mostrar_site boolean Publicar na vitrine
mostrar_vagas_disponiveis boolean Mostrar contador de vagas
vagas_alerta_poucas integer Alerta urgência (amarelo)
vagas_alerta_ultimas integer Alerta urgência (vermelho)
observacoes string Observações públicas
observacoes_internas string Observações internas
incluir_observacoes_no_cartao boolean Imprimir no cartão
exigir_contrato boolean Forçar aceite contrato
exigir_documentos boolean Forçar upload docs
contrato_template_id integer Template do contrato
desativar_vendas_dias_antes integer Dias para fechar vendas
prazo_pagamento_minutos integer Minutos pra expirar reserva
duracao_dias integer Duração em dias
recorrencia_config object Config série
recorrencia_ativa boolean Toggle série
permitir_escolha_assento boolean Cliente escolhe
escolha_assento_dias_antes integer Dias antes pra liberar
escolha_assento_a_partir_de date Data específica
permitir_troca_transporte boolean Troca de transporte
guias_contam_vaga boolean Guia ocupa vaga
parcelas_max integer Parcelas máx
acrescimo_tipo string percentual ou fixo
acrescimo_parcela number Taxa parcelamento
modo_preco string fixo, sob_consulta, hibrido
preco_display_modo string Display preço
preco_display_intervalo boolean Intervalo público
video string URL vídeo
whatsapp string WhatsApp da viagem
mostrar_whatsapp boolean Botão WhatsApp
duracao_noites integer Pacote: noites
destino_cidade string Pacote: cidade destino
destino_estado string Pacote: estado
destino_pais string Pacote: país
regime_hospedagem string Pacote: regime
categoria_hotel string Pacote: estrelas
nome_hotel string Pacote: hotel
incluso array Pacote: inclusos
nao_incluso array Pacote: não inclusos
documentos_necessarios string Pacote: documentos
observacoes_pacote string Pacote: observações
seguro_link string URL seguro
seguro_label string Texto botão seguro
categoria_ids array IDs de categorias (sync)
external_ref string Ref do sistema origem
external_source string Nome sistema origem
conteudo object Conteúdo da vitrine pública (page builder). Ver schema completo em /excursoes/{id}/conteudo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Excursão atualizada com sucesso.",
    "data": {
        "id": 45,
        "nome": "Excursão Atualizada",
        "status": "publicada"
    }
}

Remove uma excursão. Apenas excursões sem passageiros podem ser excluídas.

Escopo necessário excursoes:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Excursão excluída com sucesso."
}

Conteúdo (Excursão)

Página de conteúdo público da excursão (atrações, inclusos, regras, etc) que renderiza a vitrine. 1:1 com excursão.

Retorna o conteúdo público da excursão (página da vitrine). Se ainda não foi criado, retorna estrutura vazia com defaults.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 22,
        "excursao_id": 45,
        "status": "publicado",
        "modo": "estruturado",
        "titulo": "Gramado Natal Luz 2026",
        "subtitulo": "5 dias de magia entre luzes e chocolate",
        "resumo": "Excursão completa com hospedagem, traslados e shows do Natal Luz.",
        "descricao_completa": "

HTML longo descritivo...<\/p>", "atracoes": [ "Show Natal Luz", "Mini Mundo", "Lago Negro", "Rua Coberta" ], "o_que_esperar": "Hospedagem 4 noites\nCafé incluso\nGuia bilíngue", "o_que_esperar_array": [ "Hospedagem 4 noites", "Café incluso", "Guia bilíngue" ], "regras": "Idade mínima 0 anos\nMenores acompanhados\nNão fumar no ônibus", "regras_array": [ "Idade mínima 0 anos", "Menores acompanhados", "Não fumar no ônibus" ], "o_que_levar": "Documento RG\nAgasalho\nMedicamentos pessoais", "o_que_levar_array": [ "Documento RG", "Agasalho", "Medicamentos pessoais" ], "inclusos": "Transporte ida e volta\nHospedagem 4 diárias\nCafé da manhã", "inclusos_array": [ "Transporte ida e volta", "Hospedagem 4 diárias", "Café da manhã" ], "nao_inclusos": "Almoço e jantar\nBebidas\nDespesas extras", "nao_inclusos_array": [ "Almoço e jantar", "Bebidas", "Despesas extras" ], "videos": [ "https:\/\/youtu.be\/abc123" ], "links": [ { "titulo": "Mapa do roteiro", "url": "https:\/\/google.com\/maps\/..." } ], "capa_url": "https:\/\/cdn...\/gramado-capa.jpg", "banner_display_mode": "hero", "meta_title": "Gramado Natal Luz 2026 — 5 dias inesquecíveis", "meta_description": "Venha viver a magia do Natal Luz com a melhor agência.", "meta_keywords": "gramado, natal luz, excursão" } }

Cria ou atualiza o conteúdo público (upsert por excursao_id). **Os 5 campos de lista** (`o_que_esperar`, `regras`, `o_que_levar`, `inclusos`, `nao_inclusos`) aceitam 2 formatos: string com `\n` separador OU array via `{campo}_items[]` (será convertido automaticamente).

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
modo string estruturado (default) ou livre (HTML único)
conteudo_livre string HTML completo (só se modo=livre)
titulo string Título do bloco principal
subtitulo string Subtítulo
resumo string Resumo curto
descricao_completa string Descrição longa (HTML permitido)
atracoes array Lista de atrações: ["Praia X", "Centro Y"]
legenda_atracoes string Texto acima da lista de atrações
o_que_esperar string Texto multilinha (1 item por linha)
o_que_esperar_items array Alternativa: array de strings
legenda_o_que_esperar string Texto acima
regras string Regras e normas (multilinha)
regras_items array Alternativa array
legenda_regras string Texto acima
o_que_levar string Itens a levar (multilinha)
o_que_levar_items array Alternativa array
inclusos string Itens inclusos (multilinha)
inclusos_items array Alternativa array
nao_inclusos string Itens não inclusos (multilinha)
nao_inclusos_items array Alternativa array
videos array URLs YouTube/Vimeo
legenda_videos string Texto acima dos vídeos
links array Links: [{titulo, url}]
titulo_galeria string Título da galeria
legenda_galeria string Texto acima da galeria
ingressos_ids array IDs de ingressos do tenant a exibir
legenda_ingressos string Texto acima
capa_url string URL da imagem de capa
banner_display_mode string hero | vitrine | split | minimal
meta_title string SEO: título da página
meta_description string SEO: meta description (até 500 chars)
meta_keywords string SEO: keywords
status string rascunho (default) ou publicado

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Conteúdo salvo com sucesso.",
    "data": {
        "id": 22,
        "excursao_id": 45,
        "status": "publicado",
        "titulo": "Gramado Natal Luz 2026",
        "atracoes": [
            "Show Natal Luz",
            "Mini Mundo",
            "Lago Negro"
        ],
        "inclusos_array": [
            "Transporte",
            "Hospedagem",
            "Café"
        ]
    }
}

Marca o conteúdo como `publicado`. Necessário pra aparecer na vitrine pública.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Conteúdo publicado."
}

Volta o status para `rascunho` — o conteúdo deixa de aparecer na vitrine pública (mas a excursão pode continuar publicada).

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Conteúdo despublicado."
}

Fotos & Capa (Excursão)

Galeria pública da excursão (até 10 fotos) + capa. Upload via multipart/form-data ou URL externa com validações de segurança (mime real via finfo, magic bytes, anti-SSRF, dimensões máx, sem SVG).

Retorna as fotos da galeria ordenadas. Inclui URL pública, thumbnail, legenda e flag de destaque.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 12,
            "excursao_id": 45,
            "url": "https:\/\/...\/storage\/tenants\/X\/excursoes\/45\/foto1.webp",
            "thumbnail_url": "https:\/\/...\/storage\/tenants\/X\/excursoes\/45\/foto1_thumb.webp",
            "legenda": "Vista da praia",
            "alt_text": "Praia ao pôr do sol",
            "destaque": false,
            "ordem": 1,
            "largura": 1920,
            "altura": 1280,
            "tamanho": 245000
        }
    ]
}

Aceita 2 caminhos: **(a)** multipart/form-data com campo `foto` (arquivo binário) **OU (b)** application/json com campo `url` (URL externa que será baixada e re-hospedada). Limite: 10 fotos por excursão. Validações de segurança: extensão whitelist (jpg/jpeg/png/webp/gif), MIME real via finfo, magic bytes via getimagesize, dimensões máx 8000x8000, anti-SSRF na URL externa (bloqueia IPs privados).

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
foto file Arquivo da foto (jpg/png/webp/gif, máx 10MB). multipart/form-data. Use ESTE ou `url`, não os dois.
url string URL pública da imagem (será baixada e re-hospedada). Apenas HTTP/HTTPS, IPs privados bloqueados.
legenda string Legenda visível na vitrine
alt_text string Texto alternativo (SEO/acessibilidade)
destaque boolean Marcar como destaque

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Foto adicionada.",
    "data": {
        "id": 12,
        "url": "https:\/\/...\/foto.webp",
        "thumbnail_url": "https:\/\/...\/foto_thumb.webp",
        "ordem": 3
    }
}

Edita legenda, alt_text, destaque ou ordem de uma foto existente.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID da foto

Corpo da requisição

Campo Tipo Descrição
legenda string Legenda
alt_text string Texto alternativo
destaque boolean Destaque
ordem integer Posição na galeria (1-N)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Foto atualizada."
}

Remove a foto da galeria e apaga os arquivos do storage.

Escopo necessário excursoes:delete

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID da foto

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Foto removida."
}

Atualiza a ordem de exibição das fotos. Envie o array `ordem` com os IDs na sequência desejada (índice 0 = primeira posição).

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
ordem * array Array de IDs na ordem desejada: [42, 41, 43, ...]

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Ordem atualizada."
}

Define a imagem de capa da excursão (renderizada como banner). Aceita multipart (`capa`) OU URL externa (`url`). A URL externa não é re-hospedada (fica como apontamento), mas passa por validação anti-SSRF e content-type. Para garantia de disponibilidade, prefira upload multipart.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
capa file Arquivo da capa (jpg/png/webp/gif, máx 5MB)
url string URL pública da capa (alternativa ao upload)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Capa atualizada.",
    "data": {
        "capa_url": "https:\/\/...\/storage\/...\/capa.jpg"
    }
}

Categorias (Excursão)

Sub-recurso de excursão: categorias de passageiro (Adulto, Criança, etc)

Retorna as categorias cadastradas para a excursão.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 197,
            "excursao_id": 70,
            "nome": "Adulto",
            "descricao": "Passageiro adulto",
            "idade_min": 18,
            "idade_max": null,
            "ordem": 1,
            "vagas_max_categoria": null,
            "qtd_passageiros": 1,
            "requer_documento": false,
            "documento_tipo": null,
            "ativo": true,
            "vagas_ocupadas": 0,
            "vagas_disponiveis": null,
            "created_at": "2026-04-21T20:44:47.000000Z"
        }
    ]
}

Retorna uma categoria específica.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID da categoria

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 197,
        "excursao_id": 70,
        "nome": "Adulto",
        "descricao": "Passageiro adulto",
        "idade_min": 18,
        "idade_max": null,
        "ordem": 1,
        "vagas_max_categoria": null,
        "qtd_passageiros": 1,
        "requer_documento": false,
        "documento_tipo": null,
        "ativo": true,
        "vagas_ocupadas": 0,
        "vagas_disponiveis": null,
        "created_at": "2026-04-21T20:44:47.000000Z"
    }
}

Cria uma nova categoria vinculada à excursão.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
nome * string Nome da categoria (ex: Adulto, Criança, Idoso)
descricao string Descrição da categoria
idade_min integer Idade mínima
idade_max integer Idade máxima
ordem integer Ordem de exibição (1, 2, 3...)
vagas_max_categoria integer Limite de vagas para esta categoria
qtd_passageiros integer Quantos passageiros ocupam (default 1; use 0 para bebê de colo)
requer_documento boolean Exige documento específico
documento_tipo string Tipo do documento exigido
ativo boolean Categoria ativa

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Categoria criada com sucesso.",
    "data": {
        "id": 197,
        "excursao_id": 70,
        "nome": "Adulto",
        "descricao": "Passageiro adulto",
        "idade_min": 18,
        "idade_max": null,
        "ordem": 1,
        "vagas_max_categoria": null,
        "qtd_passageiros": 1,
        "requer_documento": false,
        "documento_tipo": null,
        "ativo": true,
        "vagas_ocupadas": 0,
        "vagas_disponiveis": null,
        "created_at": "2026-04-21T20:44:47.000000Z"
    }
}

Atualiza parcialmente uma categoria.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID da categoria

Corpo da requisição

Campo Tipo Descrição
nome string Nome da categoria (ex: Adulto, Criança, Idoso)
descricao string Descrição da categoria
idade_min integer Idade mínima
idade_max integer Idade máxima
ordem integer Ordem de exibição (1, 2, 3...)
vagas_max_categoria integer Limite de vagas para esta categoria
qtd_passageiros integer Quantos passageiros ocupam (default 1; use 0 para bebê de colo)
requer_documento boolean Exige documento específico
documento_tipo string Tipo do documento exigido
ativo boolean Categoria ativa

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Categoria atualizada.",
    "data": {
        "id": 197,
        "excursao_id": 70,
        "nome": "Adulto",
        "descricao": "Passageiro adulto",
        "idade_min": 18,
        "idade_max": null,
        "ordem": 1,
        "vagas_max_categoria": null,
        "qtd_passageiros": 1,
        "requer_documento": false,
        "documento_tipo": null,
        "ativo": true,
        "vagas_ocupadas": 0,
        "vagas_disponiveis": null,
        "created_at": "2026-04-21T20:44:47.000000Z"
    }
}

Remove uma categoria.

Escopo necessário excursoes:delete

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID da categoria

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Categoria excluída."
}

Reordena a exibição das categorias.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
ordem * array Array de IDs na nova ordem: [id1, id2, id3]

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Categorias reordenadas."
}

Embarques (Excursão)

Sub-recurso de excursão: pontos de embarque/retorno

Retorna todos os pontos de embarque da excursão.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 188,
            "excursao_id": 70,
            "nome": "Terminal Tietê",
            "endereco": "Av. Cruzeiro do Sul, 1800",
            "cidade": "São Paulo",
            "estado": "SP",
            "cep": "02036-100",
            "referencia": "Plataforma 35",
            "hora_embarque": "05:00",
            "hora_retorno": "23:00",
            "data_embarque": "2026-11-15",
            "tolerancia_minutos": 15,
            "latitude": null,
            "longitude": null,
            "transporte_id": null,
            "permite_reserva_online": true,
            "vagas_max": null,
            "ordem": 1,
            "ativo": true,
            "created_at": "2026-04-21T20:44:17.000000Z"
        }
    ]
}

Retorna um ponto de embarque.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID do embarque

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 188,
        "excursao_id": 70,
        "nome": "Terminal Tietê",
        "endereco": "Av. Cruzeiro do Sul, 1800",
        "cidade": "São Paulo",
        "estado": "SP",
        "cep": "02036-100",
        "referencia": "Plataforma 35",
        "hora_embarque": "05:00",
        "hora_retorno": "23:00",
        "data_embarque": "2026-11-15",
        "tolerancia_minutos": 15,
        "latitude": null,
        "longitude": null,
        "transporte_id": null,
        "permite_reserva_online": true,
        "vagas_max": null,
        "ordem": 1,
        "ativo": true,
        "created_at": "2026-04-21T20:44:17.000000Z"
    }
}

Cadastra um novo ponto de embarque.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
nome * string Nome do ponto (ex: Terminal Tietê)
endereco string Endereço completo
cidade string Cidade
estado string UF
cep string CEP
referencia string Ponto de referência
hora_embarque string Horário de embarque (H:i)
hora_retorno string Horário de retorno (H:i)
data_embarque date Data específica (sobrescreve data_inicio da excursão)
tolerancia_minutos integer Tolerância de atraso em minutos
latitude number Latitude do ponto
longitude number Longitude do ponto
transporte_id integer ID do transporte específico (se múltiplos)
permite_reserva_online boolean Permite reserva online (default true)
vagas_max integer Limite de vagas por este embarque
ordem integer Ordem de exibição
ativo boolean Embarque ativo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Embarque criado.",
    "data": {
        "id": 188,
        "excursao_id": 70,
        "nome": "Terminal Tietê",
        "endereco": "Av. Cruzeiro do Sul, 1800",
        "cidade": "São Paulo",
        "estado": "SP",
        "cep": "02036-100",
        "referencia": "Plataforma 35",
        "hora_embarque": "05:00",
        "hora_retorno": "23:00",
        "data_embarque": "2026-11-15",
        "tolerancia_minutos": 15,
        "latitude": null,
        "longitude": null,
        "transporte_id": null,
        "permite_reserva_online": true,
        "vagas_max": null,
        "ordem": 1,
        "ativo": true,
        "created_at": "2026-04-21T20:44:17.000000Z"
    }
}

Atualiza parcialmente um ponto de embarque.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID do embarque

Corpo da requisição

Campo Tipo Descrição
nome string Nome do ponto (ex: Terminal Tietê)
endereco string Endereço completo
cidade string Cidade
estado string UF
cep string CEP
referencia string Ponto de referência
hora_embarque string Horário de embarque (H:i)
hora_retorno string Horário de retorno (H:i)
data_embarque date Data específica (sobrescreve data_inicio da excursão)
tolerancia_minutos integer Tolerância de atraso em minutos
latitude number Latitude do ponto
longitude number Longitude do ponto
transporte_id integer ID do transporte específico (se múltiplos)
permite_reserva_online boolean Permite reserva online (default true)
vagas_max integer Limite de vagas por este embarque
ordem integer Ordem de exibição
ativo boolean Embarque ativo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Embarque atualizado.",
    "data": {
        "id": 188,
        "excursao_id": 70,
        "nome": "Terminal Tietê",
        "endereco": "Av. Cruzeiro do Sul, 1800",
        "cidade": "São Paulo",
        "estado": "SP",
        "cep": "02036-100",
        "referencia": "Plataforma 35",
        "hora_embarque": "05:00",
        "hora_retorno": "23:00",
        "data_embarque": "2026-11-15",
        "tolerancia_minutos": 15,
        "latitude": null,
        "longitude": null,
        "transporte_id": null,
        "permite_reserva_online": true,
        "vagas_max": null,
        "ordem": 1,
        "ativo": true,
        "created_at": "2026-04-21T20:44:17.000000Z"
    }
}

Remove um ponto de embarque.

Escopo necessário excursoes:delete

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID do embarque

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Embarque excluído."
}

Reordena a exibição dos embarques.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
ordem * array Array de IDs na nova ordem

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Embarques reordenados."
}

Preços (Excursão)

Sub-recurso de excursão: valores por categoria × embarque

Retorna todos os preços (categoria × embarque) da excursão.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 371,
            "excursao_id": 70,
            "categoria_id": 197,
            "embarque_id": 188,
            "valor": 250,
            "valor_ate": null,
            "valor_aumenta_em": null,
            "permite_reserva_online": true,
            "ativo": true,
            "categoria": {
                "id": 197,
                "nome": "Adulto"
            },
            "embarque": {
                "id": 188,
                "nome": "Terminal Tietê"
            },
            "created_at": "2026-04-21T20:44:57.000000Z"
        }
    ]
}

Retorna um preço específico.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID do preço

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 371,
        "excursao_id": 70,
        "categoria_id": 197,
        "embarque_id": 188,
        "valor": 250,
        "valor_ate": null,
        "valor_aumenta_em": null,
        "permite_reserva_online": true,
        "ativo": true,
        "categoria": {
            "id": 197,
            "nome": "Adulto"
        },
        "embarque": {
            "id": 188,
            "nome": "Terminal Tietê"
        },
        "created_at": "2026-04-21T20:44:57.000000Z"
    }
}

Cadastra um preço vinculado a uma categoria (e opcionalmente a um embarque).

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
categoria_id * integer ID da categoria (Adulto, Criança, etc)
embarque_id integer ID do embarque (permite preço diferente por ponto)
valor * number Valor atual cobrado (R$)
valor_ate number Valor limite quando há reajuste progressivo
valor_aumenta_em date Data em que o valor passa para valor_ate
permite_reserva_online boolean Permite reserva online (default true)
ativo boolean Preço ativo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Preço criado.",
    "data": {
        "id": 371,
        "excursao_id": 70,
        "categoria_id": 197,
        "embarque_id": 188,
        "valor": 250,
        "valor_ate": null,
        "valor_aumenta_em": null,
        "permite_reserva_online": true,
        "ativo": true,
        "categoria": {
            "id": 197,
            "nome": "Adulto"
        },
        "embarque": {
            "id": 188,
            "nome": "Terminal Tietê"
        },
        "created_at": "2026-04-21T20:44:57.000000Z"
    }
}

Atualiza parcialmente um preço.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID do preço

Corpo da requisição

Campo Tipo Descrição
categoria_id integer ID da categoria (Adulto, Criança, etc)
embarque_id integer ID do embarque (permite preço diferente por ponto)
valor number Valor atual cobrado (R$)
valor_ate number Valor limite quando há reajuste progressivo
valor_aumenta_em date Data em que o valor passa para valor_ate
permite_reserva_online boolean Permite reserva online (default true)
ativo boolean Preço ativo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Preço atualizado.",
    "data": {
        "id": 371,
        "excursao_id": 70,
        "categoria_id": 197,
        "embarque_id": 188,
        "valor": 250,
        "valor_ate": null,
        "valor_aumenta_em": null,
        "permite_reserva_online": true,
        "ativo": true,
        "categoria": {
            "id": 197,
            "nome": "Adulto"
        },
        "embarque": {
            "id": 188,
            "nome": "Terminal Tietê"
        },
        "created_at": "2026-04-21T20:44:57.000000Z"
    }
}

Remove um preço.

Escopo necessário excursoes:delete

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID do preço

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Preço excluído."
}

Atualiza múltiplos preços em uma única chamada. Útil para reajustes.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
precos * array Lista: [{id*, valor?, valor_ate?, valor_aumenta_em?, ativo?}]

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Preços atualizados.",
    "data": {
        "atualizados": 4
    }
}

Variações

Opções de preço de um pacote de viagem (Leito, Semi-leito, tipo de quarto). Cada item de "precos" da excursão traz excursao_variacao_id; é aqui que se descobre o nome por trás desse id. Só existem em excursões com tipo_excursao=pacote_viagem.

Retorna as variações da excursão, na ordem definida no painel, com a faixa de preço e a ocupação de cada uma. Em excursão que não é pacote de viagem a lista volta vazia.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
ativas boolean query Quando 1, retorna apenas as variações ativas

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 82,
            "excursao_id": 39,
            "nome": "Quarto DUPLO + Bike Mecânica",
            "descricao": null,
            "tipo": "generica",
            "tipo_label": "Genérica",
            "codigo": null,
            "ordem": 4,
            "ativa": true,
            "vagas_maximas": null,
            "vagas_ocupadas": 6,
            "vagas_disponiveis": null,
            "fornecedor_id": null,
            "precos": {
                "quantidade": 1,
                "menor": 1990,
                "maior": 1990
            }
        }
    ]
}

Retorna uma variação específica da excursão.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID da variação

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 82,
        "excursao_id": 39,
        "nome": "Quarto DUPLO + Bike Mecânica",
        "descricao": null,
        "tipo": "generica",
        "tipo_label": "Genérica",
        "codigo": null,
        "ordem": 4,
        "ativa": true,
        "vagas_maximas": null,
        "vagas_ocupadas": 6,
        "vagas_disponiveis": null,
        "fornecedor_id": null,
        "precos": {
            "quantidade": 1,
            "menor": 1990,
            "maior": 1990
        }
    }
}

Cria uma variação na excursão. Entra no fim da lista. Recusa com 422 quando a excursão não é pacote de viagem (TIPO_NAO_SUPORTA_VARIACAO) ou quando o código já existe na mesma excursão (DUPLICATE_CODE).

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
nome * string Nome exibido ao cliente (ex: Leito, Semi-leito, Quarto DUPLO + Bike Mecânica)
tipo * string hospedagem, acomodacao, refeicao, transporte ou generica
descricao string Detalhamento do que está incluído
codigo string Código interno. Deve ser único dentro da excursão
ativa boolean Disponível para venda (default true)
vagas_maximas integer Limite de vagas desta variação. Nulo = sem limite
fornecedor_id integer Fornecedor responsável por esta variação
metadata object Campos livres do integrador

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Variação criada com sucesso",
    "data": {
        "id": 82,
        "excursao_id": 39,
        "nome": "Quarto DUPLO + Bike Mecânica",
        "descricao": null,
        "tipo": "generica",
        "tipo_label": "Genérica",
        "codigo": null,
        "ordem": 4,
        "ativa": true,
        "vagas_maximas": null,
        "vagas_ocupadas": 6,
        "vagas_disponiveis": null,
        "fornecedor_id": null,
        "precos": {
            "quantidade": 1,
            "menor": 1990,
            "maior": 1990
        }
    }
}

Atualização parcial: envie apenas os campos que quer mudar. Recusa com 422 ao reduzir vagas_maximas abaixo do que já foi vendido (LIMITE_ABAIXO_DO_VENDIDO). Para tirar da venda sem apagar histórico, envie ativa=false.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID da variação

Corpo da requisição

Campo Tipo Descrição
nome string Nome exibido ao cliente (ex: Leito, Semi-leito, Quarto DUPLO + Bike Mecânica)
tipo string hospedagem, acomodacao, refeicao, transporte ou generica
descricao string Detalhamento do que está incluído
codigo string Código interno. Deve ser único dentro da excursão
ativa boolean Disponível para venda (default true)
vagas_maximas integer Limite de vagas desta variação. Nulo = sem limite
fornecedor_id integer Fornecedor responsável por esta variação
metadata object Campos livres do integrador

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Variação atualizada com sucesso",
    "data": {
        "id": 82,
        "excursao_id": 39,
        "nome": "Quarto DUPLO + Bike Mecânica",
        "descricao": null,
        "tipo": "generica",
        "tipo_label": "Genérica",
        "codigo": null,
        "ordem": 4,
        "ativa": true,
        "vagas_maximas": null,
        "vagas_ocupadas": 6,
        "vagas_disponiveis": null,
        "fornecedor_id": null,
        "precos": {
            "quantidade": 1,
            "menor": 1990,
            "maior": 1990
        }
    }
}

Remove a variação e os preços ligados a ela. Bloqueado com 422 quando já há passageiros na variação (VARIACAO_COM_PASSAGEIROS); nesse caso use ativa=false.

Escopo necessário excursoes:delete

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID da variação

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Variação removida com sucesso"
}

Pacote de Viagem

Sub-recursos da aba "Editar Viagem > Pacote": dados gerais, roteiro dia-a-dia, componentes, voos, cruzeiro, allotment, cotações com opções e vouchers. Exige excursão com `tipo_excursao=pacote_viagem` (exceto cotações, que aceitam qualquer tipo). Para gestão de quartos/rooming, use o módulo de Hospedagem (addon).

Retorna dados gerais do pacote (país, cidade, hotel, regime, observações).

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "pais": "Argentina",
        "estado": "Buenos Aires",
        "cidade": "Buenos Aires",
        "nome_hotel": "Hotel Madero",
        "categoria_hotel": "5 estrelas",
        "regime_hospedagem": "Café da manhã",
        "documentos_necessarios": "Passaporte ou RG válido",
        "observacoes_pacote": "Reembolso integral até 30 dias antes.",
        "duracao_noites": 5
    }
}

`duracao_noites` é calculada automaticamente pelas datas da excursão.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Corpo da requisição

Campo Tipo Descrição
pais string Max 100
estado string Max 100
cidade string Max 100
nome_hotel string Max 255
categoria_hotel string Ex: 5 estrelas, Pousada
regime_hospedagem string Café, Meia pensão, All inclusive
documentos_necessarios string Texto multilinha
observacoes_pacote string Texto multilinha

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Dados do pacote atualizados."
}

Listar dias do roteiro

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 10,
            "dia": 1,
            "titulo": "Chegada em Buenos Aires",
            "cidade": "Buenos Aires",
            "pernoite": "Hotel Madero",
            "regime": "Café da manhã",
            "atividades": [
                "Traslado",
                "City tour"
            ]
        }
    ]
}

Adicionar dia ao roteiro

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Corpo da requisição

Campo Tipo Descrição
dia * integer Número sequencial do dia (1, 2, 3...)
titulo * string Max 255
descricao string
cidade string
pernoite string
regime string Café, almoço, jantar
atividades array Lista de atividades do dia
imagem string Path retornado por POST /roteiro/upload-imagem

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 11,
        "dia": 2,
        "titulo": "Tour pela cidade"
    }
}

Atualizar dia do roteiro

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
itinerarioId * integer path

Corpo da requisição

Campo Tipo Descrição
dia * integer
titulo * string
descricao string
imagem string

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Remover dia do roteiro

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
itinerarioId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Dia removido do roteiro."
}

Reordenar dias

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Corpo da requisição

Campo Tipo Descrição
items * array Lista de {id, dia} com a nova ordem

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Roteiro reordenado."
}

Faz upload de uma imagem para usar em um dia do roteiro. Retorna `path` que deve ser informado no campo `imagem` ao criar ou atualizar o dia.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Corpo da requisição

Campo Tipo Descrição
imagem * file multipart/form-data — jpg/jpeg/png/webp, max 5MB

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "path": "excursoes\/123\/roteiro\/abcd1234.jpg"
    }
}

Retorna lista de componentes + agregados (custo_total, preco_venda, margem, confirmados).

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "componentes": [
            {
                "id": 25,
                "tipo": "hospedagem",
                "nome": "Hotel Madero - 5 noites",
                "custo_unitario": 350,
                "moeda_custo": "USD",
                "confirmacao_status": "pendente"
            }
        ],
        "dashboard": {
            "custo_total": 1820,
            "preco_venda": 2500,
            "margem": 680,
            "margem_percentual": 27.2,
            "confirmados": 0,
            "total": 1
        }
    }
}

Adicionar componente

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Corpo da requisição

Campo Tipo Descrição
tipo * string hospedagem, refeicao, ingresso, transfer, voo, seguro, etc
nome * string
descricao string
fornecedor_nome string
fornecedor_email string
fornecedor_telefone string
confirmacao_status string pendente | confirmado | negado
confirmacao_codigo string
custo_unitario number
custo_fixo number
tipo_custo string por_pessoa | por_quarto | fixo | por_diaria
moeda_custo string BRL, USD, EUR... (default BRL)
taxa_cambio number Se moeda != BRL
taxa_cambio_data string YYYY-MM-DD
incluso boolean
obrigatorio boolean
valor_adicional number Se não incluso

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 25
    }
}

Atualizar componente

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
componenteId * integer path

Corpo da requisição

Campo Tipo Descrição
tipo * string
nome * string
confirmacao_status string
custo_unitario number
ativo boolean

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Remover componente

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
componenteId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Componente removido."
}

Listar voos

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": []
}

Adicionar voo

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Corpo da requisição

Campo Tipo Descrição
tipo * string ida | volta | conexao
cia_aerea string
numero_voo string
aeroporto_origem string IATA (3 letras)
aeroporto_destino string IATA (3 letras)
data_voo string YYYY-MM-DD
horario_partida string HH:MM
horario_chegada string HH:MM
classe string economica | executiva | primeira
bagagem string
observacoes string

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 5
    }
}

Atualizar voo

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
vooId * integer path

Corpo da requisição

Campo Tipo Descrição
tipo * string
cia_aerea string
numero_voo string

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Remover voo

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
vooId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Voo removido."
}

1:1 com a excursão. Retorna null se não houver.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": null
}

Cria ou atualiza (uma única operação).

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Corpo da requisição

Campo Tipo Descrição
companhia string Ex: MSC, Costa, Royal Caribbean
navio string
porto_embarque string
porto_retorno string
partida string YYYY-MM-DD
chegada string YYYY-MM-DD
itinerario string Texto livre
observacoes string

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Remover cruzeiro

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Cruzeiro removido."
}

Quartos pré-reservados com deadline de liberação.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": []
}

Criar allotment

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Corpo da requisição

Campo Tipo Descrição
tipo * string Ex: quarto, cabine, assento
descricao * string
quantidade_total * integer
componente_id integer
deadline string YYYY-MM-DD
custo_unitario number
observacoes string

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 9
    }
}

Atualizar allotment

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
allotmentId * integer path

Corpo da requisição

Campo Tipo Descrição
tipo * string
descricao * string
quantidade_total * integer
status string ativo | esgotado | expirado | cancelado

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Remover allotment

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
allotmentId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Allotment removido."
}

Disponível para qualquer excursão (não exige tipo_excursao=pacote_viagem).

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": []
}

Criar cotação

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Corpo da requisição

Campo Tipo Descrição
cliente_id * integer
mensagem_personalizada string
validade string YYYY-MM-DD

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 12
    }
}

Atualizar cotação

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
cotacaoId * integer path

Corpo da requisição

Campo Tipo Descrição
cliente_id * integer
status string rascunho | enviada | visualizada | aceita | recusada | expirada

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Remover cotação

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
cotacaoId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Cotacao removida."
}

Adicionar opção à cotação

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
cotacaoId * integer path

Corpo da requisição

Campo Tipo Descrição
nome * string Ex: Pacote Premium
descricao string
valor_total * number
custo_total number
componentes_inclusos array Lista de strings com o que inclui
detalhes object JSON livre
destaque boolean Marcar como recomendada

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 33
    }
}

Atualizar opção da cotação

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
cotacaoId * integer path
opcaoId * integer path

Corpo da requisição

Campo Tipo Descrição
nome * string
valor_total * number

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Remover opção da cotação

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
cotacaoId * integer path
opcaoId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Opção removida."
}

Listar vouchers de fornecedor

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": []
}

Criar voucher

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Corpo da requisição

Campo Tipo Descrição
tipo * string Ex: ingresso, transfer, hospedagem
fornecedor_nome * string
fornecedor_contato string
componente_id integer
codigo_reserva string
data_servico string YYYY-MM-DD
horario string HH:MM
detalhes string
observacoes_internas string
passageiros array IDs de passageiros vinculados
status string pendente | confirmado | cancelado

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 18
    }
}

Atualizar voucher

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
voucherId * integer path

Corpo da requisição

Campo Tipo Descrição
tipo * string
fornecedor_nome * string
status string

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Remover voucher

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)
voucherId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Voucher removido."
}

Custo unitário total, custo fixo total, custo total por pessoa, preço de venda, margem, receita estimada, lucro estimado e quebra por tipo de componente.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão (precisa ser tipo_excursao=pacote_viagem)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "custo_unitario_total": 1820,
        "custo_fixo_total": 500,
        "custo_total_por_pessoa": 1845,
        "preco_venda": 2500,
        "margem_por_pessoa": 655,
        "margem_percentual": 26.2,
        "passageiros_ativos": 20,
        "receita_estimada": 50000,
        "custo_estimado": 36900,
        "lucro_estimado": 13100,
        "componentes_confirmados": 5,
        "componentes_total": 8
    }
}

Custeio da Viagem

Custos operacionais da excursão (ônibus, guia, hospedagem, pedágio, alimentação, ingressos), precificação com composição de valores (overhead, lucro, comissão, taxas), cenários por ocupação, ponto de equilíbrio e rentabilidade real. Espelha a aba **Custeio** da edição da viagem. Requer addon `gestao-financeira` (custos vivem em `fin_contas_pagar`).

Retorna TUDO em uma chamada: custos fixos e variáveis listados, totais agregados, custo por pax, capacidade, passageiros vendidos, receita real, configuração de precificação, cenários por ocupação, ponto de equilíbrio (break-even em pax), rentabilidade real e comissões por vendedor.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "custos_fixos": [],
        "custos_variaveis": [],
        "variacoes": [],
        "pax_por_variacao": [],
        "total_fixo": 5000,
        "total_variavel": 150,
        "custo_por_pax": 250,
        "capacidade": 40,
        "passageiros_vendidos": 28,
        "receita_real": 11200,
        "precificacao": {
            "overhead_percentual": 10,
            "lucro_desejado_percentual": 20
        },
        "preco_sugerido": 380,
        "break_even_pax": 18,
        "cenarios": [],
        "rentabilidade": {
            "margem_real": 30.5,
            "lucro_real": 3416
        },
        "comissoes": []
    }
}

Cria um custo da viagem (entra como `fin_conta_pagar` vinculada à excursão). `tipo_custo=fixo` é rateado entre todos os pax; `tipo_custo=variavel` é por pax (ou por variação se informar `excursao_variacao_id`).

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
fornecedor string Ex: Viação São Paulo, Hotel Madero
descricao string Descrição do custo
categoria_id integer ID de fin_categorias
valor * number Min 0.01
tipo_custo * string fixo (rateado entre pax) | variavel (por pax)
excursao_variacao_id integer Quando o custo variável aplica só a uma variação (ex: hospedagem camping vs alojamento)
data_vencimento string YYYY-MM-DD
forma_pagamento string dinheiro | pix | cartao_credito | cartao_debito | transferencia | boleto | cheque
observacao string
desconto_crianca number % de desconto pra criança (0-100)
desconto_idoso number % de desconto pra idoso (0-100)
desconto_bebe number % de desconto pra bebê (0-100)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Custo adicionado com sucesso!",
    "data": {
        "custo": {
            "id": 42
        }
    }
}

Atualizar custo

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
custoId * integer path ID do custo (FinContaPagar)

Corpo da requisição

Campo Tipo Descrição
valor * number
tipo_custo * string fixo | variavel
fornecedor string
descricao string
categoria_id integer
data_vencimento string
forma_pagamento string

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Custo atualizado com sucesso!"
}

Soft delete. Custo deixa de impactar nos totais.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
custoId * integer path ID do custo (FinContaPagar)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Custo removido com sucesso!"
}

Define `status=pago`, `valor_pago=valor`, `data_pagamento=now()`, `pago_por=usuário corrente`. Retorna 422 se já está pago.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
custoId * integer path ID do custo (FinContaPagar)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Custo marcado como pago!"
}

Volta para `pendente` (ou `vencido` se passou da data). Retorna 422 se não estava pago.

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
custoId * integer path ID do custo (FinContaPagar)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Pagamento revertido."
}

Define a **composição de valores** que entra no cálculo do preço sugerido: overhead, lucro desejado, comissão de vendedor, taxas financeiras, ocupação estimada e mix de meios de pagamento. Persiste em `excursao_precificacao` (1:1 com excursão).

Escopo necessário excursoes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
overhead_percentual number % de overhead (admin, marketing, infra)
lucro_desejado_percentual number % de lucro alvo
comissao_vendedor_percentual number % de comissão
comissao_base string bruto | liquido | preco_venda | custo
taxa_financeira_media number % médio das taxas de gateway
ocupacao_estimada integer % de ocupação alvo (1-100)
passageiros_estimados integer Nº absoluto de pax (alternativa a ocupacao_estimada)
mix_financeiro array Array de {percentual, taxa} por meio de pagamento
taxas_financeiras array Array de {percentual, taxa} alternativo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Precificação salva com sucesso!",
    "data": {
        "precificacao": {
            "preco_sugerido": 380
        }
    }
}

Calcula cenários (margem, lucro, break-even) para um `preco_venda` arbitrário SEM persistir. Se `preco_venda` for omitido, usa o `preco_sugerido` da precificação salva. Retorna 422 se nem o preço foi informado nem há precificação salva.

Escopo necessário excursoes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
preco_venda number Preço de venda a testar. Se omitido, usa o preco_sugerido salvo.

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "cenarios": [
            {
                "ocupacao_pct": 50,
                "pax": 20,
                "receita": 7600,
                "custo": 6000,
                "lucro": 1600,
                "margem_pct": 21
            },
            {
                "ocupacao_pct": 100,
                "pax": 40,
                "receita": 15200,
                "custo": 11000,
                "lucro": 4200,
                "margem_pct": 27.6
            }
        ],
        "break_even_pax": 18,
        "capacidade": 40,
        "preco_venda": 380
    }
}

Passageiros

Gerenciamento de passageiros individuais das excursões

Lista passageiros de uma excursão específica.

Escopo necessário passageiros:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
status string query pendente, confirmado, cancelado, embarcado
search string query Busca por nome ou CPF
per_page integer query Itens por página

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 1001,
            "excursao_id": 45,
            "cliente_id": 123,
            "comprador_id": 123,
            "preco_id": 77,
            "embarque_id": 12,
            "transporte_id": 9,
            "categoria_id": 1,
            "valor_cobrado": 1450,
            "status": "confirmado",
            "codigo_reserva": "VGABC12345",
            "qr_code": "550e8400-e29b-41d4-a716-446655440000",
            "assento": "A-10",
            "observacao": null,
            "cadastrado_via": "api",
            "cliente": {
                "id": 123,
                "nome": "Maria Silva Santos",
                "cpf": "12345678901",
                "telefone": "11999998888"
            },
            "preco": {
                "id": 77,
                "valor": 1450,
                "categoria_id": 1,
                "embarque_id": 12
            },
            "embarque": {
                "id": 12,
                "nome": "Terminal Tietê",
                "hora_embarque": "06:00"
            },
            "transporte": {
                "id": 9,
                "nome": "Ônibus 1",
                "tipo": "onibus_leito"
            },
            "categoria": {
                "id": 1,
                "nome": "Adulto"
            },
            "checkin_at": null,
            "created_at": "2024-01-20T11:30:00Z"
        }
    ],
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 45
    }
}

Retorna passageiro com cliente, preço, embarque, transporte.

Escopo necessário passageiros:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID do passageiro

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 1001,
        "excursao_id": 45,
        "cliente_id": 123,
        "comprador_id": 123,
        "preco_id": 77,
        "embarque_id": 12,
        "transporte_id": 9,
        "categoria_id": 1,
        "valor_cobrado": 1450,
        "status": "confirmado",
        "codigo_reserva": "VGABC12345",
        "qr_code": "550e8400-e29b-41d4-a716-446655440000",
        "assento": "A-10",
        "observacao": null,
        "cadastrado_via": "api",
        "cliente": {
            "id": 123,
            "nome": "Maria Silva Santos",
            "cpf": "12345678901",
            "telefone": "11999998888"
        },
        "preco": {
            "id": 77,
            "valor": 1450,
            "categoria_id": 1,
            "embarque_id": 12
        },
        "embarque": {
            "id": 12,
            "nome": "Terminal Tietê",
            "hora_embarque": "06:00"
        },
        "transporte": {
            "id": 9,
            "nome": "Ônibus 1",
            "tipo": "onibus_leito"
        },
        "categoria": {
            "id": 1,
            "nome": "Adulto"
        },
        "checkin_at": null,
        "created_at": "2024-01-20T11:30:00Z"
    }
}

Adiciona um passageiro (cliente novo ou existente). Para múltiplos passageiros em uma order, prefira POST /reservas.

Escopo necessário passageiros:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
cliente_id integer ID do cliente existente (ou enviar cliente inline)
cliente object Dados do cliente inline: {nome*, cpf, email, telefone}
preco_id * integer ID do preço escolhido
categoria_id integer ID da categoria (inferido do preço se omitido)
embarque_id integer ID do ponto de embarque (opcional para pacote sem transporte)
transporte_id integer ID do transporte (opcional para pacote sem transporte)
valor_cobrado number Valor específico (default = valor do preço)
assento string Identificador do assento (ex: A-10)
observacao string Observações
status string pendente (default), confirmado

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Passageiro adicionado com sucesso.",
    "data": {
        "id": 1001,
        "excursao_id": 45,
        "cliente_id": 123,
        "comprador_id": 123,
        "preco_id": 77,
        "embarque_id": 12,
        "transporte_id": 9,
        "categoria_id": 1,
        "valor_cobrado": 1450,
        "status": "confirmado",
        "codigo_reserva": "VGABC12345",
        "qr_code": "550e8400-e29b-41d4-a716-446655440000",
        "assento": "A-10",
        "observacao": null,
        "cadastrado_via": "api",
        "cliente": {
            "id": 123,
            "nome": "Maria Silva Santos",
            "cpf": "12345678901",
            "telefone": "11999998888"
        },
        "preco": {
            "id": 77,
            "valor": 1450,
            "categoria_id": 1,
            "embarque_id": 12
        },
        "embarque": {
            "id": 12,
            "nome": "Terminal Tietê",
            "hora_embarque": "06:00"
        },
        "transporte": {
            "id": 9,
            "nome": "Ônibus 1",
            "tipo": "onibus_leito"
        },
        "categoria": {
            "id": 1,
            "nome": "Adulto"
        },
        "checkin_at": null,
        "created_at": "2024-01-20T11:30:00Z"
    }
}

Atualiza um passageiro (dados, embarque, assento, status).

Escopo necessário passageiros:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID do passageiro

Corpo da requisição

Campo Tipo Descrição
embarque_id integer Trocar embarque
transporte_id integer Trocar transporte
assento string Novo assento
valor_cobrado number Ajustar valor
status string pendente, confirmado, cancelado, embarcado
observacao string Observações

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Passageiro atualizado.",
    "data": {
        "id": 1001,
        "excursao_id": 45,
        "cliente_id": 123,
        "comprador_id": 123,
        "preco_id": 77,
        "embarque_id": 12,
        "transporte_id": 9,
        "categoria_id": 1,
        "valor_cobrado": 1450,
        "status": "confirmado",
        "codigo_reserva": "VGABC12345",
        "qr_code": "550e8400-e29b-41d4-a716-446655440000",
        "assento": "A-10",
        "observacao": null,
        "cadastrado_via": "api",
        "cliente": {
            "id": 123,
            "nome": "Maria Silva Santos",
            "cpf": "12345678901",
            "telefone": "11999998888"
        },
        "preco": {
            "id": 77,
            "valor": 1450,
            "categoria_id": 1,
            "embarque_id": 12
        },
        "embarque": {
            "id": 12,
            "nome": "Terminal Tietê",
            "hora_embarque": "06:00"
        },
        "transporte": {
            "id": 9,
            "nome": "Ônibus 1",
            "tipo": "onibus_leito"
        },
        "categoria": {
            "id": 1,
            "nome": "Adulto"
        },
        "checkin_at": null,
        "created_at": "2024-01-20T11:30:00Z"
    }
}

Cancela (soft delete) o passageiro e libera a vaga.

Escopo necessário passageiros:delete

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID do passageiro

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Passageiro cancelado."
}

Marca passageiro como embarcado (checkin).

Escopo necessário checkin:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID do passageiro

Corpo da requisição

Campo Tipo Descrição
latitude number Latitude do ponto de check-in
longitude number Longitude
observacao string Observação

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Check-in realizado.",
    "data": {
        "id": 1001,
        "excursao_id": 45,
        "cliente_id": 123,
        "comprador_id": 123,
        "preco_id": 77,
        "embarque_id": 12,
        "transporte_id": 9,
        "categoria_id": 1,
        "valor_cobrado": 1450,
        "status": "confirmado",
        "codigo_reserva": "VGABC12345",
        "qr_code": "550e8400-e29b-41d4-a716-446655440000",
        "assento": "A-10",
        "observacao": null,
        "cadastrado_via": "api",
        "cliente": {
            "id": 123,
            "nome": "Maria Silva Santos",
            "cpf": "12345678901",
            "telefone": "11999998888"
        },
        "preco": {
            "id": 77,
            "valor": 1450,
            "categoria_id": 1,
            "embarque_id": 12
        },
        "embarque": {
            "id": 12,
            "nome": "Terminal Tietê",
            "hora_embarque": "06:00"
        },
        "transporte": {
            "id": 9,
            "nome": "Ônibus 1",
            "tipo": "onibus_leito"
        },
        "categoria": {
            "id": 1,
            "nome": "Adulto"
        },
        "checkin_at": null,
        "created_at": "2024-01-20T11:30:00Z"
    }
}

Retorna o cartão de embarque do passageiro. O parâmetro `format` define o formato: `pdf` (default, stream binário application/pdf), `base64` (JSON com PDF em base64) ou `link` (JSON com URL pública assinada via token). O parâmetro `grupo` aplica-se a TODOS os formatos: quando true (ou auto-detectado), retorna o cartão consolidado de todo o grupo (titular + dependentes), uma página por passageiro no PDF.

Escopo necessário passageiros:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
id * integer path ID do passageiro
format string query Formato de retorno: pdf | base64 | link (default: pdf)
grupo boolean query Se true, retorna o cartão de embarque do grupo todo (titular + dependentes). Default: auto — true quando o passageiro tem dependentes ativos, false para individual. Vale para todos os formatos (pdf/base64/link).

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "filename": "cartao-embarque-ABCD1234.pdf",
        "content_type": "application\/pdf",
        "content_base64": "JVBERi0xLjQK...",
        "size_bytes": 142536
    }
}

Clientes

Cadastro de clientes, dependentes e histórico de reservas

Lista paginada de clientes com filtros.

Escopo necessário clientes:read

Parâmetros

Nome Tipo Local Descrição
page integer query Página
per_page integer query Itens (max 100)
search string query Busca por nome, email, CPF, celular ou telefone. Termos com 5+ dígitos cruzam com CPF/celular/telefone normalizados.
email string query E-mail exato
cpf string query CPF (com ou sem formatação)
celular string query Celular/WhatsApp. Aceita com/sem DDI 55, com/sem 9, com/sem máscara. Compara últimos 10 dígitos.
whatsapp string query Alias de celular
telefone string query Filtra também pela coluna telefone (fixo). Mesma normalização.
ativo boolean query Filtrar por ativo/inativo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 123,
            "nome": "Maria Silva Santos",
            "email": "[email protected]",
            "cpf": "12345678901",
            "rg": "12.345.678-9",
            "passaporte": null,
            "nacionalidade": "Brasileira",
            "documento_estrangeiro": null,
            "documento_estrangeiro_tipo": null,
            "documento_estrangeiro_emissor": null,
            "documento_estrangeiro_emissao": null,
            "data_nascimento": "1985-03-15",
            "telefone": "1133334444",
            "celular": "11999998888",
            "instagram": "@maria.silva",
            "cep": "01310-100",
            "endereco": "Av. Paulista",
            "numero": "1000",
            "complemento": "Apto 52",
            "bairro": "Bela Vista",
            "cidade": "São Paulo",
            "estado": "SP",
            "contato_emergencia_nome": "João Silva",
            "contato_emergencia_parentesco": "Cônjuge",
            "contato_emergencia_telefone": "11988887777",
            "avatar_url": null,
            "observacoes": null,
            "ativo": true,
            "origem_cadastro": "api",
            "campos_personalizados": {
                "profissao": "Engenheiro",
                "tamanho_camiseta": "M"
            },
            "created_at": "2024-01-10T14:30:00Z",
            "updated_at": "2024-02-05T09:15:00Z"
        }
    ],
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 1250
    }
}

Busca exata por CPF (11 dígitos).

Escopo necessário clientes:read

Parâmetros

Nome Tipo Local Descrição
cpf * string query CPF (com ou sem formatação)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 123,
        "nome": "Maria Silva Santos",
        "email": "[email protected]",
        "cpf": "12345678901",
        "rg": "12.345.678-9",
        "passaporte": null,
        "nacionalidade": "Brasileira",
        "documento_estrangeiro": null,
        "documento_estrangeiro_tipo": null,
        "documento_estrangeiro_emissor": null,
        "documento_estrangeiro_emissao": null,
        "data_nascimento": "1985-03-15",
        "telefone": "1133334444",
        "celular": "11999998888",
        "instagram": "@maria.silva",
        "cep": "01310-100",
        "endereco": "Av. Paulista",
        "numero": "1000",
        "complemento": "Apto 52",
        "bairro": "Bela Vista",
        "cidade": "São Paulo",
        "estado": "SP",
        "contato_emergencia_nome": "João Silva",
        "contato_emergencia_parentesco": "Cônjuge",
        "contato_emergencia_telefone": "11988887777",
        "avatar_url": null,
        "observacoes": null,
        "ativo": true,
        "origem_cadastro": "api",
        "campos_personalizados": {
            "profissao": "Engenheiro",
            "tamanho_camiseta": "M"
        },
        "created_at": "2024-01-10T14:30:00Z",
        "updated_at": "2024-02-05T09:15:00Z"
    }
}

Busca cliente pelo telefone com normalização tolerante a formato (DDI 55, 9 mobile, máscara). Útil para chatbots identificarem cliente recorrente a partir do número do WhatsApp.

Escopo necessário clientes:read

Parâmetros

Nome Tipo Local Descrição
celular string query Aceita whatsapp= ou telefone= como alias. Ex: "85999281920", "(85) 99928-1920", "+5585999281920"
whatsapp string query Alias de celular
telefone string query Alias de celular

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 123,
        "nome": "Maria Silva Santos",
        "email": "[email protected]",
        "cpf": "12345678901",
        "rg": "12.345.678-9",
        "passaporte": null,
        "nacionalidade": "Brasileira",
        "documento_estrangeiro": null,
        "documento_estrangeiro_tipo": null,
        "documento_estrangeiro_emissor": null,
        "documento_estrangeiro_emissao": null,
        "data_nascimento": "1985-03-15",
        "telefone": "1133334444",
        "celular": "11999998888",
        "instagram": "@maria.silva",
        "cep": "01310-100",
        "endereco": "Av. Paulista",
        "numero": "1000",
        "complemento": "Apto 52",
        "bairro": "Bela Vista",
        "cidade": "São Paulo",
        "estado": "SP",
        "contato_emergencia_nome": "João Silva",
        "contato_emergencia_parentesco": "Cônjuge",
        "contato_emergencia_telefone": "11988887777",
        "avatar_url": null,
        "observacoes": null,
        "ativo": true,
        "origem_cadastro": "api",
        "campos_personalizados": {
            "profissao": "Engenheiro",
            "tamanho_camiseta": "M"
        },
        "created_at": "2024-01-10T14:30:00Z",
        "updated_at": "2024-02-05T09:15:00Z"
    }
}

Retorna o cliente. Use include_dependentes=true para trazer os dependentes.

Escopo necessário clientes:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do cliente
include_dependentes boolean query Se true, inclui array dependentes na resposta

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 123,
        "nome": "Maria Silva Santos",
        "email": "[email protected]",
        "cpf": "12345678901",
        "rg": "12.345.678-9",
        "passaporte": null,
        "nacionalidade": "Brasileira",
        "documento_estrangeiro": null,
        "documento_estrangeiro_tipo": null,
        "documento_estrangeiro_emissor": null,
        "documento_estrangeiro_emissao": null,
        "data_nascimento": "1985-03-15",
        "telefone": "1133334444",
        "celular": "11999998888",
        "instagram": "@maria.silva",
        "cep": "01310-100",
        "endereco": "Av. Paulista",
        "numero": "1000",
        "complemento": "Apto 52",
        "bairro": "Bela Vista",
        "cidade": "São Paulo",
        "estado": "SP",
        "contato_emergencia_nome": "João Silva",
        "contato_emergencia_parentesco": "Cônjuge",
        "contato_emergencia_telefone": "11988887777",
        "avatar_url": null,
        "observacoes": null,
        "ativo": true,
        "origem_cadastro": "api",
        "campos_personalizados": {
            "profissao": "Engenheiro",
            "tamanho_camiseta": "M"
        },
        "created_at": "2024-01-10T14:30:00Z",
        "updated_at": "2024-02-05T09:15:00Z",
        "dependentes": []
    }
}

Lista paginada dos pedidos (Orders) onde o cliente é comprador. Retorna o pedido completo com codigo, valor_total, status e passageiros aninhados (incluindo vagas pendentes com cadastrado_via=convite_pendente).

Escopo necessário clientes:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do cliente
status string query Filtro CSV (ex: "pendente,confirmado")
excursao_id integer query Pedidos contendo passageiros desta excursão
updated_since datetime query Modificados a partir de (ISO 8601). Sync incremental.
per_page integer query Itens (max 100)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 501,
            "codigo": "VG-ABC12345",
            "valor_total": 2900,
            "valor_pago": 0,
            "valor_pendente": 2900,
            "status": "pendente",
            "passageiros": [
                {
                    "id": 1001,
                    "nome": "Maria Silva",
                    "cadastrado_via": "api",
                    "valor_cobrado": 1450
                },
                {
                    "id": 1002,
                    "nome": "Vaga 2",
                    "cadastrado_via": "convite_pendente",
                    "valor_cobrado": 1450
                }
            ]
        }
    ],
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 5
    }
}

Cria um cliente. origem_cadastro é gravado automaticamente como "api". Valida unicidade de CPF e email (retorna 409 em duplicata). A resposta inclui um auto_login_url (magic link de 30 min, one-time use) pronto para redirecionar o cliente já logado no portal.

Escopo necessário clientes:write

Corpo da requisição

Campo Tipo Descrição
nome * string Nome completo (required em POST)
email string E-mail (único)
cpf string CPF (apenas dígitos ou formatado, será normalizado)
rg string RG
passaporte string Número do passaporte
nacionalidade string Nacionalidade
documento_estrangeiro string Documento estrangeiro (para não-brasileiros)
documento_estrangeiro_tipo string Tipo do documento estrangeiro
documento_estrangeiro_emissor string Órgão emissor
documento_estrangeiro_emissao date Data de emissão (Y-m-d)
data_nascimento date Data de nascimento (Y-m-d)
telefone string Telefone fixo
celular string Celular/WhatsApp
instagram string @usuario do Instagram
cep string CEP
endereco string Logradouro
numero string Número
complemento string Complemento
bairro string Bairro
cidade string Cidade
estado string UF (2 letras)
contato_emergencia_nome string Nome do contato de emergência
contato_emergencia_parentesco string Parentesco do contato
contato_emergencia_telefone string Telefone do contato
avatar_url string URL da foto
ativo boolean Cliente ativo (default true)
observacoes string Observações livres
campos_personalizados object Campos personalizados de cliente. Objeto { field_key: valor }. Os field_keys variam por empresa (veja os campos ativos em Configurações > Formulários > Clientes). Em campos de seleção aceita o value da opção OU o rótulo (mapeado para o value); multi-seleção por lista separada por vírgula. field_key inexistente ou valor de seleção inválido retornam 422 com as opções válidas.

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Cliente criado com sucesso.",
    "data": {
        "id": 123,
        "nome": "Maria Silva Santos",
        "email": "[email protected]",
        "cpf": "12345678901",
        "rg": "12.345.678-9",
        "passaporte": null,
        "nacionalidade": "Brasileira",
        "documento_estrangeiro": null,
        "documento_estrangeiro_tipo": null,
        "documento_estrangeiro_emissor": null,
        "documento_estrangeiro_emissao": null,
        "data_nascimento": "1985-03-15",
        "telefone": "1133334444",
        "celular": "11999998888",
        "instagram": "@maria.silva",
        "cep": "01310-100",
        "endereco": "Av. Paulista",
        "numero": "1000",
        "complemento": "Apto 52",
        "bairro": "Bela Vista",
        "cidade": "São Paulo",
        "estado": "SP",
        "contato_emergencia_nome": "João Silva",
        "contato_emergencia_parentesco": "Cônjuge",
        "contato_emergencia_telefone": "11988887777",
        "avatar_url": null,
        "observacoes": null,
        "ativo": true,
        "origem_cadastro": "api",
        "campos_personalizados": {
            "profissao": "Engenheiro",
            "tamanho_camiseta": "M"
        },
        "created_at": "2024-01-10T14:30:00Z",
        "updated_at": "2024-02-05T09:15:00Z",
        "auto_login_url": "https:\/\/seu-tenant.viagilize.com.br\/auth\/magic\/abc123...",
        "auto_login_expires_at": "2026-04-21T22:15:00+00:00",
        "auto_login_single_use": true
    }
}

Atualiza parcialmente um cliente. Todos os campos são opcionais.

Escopo necessário clientes:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do cliente

Corpo da requisição

Campo Tipo Descrição
nome string Nome completo (required em POST)
email string E-mail (único)
cpf string CPF (apenas dígitos ou formatado, será normalizado)
rg string RG
passaporte string Número do passaporte
nacionalidade string Nacionalidade
documento_estrangeiro string Documento estrangeiro (para não-brasileiros)
documento_estrangeiro_tipo string Tipo do documento estrangeiro
documento_estrangeiro_emissor string Órgão emissor
documento_estrangeiro_emissao date Data de emissão (Y-m-d)
data_nascimento date Data de nascimento (Y-m-d)
telefone string Telefone fixo
celular string Celular/WhatsApp
instagram string @usuario do Instagram
cep string CEP
endereco string Logradouro
numero string Número
complemento string Complemento
bairro string Bairro
cidade string Cidade
estado string UF (2 letras)
contato_emergencia_nome string Nome do contato de emergência
contato_emergencia_parentesco string Parentesco do contato
contato_emergencia_telefone string Telefone do contato
avatar_url string URL da foto
ativo boolean Cliente ativo (default true)
observacoes string Observações livres
campos_personalizados object Campos personalizados de cliente. Objeto { field_key: valor }. Os field_keys variam por empresa (veja os campos ativos em Configurações > Formulários > Clientes). Em campos de seleção aceita o value da opção OU o rótulo (mapeado para o value); multi-seleção por lista separada por vírgula. field_key inexistente ou valor de seleção inválido retornam 422 com as opções válidas.

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Cliente atualizado com sucesso.",
    "data": {
        "id": 123,
        "nome": "Maria Silva Santos",
        "email": "[email protected]",
        "cpf": "12345678901",
        "rg": "12.345.678-9",
        "passaporte": null,
        "nacionalidade": "Brasileira",
        "documento_estrangeiro": null,
        "documento_estrangeiro_tipo": null,
        "documento_estrangeiro_emissor": null,
        "documento_estrangeiro_emissao": null,
        "data_nascimento": "1985-03-15",
        "telefone": "1133334444",
        "celular": "11999998888",
        "instagram": "@maria.silva",
        "cep": "01310-100",
        "endereco": "Av. Paulista",
        "numero": "1000",
        "complemento": "Apto 52",
        "bairro": "Bela Vista",
        "cidade": "São Paulo",
        "estado": "SP",
        "contato_emergencia_nome": "João Silva",
        "contato_emergencia_parentesco": "Cônjuge",
        "contato_emergencia_telefone": "11988887777",
        "avatar_url": null,
        "observacoes": null,
        "ativo": true,
        "origem_cadastro": "api",
        "campos_personalizados": {
            "profissao": "Engenheiro",
            "tamanho_camiseta": "M"
        },
        "created_at": "2024-01-10T14:30:00Z",
        "updated_at": "2024-02-05T09:15:00Z"
    }
}

Remove o cliente (soft delete).

Escopo necessário clientes:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Cliente excluído com sucesso."
}

Gera um novo token de auto-login para um cliente existente. O token é válido por 30 minutos, one-time use (invalida após primeiro clique) e invalida qualquer token anterior. Use para SSO: parceiro envia o URL por WhatsApp/email e o cliente cai já logado em /minha-conta.

Escopo necessário clientes:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do cliente

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Link de login automático gerado.",
    "data": {
        "cliente_id": 86,
        "auto_login_url": "https:\/\/seu-tenant.viagilize.com.br\/auth\/magic\/abc123...",
        "auto_login_expires_at": "2026-04-21T22:15:00+00:00",
        "auto_login_single_use": true
    }
}

Invalida o token atual do cliente (equivalente a "logout forçado" dos links pendentes). Use em caso de token comprometido.

Escopo necessário clientes:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do cliente

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Token de auto-login revogado."
}

Lista os dependentes (filhos, cônjuges, etc) do cliente.

Escopo necessário clientes:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do cliente

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 301,
            "cliente_id": 123,
            "nome": "Lucas Silva",
            "cpf": "98765432100",
            "data_nascimento": "2012-06-20",
            "parentesco": "filho",
            "created_at": "2024-03-12T10:00:00Z"
        }
    ]
}

Cria um dependente vinculado ao cliente.

Escopo necessário clientes:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do cliente

Corpo da requisição

Campo Tipo Descrição
nome * string Nome completo
cpf string CPF
rg string RG
passaporte string Passaporte
nacionalidade string Nacionalidade
documento_estrangeiro string Documento estrangeiro
documento_estrangeiro_tipo string Tipo
documento_estrangeiro_emissor string Emissor
documento_estrangeiro_emissao date Emissão
data_nascimento date Nascimento
parentesco string filho, cônjuge, pai, mãe...
telefone string Telefone
email string E-mail
observacoes string Observações

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Dependente criado com sucesso.",
    "data": {
        "id": 301,
        "cliente_id": 123,
        "nome": "Lucas Silva",
        "parentesco": "filho"
    }
}

Atualiza um dependente. Todos os campos são opcionais.

Escopo necessário clientes:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do cliente
dependenteId * integer path ID do dependente

Corpo da requisição

Campo Tipo Descrição
nome string Nome completo
cpf string CPF
rg string RG
passaporte string Passaporte
nacionalidade string Nacionalidade
documento_estrangeiro string Documento estrangeiro
documento_estrangeiro_tipo string Tipo
documento_estrangeiro_emissor string Emissor
documento_estrangeiro_emissao date Emissão
data_nascimento date Nascimento
parentesco string filho, cônjuge, pai, mãe...
telefone string Telefone
email string E-mail
observacoes string Observações

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Dependente atualizado com sucesso.",
    "data": {
        "id": 301,
        "nome": "Lucas Silva Atualizado"
    }
}

Remove o dependente.

Escopo necessário clientes:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do cliente
dependenteId * integer path ID do dependente

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Dependente excluído com sucesso."
}

Reservas

Orders de reservas com geração de link de pagamento

Lista paginada de orders/reservas com filtros.

Escopo necessário reservas:read

Parâmetros

Nome Tipo Local Descrição
page integer query Página
per_page integer query Itens (max 100)
status string query pendente, parcial, pago, cancelado, reembolsado
cliente_id integer query Filtrar por comprador
excursao_id integer query Filtrar por excursão
data_de date query Criadas a partir de (Y-m-d)
data_ate date query Criadas até (Y-m-d)
updated_since datetime query Modificadas a partir de (ISO 8601). Útil para sync incremental.
search string query Busca por código da order, nome ou email do comprador

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 501,
            "codigo": "VG-ABC12345",
            "comprador_id": 123,
            "status": "pendente",
            "valor_original": 2900,
            "valor_total": 2900,
            "valor_pago": 0,
            "valor_pendente": 2900,
            "pagamento_expira_em": "2026-04-26T18:30:42-03:00",
            "forma_pagamento": "pix",
            "parcelas": 1,
            "origem": "api",
            "gateway_preference_id": null,
            "comprador": {
                "id": 123,
                "nome": "Maria Silva Santos",
                "email": "[email protected]",
                "cpf": "12345678901"
            },
            "passageiros": [
                {
                    "id": 1001,
                    "excursao_id": 45,
                    "cliente_id": 123,
                    "preco_id": 77,
                    "embarque_id": 12,
                    "transporte_id": 9,
                    "categoria_id": 1,
                    "valor_cobrado": 1450,
                    "status": "pendente",
                    "codigo_reserva": "VGABC12345",
                    "qr_code": "550e8400-e29b-41d4-a716-446655440000",
                    "excursao": {
                        "id": 45,
                        "nome": "Gramado - Natal Luz 2025"
                    }
                },
                {
                    "id": 1002,
                    "excursao_id": 45,
                    "cliente_id": 124,
                    "preco_id": 77,
                    "valor_cobrado": 1450,
                    "status": "pendente",
                    "codigo_reserva": "VGDEF67890"
                }
            ],
            "payments": [],
            "created_at": "2024-10-15T11:30:00Z"
        }
    ],
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 32
    }
}

Reserva completa com passageiros, preços, embarques, transportes, pagamentos e financeiro. Inclui também `total_pendentes` (vagas aguardando preenchimento), `passageiros_completos` e `passageiros_total` — use pra decidir liberação de cartão de embarque sem precisar chamar /passageiros-pendentes.

Escopo necessário reservas:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da reserva (order)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 501,
        "codigo": "VG-ABC12345",
        "comprador_id": 123,
        "status": "pendente",
        "valor_original": 2900,
        "valor_total": 2900,
        "valor_pago": 0,
        "valor_pendente": 2900,
        "pagamento_expira_em": "2026-04-26T18:30:42-03:00",
        "forma_pagamento": "pix",
        "parcelas": 1,
        "origem": "api",
        "gateway_preference_id": null,
        "comprador": {
            "id": 123,
            "nome": "Maria Silva Santos",
            "email": "[email protected]",
            "cpf": "12345678901"
        },
        "passageiros": [
            {
                "id": 1001,
                "excursao_id": 45,
                "cliente_id": 123,
                "preco_id": 77,
                "embarque_id": 12,
                "transporte_id": 9,
                "categoria_id": 1,
                "valor_cobrado": 1450,
                "status": "pendente",
                "codigo_reserva": "VGABC12345",
                "qr_code": "550e8400-e29b-41d4-a716-446655440000",
                "excursao": {
                    "id": 45,
                    "nome": "Gramado - Natal Luz 2025"
                }
            },
            {
                "id": 1002,
                "excursao_id": 45,
                "cliente_id": 124,
                "preco_id": 77,
                "valor_cobrado": 1450,
                "status": "pendente",
                "codigo_reserva": "VGDEF67890"
            }
        ],
        "payments": [],
        "created_at": "2024-10-15T11:30:00Z",
        "total_pendentes": 0,
        "passageiros_completos": 3,
        "passageiros_total": 3
    }
}

Cria uma order com um ou mais passageiros em transação. Aceita cliente_id existente ou objeto cliente inline (auto-cria por CPF/email). Se gerar_link_pagamento=true, retorna também `payment_url` do gateway ativo. Se a geração falhar (sem gateway, excursão sem preço, etc), a reserva ainda é criada e a resposta inclui `payment_link_error: { code, message }` em vez de `payment_url`.

Escopo necessário reservas:write

Corpo da requisição

Campo Tipo Descrição
excursao_id * integer ID da excursão/pacote
cliente_id integer ID do comprador (ou enviar cliente inline)
cliente object Dados do comprador inline: {nome*, email, cpf, telefone, celular, cep, endereco, numero, bairro, cidade, estado, forcar_novo?}. Dedupe LGPD: CPF first, e-mail só reusa se cliente existente nao tiver CPF. Use forcar_novo=true para pular dedupe.
passageiros * array Lista (1-20): {cliente_id|cliente|pendente, preco_id*, categoria_id?, embarque_id?, transporte_id?, valor_cobrado?, observacao?}. Use pendente:true (sem cliente_id/cliente) pra criar vaga aguardando dados — o comprador preenche depois (portal /minha-conta/convites, API POST .../preencher, ou link público de convite retornado).
forma_pagamento string pix, cartao, boleto, dinheiro, transferencia
parcelas integer Número de parcelas (1-24)
observacoes string Observações livres
gerar_link_pagamento boolean Se true, retorna payment_url junto

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Reserva criada com sucesso.",
    "data": {
        "id": 501,
        "codigo": "VG-ABC12345",
        "comprador_id": 123,
        "status": "pendente",
        "valor_original": 2900,
        "valor_total": 2900,
        "valor_pago": 0,
        "valor_pendente": 2900,
        "pagamento_expira_em": "2026-04-26T18:30:42-03:00",
        "forma_pagamento": "pix",
        "parcelas": 1,
        "origem": "api",
        "gateway_preference_id": null,
        "comprador": {
            "id": 123,
            "nome": "Maria Silva Santos",
            "email": "[email protected]",
            "cpf": "12345678901"
        },
        "passageiros": [
            {
                "id": 1001,
                "excursao_id": 45,
                "cliente_id": 123,
                "preco_id": 77,
                "embarque_id": 12,
                "transporte_id": 9,
                "categoria_id": 1,
                "valor_cobrado": 1450,
                "status": "pendente",
                "codigo_reserva": "VGABC12345",
                "qr_code": "550e8400-e29b-41d4-a716-446655440000",
                "excursao": {
                    "id": 45,
                    "nome": "Gramado - Natal Luz 2025"
                }
            },
            {
                "id": 1002,
                "excursao_id": 45,
                "cliente_id": 124,
                "preco_id": 77,
                "valor_cobrado": 1450,
                "status": "pendente",
                "codigo_reserva": "VGDEF67890"
            }
        ],
        "payments": [],
        "created_at": "2024-10-15T11:30:00Z",
        "payment_url": "https:\/\/mpago.la\/abc123",
        "payment_gateway": "Mercado Pago"
    }
}

Gera uma URL de pagamento no gateway ativo do tenant (Mercado Pago, Asaas, Pagar.me, Infinite Pay, PagSeguro, ValePay). Requer que o tenant tenha ao menos um gateway configurado e habilitado.

Escopo necessário reservas:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da reserva

Corpo da requisição

Campo Tipo Descrição
valor number Valor a cobrar (default = valor_pendente da reserva)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "url": "https:\/\/mpago.la\/abc123",
        "gateway": "Mercado Pago",
        "valor": 2900,
        "order_id": 501
    }
}

Registra um pagamento manual (dinheiro, transferência, PIX confirmado fora do gateway, etc). Cria OrderPayment, propaga para o financeiro de cada passageiro proporcionalmente ao valor cobrado, confirma passageiros automaticamente se o valor total for atingido e envia e-mail de confirmação.

Escopo necessário reservas:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da reserva

Corpo da requisição

Campo Tipo Descrição
valor * number Valor pago (não pode exceder valor_pendente)
forma_pagamento * string pix, cartao, boleto, dinheiro, transferencia, cheque
gateway string Nome do gateway se aplicável (mercadopago, asaas, pagarme, infinitipay...)
gateway_payment_id string ID externo do pagamento no gateway
observacao string Observação livre

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Pagamento registrado com sucesso.",
    "data": {
        "payment": {
            "id": 42,
            "order_id": 501,
            "valor": 1450,
            "forma_pagamento": "pix",
            "status": "aprovado",
            "pago_em": "2024-10-25T10:15:00Z"
        },
        "order": {
            "id": 501,
            "codigo": "VG-ABC12345",
            "valor_total": 2900,
            "valor_pago": 1450,
            "valor_pendente": 1450,
            "status": "parcial"
        }
    }
}

Cancela a reserva e todos os passageiros associados. Dispara webhook reserva.cancelada.

Escopo necessário reservas:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da reserva

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Reserva cancelada.",
    "data": {
        "id": 501,
        "status": "cancelado"
    }
}

Gera URL única (válida 30 minutos, single-use) que loga o comprador e redireciona para a página da reserva no portal cliente. Útil para enviar via WhatsApp/email pós-pagamento e pedir que o cliente complete documentos/contrato.

Escopo necessário reservas:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da reserva

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Magic link da reserva gerado.",
    "data": {
        "reserva_id": 501,
        "codigo": "VG-ABC12345",
        "cliente_id": 123,
        "magic_link_url": "https:\/\/tenant.viagilize.com.br\/auth\/magic\/abc123def456?redirect=%2Fminha-conta%2Freservas%2FVG-ABC12345",
        "expires_at": "2026-04-25T22:00:00-03:00",
        "single_use": true
    }
}

Retorna o status do aceite eletrônico do contrato por passageiro da reserva. Inclui referência ao SignatureAgreement ativo (se houver). O fluxo recomendado é: pagar primeiro (via payment-link) → gerar magic-link → cliente assina pelo portal.

Escopo necessário reservas:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da reserva

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "reserva_id": 501,
        "codigo": "VG-ABC12345",
        "exige_contrato": true,
        "passageiros": [
            {
                "passageiro_id": 1001,
                "codigo_reserva": "VGABC12345",
                "cliente_id": 123,
                "nome": "Maria Silva Santos",
                "aceite_status": false,
                "aceite_data": null,
                "aceite_ip": null,
                "agreement": {
                    "id": 891,
                    "status": "pending",
                    "created_at": "2026-04-25T19:15:00-03:00",
                    "signed_at": null
                }
            }
        ],
        "fluxo": "O aceite acontece pelo portal do cliente apos o pagamento, via magic link em \/minha-conta\/excursao\/{id}\/contrato. Use POST \/reservas\/{id}\/magic-link para gerar."
    }
}

Lista as vagas pendentes (passageiros placeholder aguardando preenchimento). Cada vaga retorna o link_convite — URL pública do formulário que pode ser copiada e enviada via WhatsApp/email para o convidado preencher, ou usada pelo comprador no portal. **Auto-renovação:** se o token de uma vaga ainda pendente estiver expirado/usado, este endpoint regenera automaticamente um token novo (24h de validade) antes de retornar. Não é necessário chamar o endpoint dedicado de reenviar-convite — basta consultar este GET periodicamente.

Escopo necessário reservas:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da reserva

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "reserva_id": 501,
        "codigo": "VG-ABC12345",
        "total_pendentes": 2,
        "vagas_pendentes": [
            {
                "pendente_id": 10,
                "posicao": 2,
                "valor": 1450,
                "status": "pendente",
                "preco_id": 77,
                "transporte_id": 9,
                "transporte_nome": "Ônibus 01",
                "embarque_id": 12,
                "embarque_nome": "Terminal Tietê",
                "expira_em": "2026-05-26T18:30:42-03:00",
                "link_convite": "https:\/\/tenant.viagilize.com.br\/convite\/abc123def456...",
                "created_at": "2026-05-19T10:00:00-03:00"
            }
        ]
    }
}

Preenche os dados de uma vaga pendente em nome do comprador. Atualiza o ExcursaoPassageiro placeholder com os dados reais. Aceita 1 de 3 formas: (a) cliente_id de cliente existente, (b) dependente_id do comprador, ou (c) dados crus (nome+cpf+...) que cria/reusa cliente por CPF (LGPD).

Escopo necessário reservas:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da reserva
pendenteId * integer path ID da vaga pendente

Corpo da requisição

Campo Tipo Descrição
cliente_id integer Forma A: usa cliente já cadastrado
dependente_id integer Forma B: usa dependente do comprador
nome string Forma C (com cpf): cria/reusa cliente
cpf string Forma C (com nome): aceita com/sem formatação
rg string RG do passageiro (opcional)
telefone string Telefone/celular do passageiro (opcional)
email string E-mail do passageiro (opcional)
data_nascimento date Data de nascimento (YYYY-MM-DD, opcional)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Vaga preenchida com sucesso.",
    "data": {
        "passageiro": {
            "id": 1002,
            "nome": "João Silva",
            "cpf": "12345678901",
            "cliente_id": 245,
            "cadastrado_via": "preenchido_comprador"
        },
        "pendente_id": 10
    }
}

Invalida o token atual e gera um novo (validade padrão 24h). Use para recuperar vaga com link_convite expirado. Não dispara envio por canal — quem decide se reencaminha por WhatsApp/email é o integrador.

Escopo necessário reservas:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da reserva
pendenteId * integer path ID da vaga pendente

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Convite regenerado.",
    "data": {
        "pendente_id": 10,
        "link_convite": "https:\/\/tenant.viagilize.com.br\/convite\/abc123token",
        "expira_em": "2026-05-20T13:00:00-03:00"
    }
}

Cancela uma vaga pendente não preenchida. O valor da vaga é subtraído de valor_total/valor_pendente do pedido. Token de convite associado é invalidado.

Escopo necessário reservas:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da reserva
pendenteId * integer path ID da vaga pendente

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Vaga pendente cancelada."
}

Remove permanentemente uma reserva e todos os passageiros, financeiros, pagamentos e vagas pendentes vinculados. Só funciona com status=cancelado — use POST /reservas/{id}/cancel primeiro para reservas ativas.

Escopo necessário reservas:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da reserva

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Reserva removida permanentemente.",
    "data": {
        "codigo": "A8CA1475"
    }
}

Lista de Espera

Fila de espera por excursão. Quando uma vaga abre, o sistema notifica o primeiro da fila com janela de oferta limitada.

Lista paginada das entradas em lista de espera, com filtros.

Escopo necessário reservas:read

Parâmetros

Nome Tipo Local Descrição
page integer query Página
per_page integer query Itens (max 100)
excursao_id integer query Filtrar por excursão
status string query aguardando, notificado, expirado, cancelado, convertido
cliente_id integer query Filtrar por cliente

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 17,
            "excursao_id": 45,
            "cliente_id": 123,
            "nome": "Maria Silva Santos",
            "email": "[email protected]",
            "celular": "85988887777",
            "cpf": "12345678901",
            "quantidade": 2,
            "observacoes": "Aceita troca de embarque se houver",
            "posicao": 3,
            "status": "aguardando",
            "origem": "api",
            "created_at": "2026-04-25T15:00:00-03:00"
        }
    ],
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 7
    }
}

Retorna a entrada com cliente e excursão carregados.

Escopo necessário reservas:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da entrada

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 17,
        "excursao_id": 45,
        "cliente_id": 123,
        "nome": "Maria Silva Santos",
        "email": "[email protected]",
        "celular": "85988887777",
        "cpf": "12345678901",
        "quantidade": 2,
        "observacoes": "Aceita troca de embarque se houver",
        "posicao": 3,
        "status": "aguardando",
        "origem": "api",
        "created_at": "2026-04-25T15:00:00-03:00"
    }
}

Adiciona uma pessoa na fila. Posição é calculada automaticamente (ultima da fila para essa excursão).

Escopo necessário reservas:write

Corpo da requisição

Campo Tipo Descrição
excursao_id * integer ID da excursão
cliente_id integer ID de cliente existente (alternativa a passar nome/email/celular)
nome string Obrigatorio se cliente_id nao for informado
email string Email para notificacao quando vaga abrir
celular string Celular para notificacao via WhatsApp
cpf string CPF (opcional)
quantidade integer Quantas vagas reservar (1-20, default 1)
observacoes string Observacoes livres

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Entrada criada na lista de espera.",
    "data": {
        "id": 17,
        "excursao_id": 45,
        "cliente_id": 123,
        "nome": "Maria Silva Santos",
        "email": "[email protected]",
        "celular": "85988887777",
        "cpf": "12345678901",
        "quantidade": 2,
        "observacoes": "Aceita troca de embarque se houver",
        "posicao": 3,
        "status": "aguardando",
        "origem": "api",
        "created_at": "2026-04-25T15:00:00-03:00"
    }
}

Marca a entrada como cancelada. Posicoes seguintes nao sao reordenadas automaticamente.

Escopo necessário reservas:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da entrada

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Entrada removida da lista de espera."
}

Financeiro

Pagamentos e dados financeiros dos passageiros

Resumo financeiro: valor total, pago, pendente, status.

Escopo necessário financeiro:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
passageiroId * integer path ID do passageiro

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 301,
        "passageiro_id": 1001,
        "valor_original": 1450,
        "valor_desconto": 0,
        "valor_total": 1450,
        "valor_pago": 725,
        "valor_pendente": 725,
        "percentual_pago": 50,
        "forma_pagamento": "pix",
        "parcelas": 2,
        "status": "parcial",
        "ultimo_pagamento_em": "2024-10-20T14:22:00Z"
    }
}

Lista todos os pagamentos registrados para um passageiro.

Escopo necessário financeiro:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
passageiroId * integer path ID do passageiro

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 501,
            "passageiro_id": 1001,
            "valor": 725,
            "forma": "pix",
            "gateway": "mercado_pago",
            "gateway_payment_id": "mp_12345",
            "data_pagamento": "2024-10-20",
            "observacao": null,
            "created_at": "2024-10-20T14:22:00Z"
        }
    ]
}

Registra um pagamento manual (ex: recebido em dinheiro, transferência). Atualiza valor_pago do passageiro/order.

Escopo necessário financeiro:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
passageiroId * integer path ID do passageiro

Corpo da requisição

Campo Tipo Descrição
valor * number Valor pago (>= 0.01)
forma * string pix, cartao, boleto, dinheiro, transferencia, cheque
data_pagamento date Data do pagamento (default: hoje)
observacao string Observações

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Pagamento registrado.",
    "data": {
        "id": 502,
        "valor": 725,
        "forma": "pix",
        "data_pagamento": "2024-10-25"
    }
}

Agrega valores de todos os passageiros da excursão.

Escopo necessário financeiro:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "totais": {
            "passageiros": 45,
            "com_financeiro": 45,
            "valor_total": 65250,
            "valor_pago": 32625,
            "valor_pendente": 32625,
            "percentual_pago": 50
        },
        "por_status": {
            "pendente": 10,
            "parcial": 25,
            "pago": 10,
            "cancelado": 0,
            "reembolsado": 0
        }
    }
}

Cupons

Cupons de desconto: CRUD, validação e aplicação em reservas.

Lista paginada de cupons com filtros opcionais.

Escopo necessário cupons:read

Parâmetros

Nome Tipo Local Descrição
search string query Busca por código ou nome
ativo boolean query Filtra por status ativo
tipo string query publico | unico | cliente | primeira_compra | indicacao
apenas_principais boolean query Se true, omite cupons filhos de lotes
per_page integer query Itens por página (default 50, máx 100)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 42,
            "codigo": "VERAO50",
            "nome": "Promoção Verão 2026",
            "descricao": "Desconto de 15% nas excursões de janeiro e fevereiro",
            "tipo": "publico",
            "tipo_label": "Público",
            "tipo_desconto": "percentual",
            "tipo_desconto_label": "Percentual",
            "valor_desconto": 15,
            "desconto_formatado": "15%",
            "valor_maximo_desconto": 300,
            "valor_minimo_pedido": 500,
            "limite_uso_total": 100,
            "limite_uso_por_cliente": 1,
            "usos": 27,
            "usos_disponiveis": 73,
            "usos_progresso": "27\/100",
            "data_inicio": "2026-01-01T00:00:00Z",
            "data_expiracao": "2026-02-28T23:59:59Z",
            "excursoes_permitidas": null,
            "excursoes_excluidas": null,
            "categorias_permitidas": null,
            "apenas_primeira_compra": false,
            "clientes_permitidos": null,
            "clientes_bloqueados": null,
            "cupom_pai_id": null,
            "lote_nome": null,
            "is_lote": false,
            "is_filho_lote": false,
            "ativo": true,
            "status": "Ativo",
            "status_color": "green",
            "valido": true,
            "created_at": "2025-12-15T10:00:00Z",
            "updated_at": "2026-01-10T14:30:00Z"
        }
    ]
}

Retorna todos os campos do cupom + contagem de usos e status calculado.

Escopo necessário cupons:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do cupom

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 42,
        "codigo": "VERAO50",
        "nome": "Promoção Verão 2026",
        "descricao": "Desconto de 15% nas excursões de janeiro e fevereiro",
        "tipo": "publico",
        "tipo_label": "Público",
        "tipo_desconto": "percentual",
        "tipo_desconto_label": "Percentual",
        "valor_desconto": 15,
        "desconto_formatado": "15%",
        "valor_maximo_desconto": 300,
        "valor_minimo_pedido": 500,
        "limite_uso_total": 100,
        "limite_uso_por_cliente": 1,
        "usos": 27,
        "usos_disponiveis": 73,
        "usos_progresso": "27\/100",
        "data_inicio": "2026-01-01T00:00:00Z",
        "data_expiracao": "2026-02-28T23:59:59Z",
        "excursoes_permitidas": null,
        "excursoes_excluidas": null,
        "categorias_permitidas": null,
        "apenas_primeira_compra": false,
        "clientes_permitidos": null,
        "clientes_bloqueados": null,
        "cupom_pai_id": null,
        "lote_nome": null,
        "is_lote": false,
        "is_filho_lote": false,
        "ativo": true,
        "status": "Ativo",
        "status_color": "green",
        "valido": true,
        "created_at": "2025-12-15T10:00:00Z",
        "updated_at": "2026-01-10T14:30:00Z"
    }
}

Cria um novo cupom de desconto. O código é normalizado para uppercase. Retorna 409 se já existir.

Escopo necessário cupons:write

Corpo da requisição

Campo Tipo Descrição
codigo * string Código que o cliente digita no checkout (case-insensitive, hífens/espaços ignorados). Ex: VERAO50
nome * string Nome interno do cupom (visível no admin)
descricao string Descrição opcional
tipo * string publico | unico | cliente | primeira_compra | indicacao
tipo_desconto * string percentual | valor_fixo | valor_por_passageiro | frete_gratis
valor_desconto number Valor do desconto. Em percentual: 0-100. Em valor_fixo: R$. Em valor_por_passageiro: R$ por pax
valor_maximo_desconto number Teto do desconto em R$ (útil para percentuais)
limite_uso_total integer Quantas vezes o cupom pode ser usado no total (null = ilimitado)
limite_uso_por_cliente integer Quantas vezes cada cliente pode usar (null = ilimitado)
valor_minimo_pedido number Valor mínimo do pedido para o cupom valer
data_inicio string Início da vigência (ISO 8601). null = vale desde já
data_expiracao string Fim da vigência (ISO 8601). null = sem expiração
excursoes_permitidas array IDs de excursões em que o cupom é válido (null = todas)
excursoes_excluidas array IDs de excursões em que o cupom NÃO vale
categorias_permitidas array IDs de categorias de passageiro permitidas
apenas_primeira_compra boolean Se true, só vale para clientes sem compra anterior
clientes_permitidos array IDs de clientes que podem usar (null = todos)
clientes_bloqueados array IDs de clientes que NÃO podem usar
ativo boolean Cupom ativo (default true)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Cupom criado com sucesso.",
    "data": {
        "id": 42,
        "codigo": "VERAO50",
        "nome": "Promoção Verão 2026",
        "descricao": "Desconto de 15% nas excursões de janeiro e fevereiro",
        "tipo": "publico",
        "tipo_label": "Público",
        "tipo_desconto": "percentual",
        "tipo_desconto_label": "Percentual",
        "valor_desconto": 15,
        "desconto_formatado": "15%",
        "valor_maximo_desconto": 300,
        "valor_minimo_pedido": 500,
        "limite_uso_total": 100,
        "limite_uso_por_cliente": 1,
        "usos": 27,
        "usos_disponiveis": 73,
        "usos_progresso": "27\/100",
        "data_inicio": "2026-01-01T00:00:00Z",
        "data_expiracao": "2026-02-28T23:59:59Z",
        "excursoes_permitidas": null,
        "excursoes_excluidas": null,
        "categorias_permitidas": null,
        "apenas_primeira_compra": false,
        "clientes_permitidos": null,
        "clientes_bloqueados": null,
        "cupom_pai_id": null,
        "lote_nome": null,
        "is_lote": false,
        "is_filho_lote": false,
        "ativo": true,
        "status": "Ativo",
        "status_color": "green",
        "valido": true,
        "created_at": "2025-12-15T10:00:00Z",
        "updated_at": "2026-01-10T14:30:00Z"
    }
}

Atualiza os campos do cupom. Todos os campos são opcionais (envie apenas os que mudaram).

Escopo necessário cupons:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do cupom

Corpo da requisição

Campo Tipo Descrição
codigo string Código que o cliente digita no checkout (case-insensitive, hífens/espaços ignorados). Ex: VERAO50
nome string Nome interno do cupom (visível no admin)
descricao string Descrição opcional
tipo string publico | unico | cliente | primeira_compra | indicacao
tipo_desconto string percentual | valor_fixo | valor_por_passageiro | frete_gratis
valor_desconto number Valor do desconto. Em percentual: 0-100. Em valor_fixo: R$. Em valor_por_passageiro: R$ por pax
valor_maximo_desconto number Teto do desconto em R$ (útil para percentuais)
limite_uso_total integer Quantas vezes o cupom pode ser usado no total (null = ilimitado)
limite_uso_por_cliente integer Quantas vezes cada cliente pode usar (null = ilimitado)
valor_minimo_pedido number Valor mínimo do pedido para o cupom valer
data_inicio string Início da vigência (ISO 8601). null = vale desde já
data_expiracao string Fim da vigência (ISO 8601). null = sem expiração
excursoes_permitidas array IDs de excursões em que o cupom é válido (null = todas)
excursoes_excluidas array IDs de excursões em que o cupom NÃO vale
categorias_permitidas array IDs de categorias de passageiro permitidas
apenas_primeira_compra boolean Se true, só vale para clientes sem compra anterior
clientes_permitidos array IDs de clientes que podem usar (null = todos)
clientes_bloqueados array IDs de clientes que NÃO podem usar
ativo boolean Cupom ativo (default true)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Cupom atualizado com sucesso.",
    "data": {
        "id": 42,
        "codigo": "VERAO50",
        "nome": "Promoção Verão 2026",
        "descricao": "Desconto de 15% nas excursões de janeiro e fevereiro",
        "tipo": "publico",
        "tipo_label": "Público",
        "tipo_desconto": "percentual",
        "tipo_desconto_label": "Percentual",
        "valor_desconto": 15,
        "desconto_formatado": "15%",
        "valor_maximo_desconto": 300,
        "valor_minimo_pedido": 500,
        "limite_uso_total": 100,
        "limite_uso_por_cliente": 1,
        "usos": 27,
        "usos_disponiveis": 73,
        "usos_progresso": "27\/100",
        "data_inicio": "2026-01-01T00:00:00Z",
        "data_expiracao": "2026-02-28T23:59:59Z",
        "excursoes_permitidas": null,
        "excursoes_excluidas": null,
        "categorias_permitidas": null,
        "apenas_primeira_compra": false,
        "clientes_permitidos": null,
        "clientes_bloqueados": null,
        "cupom_pai_id": null,
        "lote_nome": null,
        "is_lote": false,
        "is_filho_lote": false,
        "ativo": true,
        "status": "Ativo",
        "status_color": "green",
        "valido": true,
        "created_at": "2025-12-15T10:00:00Z",
        "updated_at": "2026-01-10T14:30:00Z"
    }
}

Inverte o status ativo do cupom (toggle). Útil para pausar/retomar um cupom sem excluí-lo.

Escopo necessário cupons:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do cupom

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Status do cupom atualizado.",
    "data": {
        "id": 42,
        "codigo": "VERAO50",
        "nome": "Promoção Verão 2026",
        "descricao": "Desconto de 15% nas excursões de janeiro e fevereiro",
        "tipo": "publico",
        "tipo_label": "Público",
        "tipo_desconto": "percentual",
        "tipo_desconto_label": "Percentual",
        "valor_desconto": 15,
        "desconto_formatado": "15%",
        "valor_maximo_desconto": 300,
        "valor_minimo_pedido": 500,
        "limite_uso_total": 100,
        "limite_uso_por_cliente": 1,
        "usos": 27,
        "usos_disponiveis": 73,
        "usos_progresso": "27\/100",
        "data_inicio": "2026-01-01T00:00:00Z",
        "data_expiracao": "2026-02-28T23:59:59Z",
        "excursoes_permitidas": null,
        "excursoes_excluidas": null,
        "categorias_permitidas": null,
        "apenas_primeira_compra": false,
        "clientes_permitidos": null,
        "clientes_bloqueados": null,
        "cupom_pai_id": null,
        "lote_nome": null,
        "is_lote": false,
        "is_filho_lote": false,
        "ativo": false,
        "status": "Ativo",
        "status_color": "green",
        "valido": true,
        "created_at": "2025-12-15T10:00:00Z",
        "updated_at": "2026-01-10T14:30:00Z"
    }
}

Remove permanentemente o cupom. Retorna 400 se já foi utilizado em alguma reserva (desative-o em vez de excluir).

Escopo necessário cupons:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do cupom

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Cupom excluído com sucesso."
}

Verifica se o código é válido e calcula o desconto. Útil para mostrar o desconto no checkout antes de confirmar. Não consome o cupom.

Escopo necessário cupons:validate

Corpo da requisição

Campo Tipo Descrição
codigo * string Código do cupom (case-insensitive)
cliente_id integer ID do cliente (necessário para tipos cliente/primeira_compra/indicacao)
valor_total number Valor total do pedido em R$ (para validar valor_minimo_pedido)
excursao_id integer ID da excursão (para validar excursoes_permitidas/excluidas)
quantidade_passageiros integer Quantidade de passageiros (necessário para tipo_desconto=valor_por_passageiro). Default: 1

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Cupom válido.",
    "data": {
        "success": true,
        "cupom": {
            "id": 42,
            "codigo": "VERAO50",
            "nome": "Promoção Verão 2026",
            "tipo_desconto": "percentual",
            "desconto_formatado": "15%"
        },
        "desconto": 180,
        "desconto_formatado": "R$ 180,00"
    }
}

Aplica o cupom em uma reserva existente. Operação atômica com lock no cupom (evita race condition em limite_uso_total). Atualiza valor_total da order, registra CupomUso e incrementa o contador de usos.

Escopo necessário cupons:validate

Parâmetros

Nome Tipo Local Descrição
orderId * integer path ID da reserva (Order)

Corpo da requisição

Campo Tipo Descrição
codigo * string Código do cupom
cliente_id * integer ID do cliente comprador

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Cupom aplicado com sucesso.",
    "data": {
        "success": true,
        "desconto": 180,
        "desconto_formatado": "R$ 180,00",
        "valor_original": 1200,
        "valor_total": 1020
    }
}

Remove o cupom aplicado em uma reserva, restaurando o valor_total original. Decrementa o contador de usos.

Escopo necessário cupons:validate

Parâmetros

Nome Tipo Local Descrição
orderId * integer path ID da reserva

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Cupom removido com sucesso.",
    "data": {
        "success": true,
        "valor_total": 1200
    }
}

Guias

Cadastro de guias e designação em excursões

Lista paginada de guias com filtros.

Escopo necessário guias:read

Parâmetros

Nome Tipo Local Descrição
search string query Buscar por nome
ativo boolean query Filtrar por ativo
per_page integer query Itens por página

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 7,
            "nome": "Carlos Santos",
            "email": "[email protected]",
            "cpf": "98765432100",
            "telefone": "1144445555",
            "celular": "11988887777",
            "data_nascimento": "1985-03-20",
            "banco": "Itaú",
            "agencia": "0001",
            "conta": "12345678",
            "tipo_conta": "corrente",
            "pix": "[email protected]",
            "ativo": true,
            "created_at": "2024-01-10T09:00:00Z"
        }
    ]
}

Retorna todos os dados do guia.

Escopo necessário guias:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 7,
        "nome": "Carlos Santos",
        "email": "[email protected]",
        "cpf": "98765432100",
        "telefone": "1144445555",
        "celular": "11988887777",
        "data_nascimento": "1985-03-20",
        "banco": "Itaú",
        "agencia": "0001",
        "conta": "12345678",
        "tipo_conta": "corrente",
        "pix": "[email protected]",
        "ativo": true,
        "created_at": "2024-01-10T09:00:00Z"
    }
}

Cadastra um novo guia.

Escopo necessário guias:write

Corpo da requisição

Campo Tipo Descrição
nome * string Nome completo
email string E-mail
telefone string Telefone fixo
celular string Celular
cpf string CPF
rg string RG
data_nascimento date Nascimento (Y-m-d)
cep string CEP
endereco string Endereço
numero string Número
complemento string Complemento
bairro string Bairro
cidade string Cidade
estado string UF
banco string Banco (para repasses)
agencia string Agência
conta string Conta
tipo_conta string corrente, poupanca
pix string Chave PIX
observacoes string Observações
ativo boolean Guia ativo (default true)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Guia cadastrado com sucesso.",
    "data": {
        "id": 7,
        "nome": "Carlos Santos",
        "email": "[email protected]",
        "cpf": "98765432100",
        "telefone": "1144445555",
        "celular": "11988887777",
        "data_nascimento": "1985-03-20",
        "banco": "Itaú",
        "agencia": "0001",
        "conta": "12345678",
        "tipo_conta": "corrente",
        "pix": "[email protected]",
        "ativo": true,
        "created_at": "2024-01-10T09:00:00Z"
    }
}

Atualiza os dados do guia.

Escopo necessário guias:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID

Corpo da requisição

Campo Tipo Descrição
nome string Nome completo
email string E-mail
telefone string Telefone fixo
celular string Celular
cpf string CPF
rg string RG
data_nascimento date Nascimento (Y-m-d)
cep string CEP
endereco string Endereço
numero string Número
complemento string Complemento
bairro string Bairro
cidade string Cidade
estado string UF
banco string Banco (para repasses)
agencia string Agência
conta string Conta
tipo_conta string corrente, poupanca
pix string Chave PIX
observacoes string Observações
ativo boolean Guia ativo (default true)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Guia atualizado.",
    "data": {
        "id": 7,
        "nome": "Carlos Santos",
        "email": "[email protected]",
        "cpf": "98765432100",
        "telefone": "1144445555",
        "celular": "11988887777",
        "data_nascimento": "1985-03-20",
        "banco": "Itaú",
        "agencia": "0001",
        "conta": "12345678",
        "tipo_conta": "corrente",
        "pix": "[email protected]",
        "ativo": true,
        "created_at": "2024-01-10T09:00:00Z"
    }
}

Ativa ou desativa o guia.

Escopo necessário guias:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Status alterado.",
    "data": {
        "ativo": false
    }
}

Remove o guia.

Escopo necessário guias:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Guia excluído."
}

Lista os guias designados para uma excursão.

Escopo necessário guias:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 51,
            "excursao_id": 45,
            "guia_id": 7,
            "funcao": "guia_principal",
            "valor_pagamento": 800,
            "guia": {
                "id": 7,
                "nome": "Carlos Santos",
                "email": "[email protected]",
                "cpf": "98765432100",
                "telefone": "1144445555",
                "celular": "11988887777",
                "data_nascimento": "1985-03-20",
                "banco": "Itaú",
                "agencia": "0001",
                "conta": "12345678",
                "tipo_conta": "corrente",
                "pix": "[email protected]",
                "ativo": true,
                "created_at": "2024-01-10T09:00:00Z"
            }
        }
    ]
}

Designa um guia para a excursão.

Escopo necessário guias:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
guia_id * integer ID do guia
transporte_id integer ID do transporte específico (se múltiplos)
embarque_id integer ID do embarque
funcao * string guia_principal, guia_auxiliar, monitor
valor_pagamento number Valor a pagar ao guia
observacao string Observação

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Guia designado.",
    "data": {
        "id": 51,
        "excursao_id": 45,
        "guia_id": 7,
        "funcao": "guia_principal"
    }
}

Veículos

Cadastro de veículos (ônibus, vans, carros)

Lista veículos com filtros.

Escopo necessário veiculos:read

Parâmetros

Nome Tipo Local Descrição
tipo string query Tipo do veículo
transporte_id integer query Filtrar pela empresa dona
ativo boolean query Filtrar por ativo
search string query Busca por modelo, placa

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 5,
            "transporte_id": 2,
            "tipo": "onibus_leito",
            "modelo": "Paradiso 1600 LD",
            "placa": "ABC-1234",
            "renavam": "12345678901",
            "ano_fabricacao": 2019,
            "capacidade_total": 46,
            "ar_condicionado": true,
            "wifi": true,
            "banheiro": true,
            "tv": true,
            "tomadas": true,
            "reclinavel": false,
            "ativo": true,
            "transporte": {
                "id": 2,
                "nome_fantasia": "Viagens Brasil Express",
                "cnpj": "12.345.678\/0001-90"
            },
            "created_at": "2024-01-05T15:45:00Z"
        }
    ]
}

Lista os tipos aceitos pelo campo tipo.

Escopo necessário veiculos:read

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        "van",
        "micro_onibus",
        "onibus",
        "onibus_leito",
        "onibus_semileito",
        "onibus_executivo",
        "onibus_double_decker",
        "minivan",
        "carro"
    ]
}

Retorna o veículo com a empresa de transporte.

Escopo necessário veiculos:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 5,
        "transporte_id": 2,
        "tipo": "onibus_leito",
        "modelo": "Paradiso 1600 LD",
        "placa": "ABC-1234",
        "renavam": "12345678901",
        "ano_fabricacao": 2019,
        "capacidade_total": 46,
        "ar_condicionado": true,
        "wifi": true,
        "banheiro": true,
        "tv": true,
        "tomadas": true,
        "reclinavel": false,
        "ativo": true,
        "transporte": {
            "id": 2,
            "nome_fantasia": "Viagens Brasil Express",
            "cnpj": "12.345.678\/0001-90"
        },
        "created_at": "2024-01-05T15:45:00Z"
    }
}

Cadastra um veículo vinculado a uma empresa de transporte.

Escopo necessário veiculos:write

Corpo da requisição

Campo Tipo Descrição
transporte_id * integer ID da empresa de transporte dona do veículo
tipo * string van, micro_onibus, onibus, onibus_leito, onibus_semileito, onibus_executivo, onibus_double_decker, minivan, carro
modelo * string Modelo (ex: Mercedes-Benz O-500)
placa string Placa
renavam string RENAVAM
ano_fabricacao integer Ano de fabricação
capacidade_total * integer Capacidade de passageiros (>=1)
ar_condicionado boolean Tem ar-condicionado
wifi boolean Tem Wi-Fi
banheiro boolean Tem banheiro
tv boolean Tem TV
tomadas boolean Tem tomadas
reclinavel boolean Assentos reclináveis
observacoes string Observações
ativo boolean Veículo ativo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Veículo criado.",
    "data": {
        "id": 5,
        "transporte_id": 2,
        "tipo": "onibus_leito",
        "modelo": "Paradiso 1600 LD",
        "placa": "ABC-1234",
        "renavam": "12345678901",
        "ano_fabricacao": 2019,
        "capacidade_total": 46,
        "ar_condicionado": true,
        "wifi": true,
        "banheiro": true,
        "tv": true,
        "tomadas": true,
        "reclinavel": false,
        "ativo": true,
        "transporte": {
            "id": 2,
            "nome_fantasia": "Viagens Brasil Express",
            "cnpj": "12.345.678\/0001-90"
        },
        "created_at": "2024-01-05T15:45:00Z"
    }
}

Atualiza parcialmente o veículo.

Escopo necessário veiculos:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID

Corpo da requisição

Campo Tipo Descrição
transporte_id integer ID da empresa de transporte dona do veículo
tipo string van, micro_onibus, onibus, onibus_leito, onibus_semileito, onibus_executivo, onibus_double_decker, minivan, carro
modelo string Modelo (ex: Mercedes-Benz O-500)
placa string Placa
renavam string RENAVAM
ano_fabricacao integer Ano de fabricação
capacidade_total integer Capacidade de passageiros (>=1)
ar_condicionado boolean Tem ar-condicionado
wifi boolean Tem Wi-Fi
banheiro boolean Tem banheiro
tv boolean Tem TV
tomadas boolean Tem tomadas
reclinavel boolean Assentos reclináveis
observacoes string Observações
ativo boolean Veículo ativo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Veículo atualizado.",
    "data": {
        "id": 5,
        "transporte_id": 2,
        "tipo": "onibus_leito",
        "modelo": "Paradiso 1600 LD",
        "placa": "ABC-1234",
        "renavam": "12345678901",
        "ano_fabricacao": 2019,
        "capacidade_total": 46,
        "ar_condicionado": true,
        "wifi": true,
        "banheiro": true,
        "tv": true,
        "tomadas": true,
        "reclinavel": false,
        "ativo": true,
        "transporte": {
            "id": 2,
            "nome_fantasia": "Viagens Brasil Express",
            "cnpj": "12.345.678\/0001-90"
        },
        "created_at": "2024-01-05T15:45:00Z"
    }
}

Alterna entre ativo e inativo.

Escopo necessário veiculos:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "ativo": false
    }
}

Remove o veículo.

Escopo necessário veiculos:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Veículo excluído."
}

Transportes

Cadastro de empresas de transporte e atribuição em excursões

Lista paginada com filtros.

Escopo necessário transportes:read

Parâmetros

Nome Tipo Local Descrição
search string query Buscar por nome
ativo boolean query Filtrar por ativo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 2,
            "nome_fantasia": "Viagens Brasil Express",
            "razao_social": "Viagens Brasil Express LTDA",
            "cnpj": "12.345.678\/0001-90",
            "email": "[email protected]",
            "telefone": "1133334444",
            "whatsapp": "11999998888",
            "cidade": "São Paulo",
            "estado": "SP",
            "contato_nome": "Pedro Oliveira",
            "contato_telefone": "11988887777",
            "ativo": true,
            "created_at": "2024-01-05T15:45:00Z"
        }
    ]
}

Retorna a empresa com dados completos.

Escopo necessário transportes:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 2,
        "nome_fantasia": "Viagens Brasil Express",
        "razao_social": "Viagens Brasil Express LTDA",
        "cnpj": "12.345.678\/0001-90",
        "email": "[email protected]",
        "telefone": "1133334444",
        "whatsapp": "11999998888",
        "cidade": "São Paulo",
        "estado": "SP",
        "contato_nome": "Pedro Oliveira",
        "contato_telefone": "11988887777",
        "ativo": true,
        "created_at": "2024-01-05T15:45:00Z"
    }
}

Cadastra uma nova empresa de transporte.

Escopo necessário transportes:write

Corpo da requisição

Campo Tipo Descrição
nome_fantasia * string Nome fantasia
razao_social string Razão social
cnpj string CNPJ
email string E-mail
telefone string Telefone principal
telefone_secundario string Telefone alternativo
whatsapp string WhatsApp
site string Site oficial
cep string CEP
endereco string Endereço
numero string Número
complemento string Complemento
bairro string Bairro
cidade string Cidade
estado string UF
contato_nome string Pessoa de contato
contato_telefone string Telefone do contato
contato_email string E-mail do contato
observacoes string Observações
ativo boolean Empresa ativa

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Empresa cadastrada.",
    "data": {
        "id": 2,
        "nome_fantasia": "Viagens Brasil Express",
        "razao_social": "Viagens Brasil Express LTDA",
        "cnpj": "12.345.678\/0001-90",
        "email": "[email protected]",
        "telefone": "1133334444",
        "whatsapp": "11999998888",
        "cidade": "São Paulo",
        "estado": "SP",
        "contato_nome": "Pedro Oliveira",
        "contato_telefone": "11988887777",
        "ativo": true,
        "created_at": "2024-01-05T15:45:00Z"
    }
}

Atualiza parcialmente os dados.

Escopo necessário transportes:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID

Corpo da requisição

Campo Tipo Descrição
nome_fantasia string Nome fantasia
razao_social string Razão social
cnpj string CNPJ
email string E-mail
telefone string Telefone principal
telefone_secundario string Telefone alternativo
whatsapp string WhatsApp
site string Site oficial
cep string CEP
endereco string Endereço
numero string Número
complemento string Complemento
bairro string Bairro
cidade string Cidade
estado string UF
contato_nome string Pessoa de contato
contato_telefone string Telefone do contato
contato_email string E-mail do contato
observacoes string Observações
ativo boolean Empresa ativa

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Empresa atualizada.",
    "data": {
        "id": 2,
        "nome_fantasia": "Viagens Brasil Express",
        "razao_social": "Viagens Brasil Express LTDA",
        "cnpj": "12.345.678\/0001-90",
        "email": "[email protected]",
        "telefone": "1133334444",
        "whatsapp": "11999998888",
        "cidade": "São Paulo",
        "estado": "SP",
        "contato_nome": "Pedro Oliveira",
        "contato_telefone": "11988887777",
        "ativo": true,
        "created_at": "2024-01-05T15:45:00Z"
    }
}

Ativa ou desativa a empresa.

Escopo necessário transportes:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "ativo": false
    }
}

Remove a empresa.

Escopo necessário transportes:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Empresa excluída."
}

Lista os transportes (veículos + vagas) configurados na excursão.

Escopo necessário transportes:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 9,
            "excursao_id": 45,
            "veiculo_id": 5,
            "empresa_transporte_id": 2,
            "nome": "Ônibus 1",
            "numero": "01",
            "tipo": "onibus_leito",
            "vagas_total": 46,
            "vagas_reserva_admin": 2,
            "ordem": 0,
            "ativo": true,
            "veiculo": {
                "id": 5,
                "modelo": "Paradiso 1600 LD",
                "placa": "ABC-1234"
            }
        }
    ]
}

Configura um veículo para a excursão com vagas.

Escopo necessário transportes:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
veiculo_id * integer ID do veículo
empresa_transporte_id integer ID da empresa (default do veículo)
nome string Nome exibido (ex: "Ônibus 1")
numero string Número
tipo string onibus, micro_onibus, van, carro, outro
vagas_total * integer Vagas totais (>=1)
vagas_reserva_admin integer Vagas reservadas para venda interna
ordem integer Ordem de exibição
ativo boolean Ativo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 9,
        "excursao_id": 45,
        "veiculo_id": 5
    }
}

Hospedagem

Addon Hospedagem — cadastro de hotéis/pousadas, tipos de quarto, suplementos, vínculo com excursões (allotment + valores) e alocação real de quartos para passageiros e guias. Requer addon `hospedagem` ativo no tenant (403 caso contrário).

Paginada. Filtros opcionais: ativo, tipo, cidade, search.

Escopo necessário hospedagem:read

Parâmetros

Nome Tipo Local Descrição
ativo boolean query true|false
tipo string query hotel|pousada|resort|hostel|chacara|camping|outro
cidade string query
search string query Busca por nome
per_page integer query Max 100 (default 20)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [],
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 0,
        "last_page": 1
    }
}

Aceita criação aninhada de `tipos_quarto[]` e `suplementos[]` no mesmo payload.

Escopo necessário hospedagem:write

Corpo da requisição

Campo Tipo Descrição
nome * string
tipo * string hotel|pousada|resort|hostel|chacara|camping|outro
endereco string
cidade string
estado string UF (2 letras)
cep string
telefone string
email string
website string URL
descricao string
amenidades array Ex: ["wifi","piscina","cafe_manha"]
politica_checkin string HH:MM
politica_checkout string HH:MM
politica_cancelamento string
ativo boolean
tipos_quarto array Array de {nome, capacidade_min, capacidade_max, descricao}
suplementos array Array de {nome, tipo, preco_padrao, cobranca}

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Hospedaria cadastrada com sucesso.",
    "data": {
        "id": 1
    }
}

Detalhes da hospedaria

Escopo necessário hospedagem:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da hospedaria

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 1,
        "nome": "Hotel Madero",
        "tipo": "hotel",
        "tipos_quarto": [],
        "suplementos": []
    }
}

Atualizar hospedaria

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da hospedaria

Corpo da requisição

Campo Tipo Descrição
nome string
tipo string
cidade string
ativo boolean

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Hospedaria atualizada."
}

Falha com 422 se houver excursões vinculadas.

Escopo necessário hospedagem:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da hospedaria

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Hospedaria removida."
}

Toggle ativo/inativo

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da hospedaria

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "ativo": true
    }
}

Listar tipos de quarto

Escopo necessário hospedagem:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da hospedaria

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": []
}

Criar tipo de quarto

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da hospedaria

Corpo da requisição

Campo Tipo Descrição
nome * string Ex: Standard Duplo, Suíte Master
capacidade_min * integer Min 1
capacidade_max * integer Min 1
descricao string
amenidades array
foto_url string URL
ordem integer
ativo boolean

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 5
    }
}

Atualizar tipo de quarto

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da hospedaria
tipoId * integer path ID do tipo

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Falha com 422 se houver allotment usando este tipo.

Escopo necessário hospedagem:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da hospedaria
tipoId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Listar suplementos

Escopo necessário hospedagem:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da hospedaria

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": []
}

Suplementos são extras (café reforçado, upgrade vista mar, etc) com preço padrão da hospedaria.

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da hospedaria

Corpo da requisição

Campo Tipo Descrição
nome * string
tipo * string Tipos definidos em Suplemento::TIPOS
preco_padrao * number
cobranca * string por_pessoa|por_quarto|por_noite
descricao string
ativo boolean

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 3
    }
}

Atualizar suplemento

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da hospedaria
suplementoId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Remover suplemento

Escopo necessário hospedagem:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da hospedaria
suplementoId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Listar hospedagens da excursão

Escopo necessário hospedagem:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": []
}

Lista hospedarias do tenant que ainda não estão vinculadas à excursão.

Escopo necessário hospedagem:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": []
}

Cria o vínculo, opcionalmente com `quartos_disponiveis[]` (allotment) e `suplementos[]` configurados pra essa excursão. Sincroniza custo com módulo financeiro.

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão

Corpo da requisição

Campo Tipo Descrição
hospedaria_id * integer
checkin_data * string YYYY-MM-DD
checkout_data * string YYYY-MM-DD (após checkin)
checkin_hora string HH:MM
checkout_hora string HH:MM
custo_total number
observacoes string
rooming_list_prazo string YYYY-MM-DD
status string pendente|confirmado|cancelado
quartos_disponiveis array Array de {tipo_quarto_id, quantidade, preco_por_pessoa, preco_por_quarto, custo_por_quarto, visivel_checkout}
suplementos array Array de {suplemento_id, preco, cobranca, visivel_checkout}

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 10
    }
}

Atualizar vínculo

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Remover vínculo

Escopo necessário hospedagem:delete

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Retorna os quartos criados (gerados a partir do allotment ou adicionados manualmente) com os hóspedes alocados em cada um.

Escopo necessário hospedagem:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "quartos": []
    }
}

Adicionar quarto avulso

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem

Corpo da requisição

Campo Tipo Descrição
tipo_quarto_id * integer
numero string Identificador (ex: 101, Cabine A12)
observacoes string

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Quarto adicionado"
}

Atualizar quarto

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem
quartoId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Falha com 422 se houver hóspedes alocados (desalocar antes).

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem
quartoId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Cria quartos vazios automaticamente baseado nos `quartos_disponiveis` do vínculo.

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Alocar passageiro em quarto

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem

Corpo da requisição

Campo Tipo Descrição
passageiro_id * integer ID do ExcursaoPassageiro
quarto_id * integer

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Desalocar passageiro

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem

Corpo da requisição

Campo Tipo Descrição
passageiro_id * integer

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Passageiro removido do quarto"
}

Alocar guia em quarto

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem

Corpo da requisição

Campo Tipo Descrição
guia_id * integer
quarto_id * integer

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Desalocar guia

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem

Corpo da requisição

Campo Tipo Descrição
guia_id * integer

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Distribui passageiros nos quartos automaticamente, respeitando capacidade e separação por gênero/grupo familiar quando aplicável.

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Remove todos os passageiros e guias dos quartos. Mantém os quartos criados.

Escopo necessário hospedagem:write

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Passageiros sem quarto

Escopo necessário hospedagem:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "passageiros": []
    }
}

Guias sem quarto

Escopo necessário hospedagem:read

Parâmetros

Nome Tipo Local Descrição
excursaoId * integer path ID da excursão
vinculoId * integer path ID do vínculo excursão-hospedagem

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "guias": []
    }
}

Ingressos

Addon Ingressos — cadastro de atrações/eventos, categorias (tipos de ingresso com preço custo/venda), controle de estoque por data e vendas. Requer addon `ingressos` ativo no tenant (403 caso contrário).

Paginada. Filtros: ativo, cidade, search, data_min, data_max.

Escopo necessário ingressos:read

Parâmetros

Nome Tipo Local Descrição
ativo boolean query
cidade string query
search string query Busca por nome
data_min string query Data evento mínima YYYY-MM-DD
data_max string query Data evento máxima YYYY-MM-DD
per_page integer query Max 100 (default 20)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [],
    "meta": {
        "total": 0
    }
}

Quando `tipo_venda=direta` (default), `categorias[]` é obrigatório. Quando `tipo_venda=afiliado`, `website` é obrigatório e categorias podem ser omitidas.

Escopo necessário ingressos:write

Corpo da requisição

Campo Tipo Descrição
nome * string
descricao string
local string
cidade string
estado string UF (2 letras)
website string URL — obrigatório se tipo_venda=afiliado
imagem_url string URL
data_evento string YYYY-MM-DD (não pode ser passado)
hora_evento string HH:MM
quantidade_total integer
quantidade_limite_venda integer
ativo boolean
destaque boolean
tipo_venda string direta (default) | afiliado
categorias array Array de {nome, descricao, idade_min, idade_max, preco_custo, preco_venda}. Obrigatório se tipo_venda=direta

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Ingresso cadastrado.",
    "data": {
        "id": 1
    }
}

Detalhes do ingresso

Escopo necessário ingressos:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do ingresso

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 1,
        "nome": "Show da banda X",
        "categorias": []
    }
}

Atualizar ingresso

Escopo necessário ingressos:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do ingresso

Corpo da requisição

Campo Tipo Descrição
nome string
descricao string
ativo boolean
destaque boolean

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Ingresso atualizado."
}

Falha com 422 se houver vendas registradas.

Escopo necessário ingressos:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do ingresso

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Toggle ativo/inativo

Escopo necessário ingressos:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do ingresso

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "ativo": true
    }
}

Listar categorias

Escopo necessário ingressos:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do ingresso

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": []
}

Ex: Inteira, Meia, Idoso, Estudante. Cada categoria tem preço de custo e venda.

Escopo necessário ingressos:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do ingresso

Corpo da requisição

Campo Tipo Descrição
nome * string Ex: Inteira, Meia, Idoso
descricao string
idade_min integer
idade_max integer
preco_custo * number
preco_venda * number
ativo boolean
ordem integer

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 1
    }
}

Atualizar categoria

Escopo necessário ingressos:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do ingresso
categoriaId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Remover categoria

Escopo necessário ingressos:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do ingresso
categoriaId * integer path

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Listar estoque por data

Escopo necessário ingressos:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do ingresso
data_min string query YYYY-MM-DD
data_max string query YYYY-MM-DD

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": []
}

Upsert por (ingresso_id, data). Para alterar várias datas chame múltiplas vezes.

Escopo necessário ingressos:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do ingresso

Corpo da requisição

Campo Tipo Descrição
data * string YYYY-MM-DD
quantidade_total * integer Estoque total para essa data
disponivel boolean Liga/desliga venda nessa data

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Estoque atualizado."
}

Paginada. Filtros: ingresso_id, status, data_min, data_max.

Escopo necessário ingressos:read

Parâmetros

Nome Tipo Local Descrição
ingresso_id integer query
status string query pendente|pago|cancelado|usado
data_min string query YYYY-MM-DD
data_max string query YYYY-MM-DD
per_page integer query

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": []
}

Registra venda manualmente (ex: vendido no balcão). `valor_total` é calculado automaticamente como `quantidade * valor_unitario - desconto`.

Escopo necessário ingressos:write

Corpo da requisição

Campo Tipo Descrição
ingresso_id * integer
categoria_id * integer
cliente_id integer Se cliente já cadastrado
comprador_nome * string
comprador_cpf string
comprador_email string
comprador_telefone string
quantidade * integer Min 1
valor_unitario * number
desconto number Default 0
forma_pagamento string pix|dinheiro|cartao|...
data_uso string YYYY-MM-DD
observacoes string
status string pendente (default) | pago | cancelado | usado

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Venda registrada.",
    "data": {
        "id": 100
    }
}

Detalhes da venda

Escopo necessário ingressos:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da venda

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 100,
        "status": "pago"
    }
}

Atualizar status da venda

Escopo necessário ingressos:write

Parâmetros

Nome Tipo Local Descrição
id * integer path

Corpo da requisição

Campo Tipo Descrição
status * string pendente | pago | cancelado | usado

Resposta de exemplo

JSON
200 OK
{
    "success": true
}

Experiências

Módulo de Experiências Turísticas (passeios): catálogo com categorias, horários, extras, temporadas e fotos, além das vendas com voucher por pessoa e check-in individual. Requer o addon passeios-experiencias ativo no tenant.

Lista paginada do catálogo, com a contagem de categorias, horários, extras e vendas de cada passeio.

Escopo necessário passeios:read

Parâmetros

Nome Tipo Local Descrição
page integer query Número da página
per_page integer query Itens por página (max: 100)
ativo boolean query Filtra por disponível para venda
destaque boolean query Somente destacados
mostrar_site boolean query Somente os publicados no site
status string query rascunho ou publicado
cidade string query Busca parcial por cidade
estado string query UF exata
pais string query País exato
categoria_tipo string query Tipo do passeio
dificuldade string query Nível de dificuldade
search string query Busca em nome, descrição curta e local
include string query Sub-recursos no mesmo payload: categorias, horarios, extras, temporadas, fotos (separados por vírgula)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 12,
            "nome": "Trilha da Pedra Bonita ao amanhecer",
            "slug": "trilha-pedra-bonita-amanhecer",
            "descricao_curta": "Subida guiada com vista para a Barra da Tijuca.",
            "local": "Parque Nacional da Tijuca",
            "cidade": "Rio de Janeiro",
            "estado": "RJ",
            "pais": "Brasil",
            "ponto_encontro": "Estacionamento da Pedra Bonita",
            "latitude": -22.9871234,
            "longitude": -43.2812345,
            "duracao_minutos": 180,
            "dificuldade": "moderado",
            "idade_minima": 12,
            "capacidade_maxima": 20,
            "antecedencia_minima_horas": 12,
            "cancelamento_horas": 24,
            "reembolso_percentual": 100,
            "exigir_waiver": true,
            "mostrar_site": true,
            "ativo": true,
            "status": "publicado",
            "categorias_count": 2,
            "horarios_count": 3,
            "extras_count": 1,
            "vendas_count": 47
        }
    ]
}

Retorna o passeio com categorias, horários, extras, temporadas e fotos já carregados.

Escopo necessário passeios:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 12,
        "nome": "Trilha da Pedra Bonita ao amanhecer",
        "slug": "trilha-pedra-bonita-amanhecer",
        "descricao_curta": "Subida guiada com vista para a Barra da Tijuca.",
        "local": "Parque Nacional da Tijuca",
        "cidade": "Rio de Janeiro",
        "estado": "RJ",
        "pais": "Brasil",
        "ponto_encontro": "Estacionamento da Pedra Bonita",
        "latitude": -22.9871234,
        "longitude": -43.2812345,
        "duracao_minutos": 180,
        "dificuldade": "moderado",
        "idade_minima": 12,
        "capacidade_maxima": 20,
        "antecedencia_minima_horas": 12,
        "cancelamento_horas": 24,
        "reembolso_percentual": 100,
        "exigir_waiver": true,
        "mostrar_site": true,
        "ativo": true,
        "status": "publicado",
        "categorias_count": 2,
        "horarios_count": 3,
        "extras_count": 1,
        "vendas_count": 47,
        "categorias": [
            {
                "id": 30,
                "passeio_id": 12,
                "nome": "Adulto",
                "descricao": "A partir de 12 anos",
                "preco_custo": 40,
                "preco_venda": 120,
                "idade_min": 12,
                "idade_max": null,
                "conta_como": "pessoa",
                "estoque_consome": 1,
                "ativo": true,
                "ordem": 0
            }
        ]
    }
}

Cria um passeio. Aceita as categorias no mesmo payload, porque passeio sem categoria não vende. O slug é gerado a partir do nome quando não informado.

Escopo necessário passeios:write

Corpo da requisição

Campo Tipo Descrição
nome * string Nome do passeio
slug string URL amigável. Gerado a partir do nome quando omitido. Único por tenant
descricao string Descrição completa (HTML permitido)
descricao_curta string Resumo usado em listagens e cards
o_que_inclui string O que está incluído no valor
o_que_nao_inclui string O que não está incluído
o_que_levar string Itens que o cliente deve levar
dicas string Dicas para o participante
requisitos string Requisitos de saúde, físicos ou documentais
local string Local do passeio
endereco string Endereço completo
cidade string Cidade
estado string UF (2 letras)
pais string País
continente string Continente
destino_slug string Slug do destino, para agrupar passeios da mesma região
ponto_encontro string Onde o grupo se encontra
ponto_encontro_maps string Link do Google Maps do ponto de encontro
latitude number Latitude (-90 a 90)
longitude number Longitude (-180 a 180)
imagem string URL da imagem de capa
videos array Lista de URLs de vídeo
duracao_minutos integer Duração em minutos
dificuldade string Nível de dificuldade (facil, moderado, dificil)
idade_minima integer Idade mínima permitida
capacidade_maxima integer Capacidade máxima por saída
categoria_tipo string Tipo do passeio (aventura, cultural, gastronomico...)
antecedencia_minima_horas integer Antecedência mínima para reservar
cancelamento_horas integer Prazo em horas para cancelar com reembolso
reembolso_percentual integer Percentual reembolsado dentro do prazo (0 a 100)
permitir_reagendamento boolean Permite remarcar a data
exigir_waiver boolean Exige termo de responsabilidade assinado
mostrar_site boolean Aparece no site público
ativo boolean Disponível para venda (default true)
destaque boolean Destacado nas listagens
status string rascunho ou publicado
banner_display_mode string Como a capa é exibida no site
meta_title string Título para SEO
meta_description string Descrição para SEO
meta_keywords string Palavras-chave para SEO
observacoes_internas string Notas internas, não exibidas ao cliente
preco_display_modo string Como o preço aparece no site
preco_display_intervalo boolean Exibe faixa de preço em vez de valor único
modo_preco string Modo de precificação
seguro_link string Link da apólice de seguro
seguro_label string Texto do botão de seguro
badge_sazonalidade string Selo de sazonalidade exibido no card
tags_categorias array Tags livres de categorização
import_source string Origem, quando importado de outro sistema
import_external_id string ID no sistema de origem
categorias array Categorias criadas junto com o passeio (apenas no POST). Cada item aceita nome, preco_venda, preco_custo, idade_min, idade_max, conta_como, ordem

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Passeio criado com sucesso",
    "data": {
        "id": 12,
        "nome": "Trilha da Pedra Bonita ao amanhecer",
        "slug": "trilha-pedra-bonita-amanhecer",
        "descricao_curta": "Subida guiada com vista para a Barra da Tijuca.",
        "local": "Parque Nacional da Tijuca",
        "cidade": "Rio de Janeiro",
        "estado": "RJ",
        "pais": "Brasil",
        "ponto_encontro": "Estacionamento da Pedra Bonita",
        "latitude": -22.9871234,
        "longitude": -43.2812345,
        "duracao_minutos": 180,
        "dificuldade": "moderado",
        "idade_minima": 12,
        "capacidade_maxima": 20,
        "antecedencia_minima_horas": 12,
        "cancelamento_horas": 24,
        "reembolso_percentual": 100,
        "exigir_waiver": true,
        "mostrar_site": true,
        "ativo": true,
        "status": "publicado",
        "categorias_count": 2,
        "horarios_count": 3,
        "extras_count": 1,
        "vendas_count": 47
    }
}

Atualização parcial: envie apenas os campos que quer mudar.

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Corpo da requisição

Campo Tipo Descrição
nome string Nome do passeio
slug string URL amigável. Gerado a partir do nome quando omitido. Único por tenant
descricao string Descrição completa (HTML permitido)
descricao_curta string Resumo usado em listagens e cards
o_que_inclui string O que está incluído no valor
o_que_nao_inclui string O que não está incluído
o_que_levar string Itens que o cliente deve levar
dicas string Dicas para o participante
requisitos string Requisitos de saúde, físicos ou documentais
local string Local do passeio
endereco string Endereço completo
cidade string Cidade
estado string UF (2 letras)
pais string País
continente string Continente
destino_slug string Slug do destino, para agrupar passeios da mesma região
ponto_encontro string Onde o grupo se encontra
ponto_encontro_maps string Link do Google Maps do ponto de encontro
latitude number Latitude (-90 a 90)
longitude number Longitude (-180 a 180)
imagem string URL da imagem de capa
videos array Lista de URLs de vídeo
duracao_minutos integer Duração em minutos
dificuldade string Nível de dificuldade (facil, moderado, dificil)
idade_minima integer Idade mínima permitida
capacidade_maxima integer Capacidade máxima por saída
categoria_tipo string Tipo do passeio (aventura, cultural, gastronomico...)
antecedencia_minima_horas integer Antecedência mínima para reservar
cancelamento_horas integer Prazo em horas para cancelar com reembolso
reembolso_percentual integer Percentual reembolsado dentro do prazo (0 a 100)
permitir_reagendamento boolean Permite remarcar a data
exigir_waiver boolean Exige termo de responsabilidade assinado
mostrar_site boolean Aparece no site público
ativo boolean Disponível para venda (default true)
destaque boolean Destacado nas listagens
status string rascunho ou publicado
banner_display_mode string Como a capa é exibida no site
meta_title string Título para SEO
meta_description string Descrição para SEO
meta_keywords string Palavras-chave para SEO
observacoes_internas string Notas internas, não exibidas ao cliente
preco_display_modo string Como o preço aparece no site
preco_display_intervalo boolean Exibe faixa de preço em vez de valor único
modo_preco string Modo de precificação
seguro_link string Link da apólice de seguro
seguro_label string Texto do botão de seguro
badge_sazonalidade string Selo de sazonalidade exibido no card
tags_categorias array Tags livres de categorização
import_source string Origem, quando importado de outro sistema
import_external_id string ID no sistema de origem
categorias array Categorias criadas junto com o passeio (apenas no POST). Cada item aceita nome, preco_venda, preco_custo, idade_min, idade_max, conta_como, ordem

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Passeio atualizado com sucesso",
    "data": {
        "id": 12,
        "nome": "Trilha da Pedra Bonita ao amanhecer",
        "slug": "trilha-pedra-bonita-amanhecer",
        "descricao_curta": "Subida guiada com vista para a Barra da Tijuca.",
        "local": "Parque Nacional da Tijuca",
        "cidade": "Rio de Janeiro",
        "estado": "RJ",
        "pais": "Brasil",
        "ponto_encontro": "Estacionamento da Pedra Bonita",
        "latitude": -22.9871234,
        "longitude": -43.2812345,
        "duracao_minutos": 180,
        "dificuldade": "moderado",
        "idade_minima": 12,
        "capacidade_maxima": 20,
        "antecedencia_minima_horas": 12,
        "cancelamento_horas": 24,
        "reembolso_percentual": 100,
        "exigir_waiver": true,
        "mostrar_site": true,
        "ativo": true,
        "status": "publicado",
        "categorias_count": 2,
        "horarios_count": 3,
        "extras_count": 1,
        "vendas_count": 47
    }
}

Atalho para mudar ativo, mostrar_site, destaque ou status sem enviar o cadastro inteiro.

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Corpo da requisição

Campo Tipo Descrição
ativo boolean Disponível para venda
mostrar_site boolean Aparece no site
destaque boolean Destacado
status string rascunho ou publicado

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Status atualizado"
}

Remove o passeio e seus sub-recursos. Bloqueado com 422 quando já há vendas registradas (PASSEIO_COM_VENDAS): nesse caso use ativo=false, que tira da venda sem apagar histórico.

Escopo necessário passeios:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Passeio removido com sucesso"
}

Tipos de bilhete do passeio (Adulto, Criança, Meia), com preço de custo e de venda.

Escopo necessário passeios:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 30,
            "passeio_id": 12,
            "nome": "Adulto",
            "descricao": "A partir de 12 anos",
            "preco_custo": 40,
            "preco_venda": 120,
            "idade_min": 12,
            "idade_max": null,
            "conta_como": "pessoa",
            "estoque_consome": 1,
            "ativo": true,
            "ordem": 0
        }
    ]
}

Tipos de bilhete do passeio (Adulto, Criança, Meia), com preço de custo e de venda.

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Corpo da requisição

Campo Tipo Descrição
nome * string Nome da categoria (Adulto, Criança, Meia...)
descricao string Detalhamento da regra
preco_venda * number Valor cobrado do cliente
preco_custo number Custo do fornecedor, usado no cálculo de lucro
idade_min integer Idade mínima
idade_max integer Idade máxima
conta_como string Como conta na capacidade (pessoa, meia, cortesia)
estoque_id integer Estoque compartilhado, quando houver
estoque_consome integer Quantas vagas cada unidade consome
ativo boolean Disponível para venda
ordem integer Ordem de exibição

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Categoria criada com sucesso",
    "data": {
        "id": 30,
        "passeio_id": 12,
        "nome": "Adulto",
        "descricao": "A partir de 12 anos",
        "preco_custo": 40,
        "preco_venda": 120,
        "idade_min": 12,
        "idade_max": null,
        "conta_como": "pessoa",
        "estoque_consome": 1,
        "ativo": true,
        "ordem": 0
    }
}

Atualização parcial: envie apenas os campos que quer mudar.

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio
categoriaId * integer path ID da categoria

Corpo da requisição

Campo Tipo Descrição
nome string Nome da categoria (Adulto, Criança, Meia...)
descricao string Detalhamento da regra
preco_venda number Valor cobrado do cliente
preco_custo number Custo do fornecedor, usado no cálculo de lucro
idade_min integer Idade mínima
idade_max integer Idade máxima
conta_como string Como conta na capacidade (pessoa, meia, cortesia)
estoque_id integer Estoque compartilhado, quando houver
estoque_consome integer Quantas vagas cada unidade consome
ativo boolean Disponível para venda
ordem integer Ordem de exibição

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Categoria atualizada com sucesso"
}

Bloqueado com 422 quando a categoria já tem vendas (RECURSO_EM_USO): nesse caso use ativo=false.

Escopo necessário passeios:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio
categoriaId * integer path ID da categoria

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Categoria removida com sucesso"
}

Grade de saídas: recorrente por dia da semana, diária ou em data específica.

Escopo necessário passeios:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 55,
            "passeio_id": 12,
            "tipo_recorrencia": "semanal",
            "dias_semana": [
                6,
                0
            ],
            "horario_inicio": "05:30",
            "horario_fim": "08:30",
            "vagas": 20,
            "ativo": true
        }
    ]
}

Grade de saídas: recorrente por dia da semana, diária ou em data específica.

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Corpo da requisição

Campo Tipo Descrição
tipo_recorrencia * string semanal, diario ou data_especifica
dias_semana array Dias da semana quando semanal (0=domingo a 6=sábado)
data_especifica date Data única quando tipo_recorrencia=data_especifica
horario_inicio * string Hora de início (HH:MM)
horario_fim string Hora de término (HH:MM)
vagas integer Vagas desta saída. Sem valor usa a capacidade do passeio
vigencia_inicio date A partir de quando a grade vale
vigencia_fim date Até quando a grade vale
ativo boolean Horário ativo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Horário criada com sucesso",
    "data": {
        "id": 55,
        "passeio_id": 12,
        "tipo_recorrencia": "semanal",
        "dias_semana": [
            6,
            0
        ],
        "horario_inicio": "05:30",
        "horario_fim": "08:30",
        "vagas": 20,
        "ativo": true
    }
}

Atualização parcial: envie apenas os campos que quer mudar.

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio
horarioId * integer path ID da horario

Corpo da requisição

Campo Tipo Descrição
tipo_recorrencia string semanal, diario ou data_especifica
dias_semana array Dias da semana quando semanal (0=domingo a 6=sábado)
data_especifica date Data única quando tipo_recorrencia=data_especifica
horario_inicio string Hora de início (HH:MM)
horario_fim string Hora de término (HH:MM)
vagas integer Vagas desta saída. Sem valor usa a capacidade do passeio
vigencia_inicio date A partir de quando a grade vale
vigencia_fim date Até quando a grade vale
ativo boolean Horário ativo

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Horário atualizada com sucesso"
}

Remove o registro.

Escopo necessário passeios:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio
horarioId * integer path ID da horario

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Horário removida com sucesso"
}

Itens opcionais vendidos junto com o passeio.

Escopo necessário passeios:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 8,
            "passeio_id": 12,
            "nome": "Transfer hotel",
            "preco": 30,
            "tipo_cobranca": "por_pessoa",
            "quantidade_maxima": 4,
            "ativo": true,
            "ordem": 0
        }
    ]
}

Itens opcionais vendidos junto com o passeio.

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Corpo da requisição

Campo Tipo Descrição
nome * string Nome do item opcional (transfer, almoço, foto)
descricao string Detalhamento
preco * number Valor do extra
tipo_cobranca string por_pessoa ou por_reserva
quantidade_maxima integer Limite por reserva
ativo boolean Disponível
ordem integer Ordem de exibição

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Extra criada com sucesso",
    "data": {
        "id": 8,
        "passeio_id": 12,
        "nome": "Transfer hotel",
        "preco": 30,
        "tipo_cobranca": "por_pessoa",
        "quantidade_maxima": 4,
        "ativo": true,
        "ordem": 0
    }
}

Atualização parcial: envie apenas os campos que quer mudar.

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio
extraId * integer path ID da extra

Corpo da requisição

Campo Tipo Descrição
nome string Nome do item opcional (transfer, almoço, foto)
descricao string Detalhamento
preco number Valor do extra
tipo_cobranca string por_pessoa ou por_reserva
quantidade_maxima integer Limite por reserva
ativo boolean Disponível
ordem integer Ordem de exibição

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Extra atualizada com sucesso"
}

Remove o registro.

Escopo necessário passeios:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio
extraId * integer path ID da extra

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Extra removida com sucesso"
}

Ajuste de preço por período. Quando dois períodos se sobrepõem, vence a maior prioridade.

Escopo necessário passeios:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 3,
            "passeio_id": 12,
            "nome": "Alta temporada",
            "data_inicio": "2026-12-20",
            "data_fim": "2027-01-31",
            "tipo_ajuste": "percentual",
            "valor_ajuste": 20,
            "prioridade": 1,
            "ativo": true
        }
    ]
}

Ajuste de preço por período. Quando dois períodos se sobrepõem, vence a maior prioridade.

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Corpo da requisição

Campo Tipo Descrição
nome * string Nome do período (Alta temporada, Feriado)
data_inicio * date Início do período
data_fim * date Fim do período
tipo_ajuste * string percentual, valor_fixo ou preco_fixo
valor_ajuste * number Valor do ajuste conforme o tipo
prioridade integer Quando dois períodos se sobrepõem, vence a maior prioridade
ativo boolean Temporada ativa

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Temporada criada com sucesso",
    "data": {
        "id": 3,
        "passeio_id": 12,
        "nome": "Alta temporada",
        "data_inicio": "2026-12-20",
        "data_fim": "2027-01-31",
        "tipo_ajuste": "percentual",
        "valor_ajuste": 20,
        "prioridade": 1,
        "ativo": true
    }
}

Atualização parcial: envie apenas os campos que quer mudar.

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio
temporadaId * integer path ID da temporada

Corpo da requisição

Campo Tipo Descrição
nome string Nome do período (Alta temporada, Feriado)
data_inicio date Início do período
data_fim date Fim do período
tipo_ajuste string percentual, valor_fixo ou preco_fixo
valor_ajuste number Valor do ajuste conforme o tipo
prioridade integer Quando dois períodos se sobrepõem, vence a maior prioridade
ativo boolean Temporada ativa

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Temporada atualizada com sucesso"
}

Remove o registro.

Escopo necessário passeios:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio
temporadaId * integer path ID da temporada

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Temporada removida com sucesso"
}

Galeria do passeio, na ordem de exibição.

Escopo necessário passeios:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 71,
            "passeio_id": 12,
            "url": "https:\/\/cdn.exemplo.com\/foto.jpg",
            "titulo": "Vista do topo",
            "ordem": 0
        }
    ]
}

Adiciona uma foto por URL. O arquivo deve estar hospedado pelo integrador.

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio

Corpo da requisição

Campo Tipo Descrição
url * string URL da imagem
thumbnail_url string URL da miniatura
titulo string Título da foto
descricao string Legenda
ordem integer Ordem de exibição

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Foto criada com sucesso"
}

Remove a foto da galeria.

Escopo necessário passeios:delete

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do passeio
fotoId * integer path ID da foto

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Foto removida com sucesso"
}

Lista paginada das vendas, com passeio, categoria, cliente e a contagem de itens do voucher.

Escopo necessário passeios:read

Parâmetros

Nome Tipo Local Descrição
page integer query Número da página
per_page integer query Itens por página (max: 100)
passeio_id integer query Filtra por passeio
cliente_id integer query Filtra por cliente
sessao_id integer query Filtra por sessão
status string query reservado, confirmado, usado ou cancelado
checked_in boolean query Somente com ou sem check-in
origem string query Canal da venda
codigo_voucher string query Código do voucher da venda (case-insensitive)
data_de date query Data inicial da sessão
data_ate date query Data final da sessão
search string query Busca por nome ou documento do beneficiário

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 508,
            "uuid": "3f1c0a2e-8b4d-4f6a-9c11-2d7e5a9b0c33",
            "passeio_id": 12,
            "categoria_id": 30,
            "cliente_id": 91,
            "beneficiario_nome": "Marina Torres",
            "beneficiario_documento": "123.456.789-00",
            "quantidade": 2,
            "valor_unitario": 120,
            "valor_extras": 30,
            "desconto": 0,
            "valor_total": 270,
            "status": "confirmado",
            "codigo_voucher": "K7PJ4RQ2",
            "checked_in": false,
            "origem": "api",
            "voucher_items_count": 2
        }
    ]
}

Retorna a venda com os itens do voucher, os pagamentos e os check-ins.

Escopo necessário passeios:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da venda

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 508,
        "uuid": "3f1c0a2e-8b4d-4f6a-9c11-2d7e5a9b0c33",
        "passeio_id": 12,
        "categoria_id": 30,
        "cliente_id": 91,
        "beneficiario_nome": "Marina Torres",
        "beneficiario_documento": "123.456.789-00",
        "quantidade": 2,
        "valor_unitario": 120,
        "valor_extras": 30,
        "desconto": 0,
        "valor_total": 270,
        "status": "confirmado",
        "codigo_voucher": "K7PJ4RQ2",
        "checked_in": false,
        "origem": "api",
        "voucher_items_count": 2,
        "voucher_items": [
            {
                "id": 1044,
                "passeio_venda_id": 508,
                "categoria_nome": "Adulto",
                "numero_item": 1,
                "codigo_qrcode": "K7PJ4RQ2-01",
                "beneficiario_nome": "Marina Torres",
                "status": "valido",
                "usado_em": null
            }
        ]
    }
}

Registra uma venda e gera o código do voucher. Sem valor_unitario, usa o preco_venda da categoria, para o integrador não precisar replicar a tabela de preços. Recusa com 422 quando a categoria não pertence ao passeio (CATEGORIA_DE_OUTRO_PASSEIO) ou quando o desconto deixa o total negativo (TOTAL_NEGATIVO).

Escopo necessário passeios:write

Corpo da requisição

Campo Tipo Descrição
passeio_id * integer ID do passeio
categoria_id * integer ID da categoria. Precisa pertencer ao passeio informado
sessao_id integer Sessão (data e hora) escolhida
cliente_id integer Cliente cadastrado, quando houver
beneficiario_nome * string Nome de quem vai fazer o passeio
beneficiario_documento string CPF ou documento
beneficiario_telefone string Telefone de contato
quantidade * integer Quantidade de pessoas. Gera um item de voucher para cada
valor_unitario number Valor por pessoa. Sem valor, usa o preco_venda da categoria
valor_custo number Custo por pessoa. Sem valor, usa o preco_custo da categoria
valor_extras number Soma dos extras
extras array Extras escolhidos
desconto number Desconto aplicado
desconto_motivo string Motivo do desconto
acrescimo number Acréscimo aplicado
acrescimo_motivo string Motivo do acréscimo
status string reservado (default), confirmado, usado ou cancelado
origem string Canal da venda. Default: api
campos_customizados object Campos livres do integrador

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Venda registrada com sucesso",
    "data": {
        "id": 508,
        "uuid": "3f1c0a2e-8b4d-4f6a-9c11-2d7e5a9b0c33",
        "passeio_id": 12,
        "categoria_id": 30,
        "cliente_id": 91,
        "beneficiario_nome": "Marina Torres",
        "beneficiario_documento": "123.456.789-00",
        "quantidade": 2,
        "valor_unitario": 120,
        "valor_extras": 30,
        "desconto": 0,
        "valor_total": 270,
        "status": "confirmado",
        "codigo_voucher": "K7PJ4RQ2",
        "checked_in": false,
        "origem": "api",
        "voucher_items_count": 2
    }
}

Atualiza dados do beneficiário, extras e valores. Não muda status: use o endpoint próprio. Venda cancelada não pode ser editada (VENDA_CANCELADA).

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da venda

Corpo da requisição

Campo Tipo Descrição
beneficiario_nome string Nome de quem vai fazer o passeio
beneficiario_documento string CPF ou documento
beneficiario_telefone string Telefone
sessao_id integer Trocar a sessão (reagendamento)
extras array Extras escolhidos
valor_extras number Soma dos extras
desconto number Desconto
desconto_motivo string Motivo do desconto
acrescimo number Acréscimo
acrescimo_motivo string Motivo do acréscimo
campos_customizados object Campos livres do integrador

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Venda atualizada com sucesso"
}

Não existe DELETE de venda: cancelar preserva voucher e financeiro. Ao cancelar, motivo_cancelamento é obrigatório e a data é carimbada.

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da venda

Corpo da requisição

Campo Tipo Descrição
status * string reservado, confirmado, usado ou cancelado
motivo_cancelamento string Obrigatório quando status=cancelado

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Status atualizado"
}

Pagamentos lançados nesta venda.

Escopo necessário passeios:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da venda

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 91,
            "passeio_venda_id": 508,
            "valor": 270,
            "forma": "pix",
            "data_pagamento": "2026-08-05"
        }
    ]
}

Lança um pagamento na venda.

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da venda

Corpo da requisição

Campo Tipo Descrição
valor * number Valor pago
forma * string Forma de pagamento (pix, dinheiro, cartao...)
data_pagamento date Data do pagamento. Default: agora
observacao string Observação

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Pagamento registrado"
}

O voucher tem UM item por pessoa, cada um com seu QR code. Uma venda de 4 pessoas gera 4 itens, e o check-in pode ser individual.

Escopo necessário passeios:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da venda

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "venda_id": 508,
        "codigo_voucher": "K7PJ4RQ2",
        "quantidade": 2,
        "itens": [
            {
                "id": 1044,
                "passeio_venda_id": 508,
                "categoria_nome": "Adulto",
                "numero_item": 1,
                "codigo_qrcode": "K7PJ4RQ2-01",
                "beneficiario_nome": "Marina Torres",
                "status": "valido",
                "usado_em": null
            }
        ]
    }
}

Usado na portaria. Procura primeiro pelo código do ITEM (o que está no QR de cada pessoa) e, se não achar, pelo código da venda. Busca case-insensitive, porque leitor de QR devolve em caixa variada. O campo "tipo" na resposta diz qual dos dois foi encontrado.

Escopo necessário passeios:read

Parâmetros

Nome Tipo Local Descrição
codigo * string path Código do item do voucher ou da venda

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "tipo": "item",
        "item": {
            "id": 1044,
            "passeio_venda_id": 508,
            "categoria_nome": "Adulto",
            "numero_item": 1,
            "codigo_qrcode": "K7PJ4RQ2-01",
            "beneficiario_nome": "Marina Torres",
            "status": "valido",
            "usado_em": null
        }
    }
}

Sem voucher_item_id, marca a venda inteira. Com ele, marca só aquela pessoa, que é o caso de grupo chegando em horários diferentes. A venda só passa para "usado" quando não resta item pendente. Recusa item já usado (ITEM_JA_USADO), item de outra venda (ITEM_DE_OUTRA_VENDA) e venda cancelada (VENDA_CANCELADA).

Escopo necessário passeios:write

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da venda

Corpo da requisição

Campo Tipo Descrição
voucher_item_id integer Item do voucher, para check-in individual
latitude number Latitude de onde o check-in foi feito
longitude number Longitude
guia_id integer Guia que registrou
registrado_por_nome string Nome de quem registrou
metodo string Método (qrcode, manual, api)
dispositivo string Identificação do aparelho

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Check-in registrado"
}

Histórico de check-ins, do mais recente para o mais antigo.

Escopo necessário passeios:read

Parâmetros

Nome Tipo Local Descrição
id * integer path ID da venda

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 22,
            "venda_id": 508,
            "data_hora": "2026-08-06T05:32:00-03:00",
            "metodo": "qrcode"
        }
    ]
}

Webhooks

Cadastro e gestão de webhooks. Eventos chegam via POST com envelope padronizado (event, event_id UUID, created_at ISO 8601, data) + assinatura HMAC-SHA256 no header X-Viagilize-Signature.

Retorna todos os eventos que podem ser inscritos, agrupados por categoria (reservas, pagamentos, clientes, excursoes, contratos, checkin).

Escopo necessário webhooks:manage

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "groups": {
            "reservas": {
                "label": "Reservas",
                "events": {
                    "reserva.criada": "Nova reserva criada",
                    "reserva.confirmada": "Reserva confirmada (pagamento OK)",
                    "reserva.cancelada": "Reserva cancelada",
                    "reserva.expirada": "Reserva expirada por falta de pagamento",
                    "vaga_pendente.preenchida": "Vaga pendente preenchida (convidado\/comprador completou dados)"
                }
            },
            "pagamentos": {
                "label": "Pagamentos",
                "events": {
                    "pagamento.criado": "Novo pagamento registrado",
                    "pagamento.confirmado": "Pagamento confirmado",
                    "pagamento.estornado": "Pagamento estornado"
                }
            },
            "contratos": {
                "label": "Contratos",
                "events": {
                    "contrato.assinado": "Contrato assinado pelo cliente"
                }
            }
        }
    }
}

Lista paginada de webhooks cadastrados.

Escopo necessário webhooks:manage

Parâmetros

Nome Tipo Local Descrição
page integer query Página
per_page integer query Itens (max 100)

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": [
        {
            "id": 1,
            "name": "Integração Kommo CRM",
            "url": "https:\/\/meusistema.com.br\/webhooks\/viagilize",
            "events": [
                "reserva.criada",
                "reserva.confirmada",
                "pagamento.confirmado"
            ],
            "is_active": true,
            "last_triggered_at": "2026-04-25T17:30:11-03:00",
            "last_status": "success",
            "failure_count": 0,
            "created_at": "2026-04-20T10:00:00-03:00"
        }
    ],
    "meta": {
        "current_page": 1,
        "per_page": 20,
        "total": 1
    }
}

Retorna dados de um webhook (sem expor o secret).

Escopo necessário webhooks:manage

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do webhook

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "id": 1,
        "name": "Integração Kommo CRM",
        "url": "https:\/\/meusistema.com.br\/webhooks\/viagilize",
        "events": [
            "reserva.criada",
            "reserva.confirmada",
            "pagamento.confirmado"
        ],
        "is_active": true,
        "last_triggered_at": "2026-04-25T17:30:11-03:00",
        "last_status": "success",
        "failure_count": 0,
        "created_at": "2026-04-20T10:00:00-03:00"
    }
}

Cadastra um webhook. Retorna o secret UMA UNICA VEZ — guarde com seguranca para validar HMAC nas entregas.

Escopo necessário webhooks:manage

Corpo da requisição

Campo Tipo Descrição
name * string Nome para identificar o webhook
url * string URL HTTPS que recebera os eventos
events * array Lista de eventos para inscrever (ex: ["reserva.criada", "pagamento.confirmado"])

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Webhook criado. Guarde o secret — ele nao sera exibido novamente.",
    "data": {
        "webhook": {
            "id": 1,
            "name": "Integração Kommo CRM",
            "url": "https:\/\/meusistema.com.br\/webhooks\/viagilize",
            "events": [
                "reserva.criada",
                "reserva.confirmada",
                "pagamento.confirmado"
            ],
            "is_active": true,
            "last_triggered_at": "2026-04-25T17:30:11-03:00",
            "last_status": "success",
            "failure_count": 0,
            "created_at": "2026-04-20T10:00:00-03:00"
        },
        "secret": "whsec_aBcDeFgHiJkLmNoPqRsTuVwXyZ012345"
    }
}

Atualiza nome, url, lista de eventos ou flag is_active.

Escopo necessário webhooks:manage

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do webhook

Corpo da requisição

Campo Tipo Descrição
name string Novo nome
url string Nova URL
events array Nova lista de eventos
is_active boolean Ativa/desativa o webhook

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Webhook atualizado.",
    "data": {
        "id": 1,
        "name": "Integração Kommo CRM",
        "url": "https:\/\/meusistema.com.br\/webhooks\/viagilize",
        "events": [
            "reserva.criada",
            "reserva.confirmada",
            "pagamento.confirmado"
        ],
        "is_active": true,
        "last_triggered_at": "2026-04-25T17:30:11-03:00",
        "last_status": "success",
        "failure_count": 0,
        "created_at": "2026-04-20T10:00:00-03:00"
    }
}

Remove definitivamente o webhook. Entregas em fila para esse webhook deixam de ser processadas.

Escopo necessário webhooks:manage

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do webhook

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Webhook removido."
}

Gera um novo secret para o webhook. Invalida HMAC de qualquer entrega futura usando o secret antigo. Atualize seu receiver imediatamente.

Escopo necessário webhooks:manage

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do webhook

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "message": "Secret regenerado.",
    "data": {
        "secret": "whsec_novoSecretGerado12345abcdef67890"
    }
}

Envia um evento test.ping para a URL configurada. Útil para validar que o receiver está respondendo corretamente.

Escopo necessário webhooks:manage

Parâmetros

Nome Tipo Local Descrição
id * integer path ID do webhook

Resposta de exemplo

JSON
200 OK
{
    "success": true,
    "data": {
        "success": true,
        "status": "success",
        "response_code": 200,
        "response_time_ms": 245,
        "error_message": null
    }
}

Webhooks (Recebimento)

Como receber e validar eventos enviados pelo Viagilize

Envelope padronizado

Todo evento entregue tem o mesmo formato — apenas o conteudo de data varia por tipo.

{
  "event": "reserva.criada",
  "event_id": "5b3a0e2c-3d6f-4e6a-9b2a-7e9d1c2f3a4b",
  "created_at": "2026-04-25T18:30:42-03:00",
  "data": { ... }
}

Headers HTTP

Content-Type: application/json
X-Viagilize-Signature: sha256=<hmac_hex>
X-Viagilize-Event: reserva.criada
User-Agent: Viagilize-Webhook/1.0

Validação HMAC (PHP)

A assinatura é HMAC-SHA256 do corpo bruto usando o secret do webhook. Sempre use comparação timing-safe.

$rawBody = $request->getContent();
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
if (!hash_equals($expected, $request->header('X-Viagilize-Signature'))) {
    abort(401);
}

Idempotência (event_id)

O event_id é UUID v4. Em retries (após 5xx ou timeout), o mesmo id reaparece — guarde-o e dedupe do seu lado antes de processar.

Retry e Backoff

  • Máximo de tentativas: 3
  • Backoff: 10s, 30s, 60s
  • Timeout HTTP: 10s por tentativa
  • Sucesso: qualquer 2xx; falha: não-2xx ou timeout
  • Após 10 falhas consecutivas o webhook é desativado automaticamente

Eventos disponíveis

Schema completo de cada payload em /docs/API-WEBHOOKS-PAYLOADS.md.

reserva.criada reserva.confirmada reserva.cancelada reserva.expirada pagamento.criado pagamento.confirmado pagamento.estornado cliente.criado excursao.publicada excursao.cancelada contrato.assinado checkin.realizado checkout.realizado

Códigos de Erro

Tratamento de erros da API

400

Bad Request

A requisição contém dados inválidos ou mal formatados.

401

Unauthorized

Token de autenticação ausente ou inválido.

403

Forbidden

Token não possui permissão (scope) para esta ação.

404

Not Found

Recurso não encontrado.

422

Unprocessable Entity

Erro de validação nos dados enviados.

429

Too Many Requests

Limite de requisições excedido. Aguarde antes de tentar novamente.

500

Internal Server Error

Erro interno do servidor. Entre em contato com o suporte.

Formato de erro

{
  "success": false,
  "message": "Descrição do erro",
  "errors": {
    "campo": ["Mensagem de validação"]
  }
}

Rate Limiting

Limites de requisições

Para garantir a estabilidade do serviço, a API limita o volume de requisições:

300 requisições por minuto
por token de API

Ao exceder o limite:

  • A API responde HTTP 429 (Too Many Requests).
  • O header Retry-After informa em quantos segundos tentar de novo.

Em toda resposta, acompanhe seu consumo pelos headers X-RateLimit-Limit e X-RateLimit-Remaining. Na resposta 429 também vêm Retry-After e X-RateLimit-Reset.