API DOCS

Innprices

Resumo do payload e regras de precificacao.

Endpoint

POST /omnibees/:id

POST /hbook/:id

Base URL: https://prices.innsights.com.br

O service recebe um provider do tipo HotelPriceProvider; por padrao usa Omnibees.

O endpoint /hbook/:id usa o provider Hbook e envia um POST para /Booking/GetAvailability.

O controller do Hbook segue o mesmo fluxo do Omnibees, trocando apenas o provider.

A implementacao do controller do Hbook replica o do Omnibees, mudando somente o provider injetado.

No provider Omnibees, a URL de consulta e o fetch sao executados dentro de getData no crawler.

Cada provider implementa buildBookingUrl e define urlField, o nome do campo em que a URL do motor aparece na resposta (Omnibees usa omnibeesUrl; Hbook usa url).

O service repassa buildBookingUrl e urlField do provider ao response builder; se a geracao da URL falhar, o campo retorna vazio.

Token obrigatorio via query string: ?token={{secreto}}

Token invalido retorna status 401.

Body esperado

{
  "checkin": "2025-12-15T03:15:00.000Z",
  "checkout": "2025-12-18T03:00:00.000Z",
  "adults": 1,
  "childrens": 0,
  "ages": "",
  "code": "",
  "template": [
    "*PARA:* {{adults}} adulto(s)",
    "Periodo: {{checkin|date}} a {{checkout|date}}"
  ],
  "order": {
    "nameList": ["Suite Luxo", "Suite premium"],
    "rateNameList": ["Tarifa VIP", "Tarifa Flex"],
    "ratePrice": "asc"
  },
  "filters": {
    "roomName": "Suite Luxo"
  },
  "rules": {
    "baseline": "price",
    "markup": { "value": 10 },
    "discount": { "value": 10, "category": "discount" },
    "bookingWindow": {
      "window": 21,
      "less": { "midweek": 20, "weekend": 25 },
      "more": 25,
      "category": "discount"
    },
    "installment": { "times": 4, "withEntry": true, "entryPercent": 30 }
  }
}

Campos

Order (Strategy)

O order define como a lista de quartos e ordenada antes de escolher o primeiro item. Ele segue o mesmo padrao Strategy das regras.

A aplicacao de order e filters e feita no service, antes de selecionar o quarto retornado pelo crawler.

nameList

Lista de nomes em ordem de prioridade. O primeiro nome encontrado vira o resultado. Qualquer nome fora da lista fica depois, mantendo a ordem original.

"order": {
  "nameList": ["Suite Luxo", "Suite premium", "Standard"]
}

rateNameList

Lista de nomes de tarifas em ordem de prioridade. Reordena o campo rates dentro de cada quarto e usa a primeira tarifa como base do preco.

"order": {
  "rateNameList": ["Tarifa VIP", "Tarifa Flex", "Tarifa Standard"]
}

ratePrice

Ordena as tarifas por preco dentro de cada quarto e usa a primeira tarifa como base. Valores: "asc" (menor preco) ou "desc" (maior preco).

"order": {
  "ratePrice": "desc"
}

price

Ordena por preco quando nameList nao e informado. Valores: "asc" ou "desc".

A ordenacao por preco usa o valor selecionado das tarifas; se nenhuma regra de tarifa for aplicada, o preco pode ficar nulo e a ordem original e mantida.

"order": {
  "price": "asc"
}

Filters

Os filtros sao aplicados apos o order e antes das regras. Se nenhum quarto atender ao filtro, retorna room_unavailable.

roomName

Filtra pelo nome exato do quarto retornado pela Omnibees.

Se vazio, o filtro nao e aplicado.

"filters": {
  "roomName": "Suite Luxo"
}

Rules (Strategy)

As regras sao aplicadas no retorno do crawler via Strategy. Cada regra transforma o item (nome e preco) e retorna o mesmo item ajustado.

O campo comments e normalizado para um array antes de adicionar novas mensagens de regras.

Regras de desconto nao se somam: cada nova regra sobrescreve o finalPrice gerado pela anterior.

baseline

Escolhe sobre qual preco as regras vao operar: "finalPrice" (padrao) ou "price". Omitir o campo mantem exatamente o comportamento de sempre.

O motor de reservas pode devolver o finalPrice ja com uma oferta propria aplicada sobre o rack. No Hbook ela vem de AppliedOffer.OfferName: por exemplo price 985.71, finalPrice 837.8535 e discount 15. Como as regras partem do finalPrice, um rate de -30 cascateia sobre essa oferta e entrega 40,5% efetivos sobre a tarifa OTA (15% + 0.85 * 30% = 586.50), e nao os 30% pedidos.

Com "baseline": "price" a oferta do motor e descartada antes de qualquer regra rodar (finalPrice = price) e toda a cadeia (rate, markup, discount, bookingWindow, installment) passa a operar a partir do rack. No exemplo acima, -30 resulta em 690.00.

O percentual original nao se perde: vai para o campo engineDiscount da resposta. O discount e limpo no reset — ele descrevia uma oferta que nao corresponde mais ao finalPrice — e as regras seguintes voltam a preenche-lo normalmente. Um comment registra o descarte: engine offer 15% discarded (baseline=price). Quando o motor nao trouxe oferta alguma o reset e inocuo: nao gera comment nem engineDiscount.

Nao e ignorado quando code e informado: e selecao de base de calculo, nao uma concessao comercial — mesmo racional do rate.

O reset e condicional

O reset so acontece quando alguma regra seguinte de fato vai ajustar o finalPrice. Cotar a tarifa cheia serve para aplicar um desconto negociado sobre ela; sem desconto nenhum para conceder, devolver o hospede ao rack seria tirar a oferta publica do motor sem contrapartida. Quando nenhuma regra ajusta o preco, baseline vira no-op total: a resposta fica identica a de uma requisicao sem o campo — sem comment e sem engineDiscount.

Contam como ajuste de preco:

Nao contam: markup, que altera o price e nao o finalPrice, e installment, que apenas parcela o valor que ja existe.

Com rack 985.71 e oferta de 15% do motor (finalPrice 837.8535):

rules finalPrice Reset
{ "baseline": "price" } 837.8535 Nao
+ "rate": { "value": "" } 837.8535 Nao
+ "rate": { "value": 0 } 837.8535 Nao
+ "rate": { "value": -30 } 690.00 Sim
+ "discount": { "value": 30 } 690.00 Sim
+ "discount": { "value": 30 } com code informado 837.8535 Nao (regra ignorada)
+ "markup": { "value": 10 } 837.8535 Nao
+ "installment": { "times": 3 } 837.8535 Nao
"rules": {
  "baseline": "price",
  "rate": { "value": -30 }
}

rate

Aplica o tipo de tarifa sobre o preco final. Formula: finalPrice = finalPrice * (1 + valor/100). Valor negativo reduz: -25 => multiplica por 0.75. O rack permanece intacto em price — a resposta traz "De price por finalPrice" — e o ajuste nao preenche o campo discount.

Roda antes das outras regras — so a selecao de baseline vem antes — e nao e ignorada quando code e informado: e o tipo de tarifa, nao uma concessao. Um discount aplicado depois compoe sobre o valor ja tarifado (25% de tarifa + 10% de desconto = 32,5% sobre o rack, nao 35%).

Valores 0 ou menores/iguais a -100 sao ignorados.

"rules": {
  "rate": { "value": -25 },
  "discount": { "value": 10 }
}

defaultValue

rate.defaultValue e opcional e entra em cena quando value nao traz numero algum para ler — string vazia ("", o que chega quando o campo do contato esta em branco), so espacos ou texto nao numerico. Nesses casos a regra tarifa pelo padrao em vez de virar no-op. Aceita numero ou string numerica, igual ao value.

0 (ou "0") nao aciona o padrao: zero e escolha explicita de "sem desconto", nao ausencia de valor. Se defaultValue tambem nao for legivel, a regra segue no-op como antes.

O percentual do padrao e resolvido antes de tudo, entao ele tambem conta como ajuste de preco para o baseline: "value": "" com "defaultValue": -20 reseta a base e cota os 20% sobre o rack. Quando o padrao e usado, o comment sai como rate: -20% (defaultValue), distinguindo do rate: -20% pedido explicitamente.

"rules": {
  "baseline": "price",
  "rate": { "value": "", "defaultValue": -20 }
}
value defaultValue Percentual aplicado
-25 -15 -25% (o pedido vence)
"" -15 -15% (padrao)
"abc" -15 -15% (padrao)
0 -15 nenhum — zero e explicito
"" ausente nenhum — no-op
"" "" nenhum — no-op

markup

Corrige o preco base usando markup. Formula: preco_corrigido = preco / (1 - percentual/100). Exemplo: 10% => divide por 0.90.

Quando markup e aplicado, o campo discount retorna o mesmo percentual para facilitar templates que exibem desconto.

"rules": {
  "markup": { "value": 10 }
}

discount

rules.discount.value e um percentual (ex.: 10 = 10%). O desconto e aplicado diretamente no finalPrice de cada item.

Categoria: discount. Quando code e informado, regras com essa categoria nao sao aplicadas.

bookingWindow

Aplica desconto com base na antecedencia entre hoje e o check-in. Usa window para decidir entre less e more.

less aplica quando dias_antecedencia <= window. more aplica quando dias_antecedencia > window. Os valores podem ser numero (percentual fixo) ou objeto { midweek, weekend }.

Weekend padrao: qui, sex, sab (o resto e midweek). O campo opcional weekendDays reescreve essa definicao com nomes de dias em ingles; qualquer dia fora da lista conta como midweek. O campo period da resposta segue a mesma definicao.

"rules": {
  "bookingWindow": {
    "window": 21,
    "less": { "midweek": 25, "weekend": 20 },
    "more": 25,
    "weekendDays": ["friday", "saturday", "sunday"]
  }
}

Categoria: discount. Quando code e informado, regras com essa categoria nao sao aplicadas.

installment

Divide o valor final em parcelas. Quando withEntry e verdadeiro, calcula entrada com base no percentual e parcela o restante.

"rules": {
  "installment": { "times": 4, "withEntry": true, "entryPercent": 30 }
}

Code

Quando code e informado, regras com category igual a discount nao sao aplicadas.

Codigos no formato WEB## (ex.: WEB05) retornam o percentual no campo discount.

Para os demais codigos o campo discount vem da diferenca entre price e finalPrice — o desconto que o motor de reservas de fato concedeu. Quando essa diferenca e zero (ex.: a tarifa nao tem oferta do motor e a regra discount foi ignorada pelo code), a resposta traz discount: 0 em vez do percentual da regra que nao rodou.

Erros

Template (Message)

O campo template permite montar um texto usando as variaveis do resultado. Use {{'{{'}}campo{{'}}'}} para interpolar valores.

Aceita string unica ou array de strings. Quando for array, o retorno inclui message_1, message_2 e assim por diante.

*PARA:* {{adults}} adulto(s){{childrens|if: e {{childrens}} crianca(s) com idades {{ages}}:}}
*PERIODO:* {{checkin|date}} a {{checkout|date}}

*Check-in:* A partir das 16h
*Check-out:* Ate as 14h

*Acomodacao:* _{{name}}_ - {{finalPrice|currency}}

*Forma de pagamento:*
Sinal de {{entryValue|currency}} via Pix no ato da reserva;
Saldo restante em ate {{times}}x de {{installment|currency}} sem juros no check-in.

*Tarifa valida somente ate as 23h59 de hoje!*

Filtros disponiveis:

Campos disponiveis no template:

Campo Descricao Quando aparece
name Nome da acomodacao. Sempre, quando ha resultado.
price Preco original (sem desconto). Sempre, quando ha resultado.
finalPrice Preco final apos regras. Sempre, quando ha resultado.
discount Percentual aplicado (discount/bookingWindow/markup) ou code (ex.: WEB05). Quando alguma regra alterar o preco.
engineDiscount Percentual da oferta do motor de reservas descartada por rules.baseline: "price". Somente quando o motor trouxe oferta, o baseline e price e alguma regra seguinte ajusta o finalPrice.
checkin Data de check-in (ISO). Sempre (input).
period Periodo calculado pelo dia do check-in (midweek ou weekend). Sempre (gerado).
checkout Data de check-out (ISO). Sempre (input).
adults Numero de adultos. Sempre (input).
childrens Numero de criancas. Sempre (input).
ages Idades das criancas (texto). Sempre (input).
code Codigo promocional enviado para a Omnibees. Somente quando informado.
rules Objeto com regras recebidas. Sempre (input).
template Texto original do template. Sempre (input).
omnibeesUrl URL final gerada pelo buildBookingUrl do provider Omnibees (urlField = omnibeesUrl); pode ficar vazia quando a geracao da URL falhar. Nas respostas do provider Omnibees.
url URL final gerada pelo buildBookingUrl do provider Hbook (urlField = url). Nas respostas do provider Hbook.
comments Lista de aplicacoes de regras. Inclui "promotional code is applied" quando code e informado no service. Quando uma regra for ignorada, inclui o motivo em texto. Quando alguma regra rodar ou for ignorada.
entryValue Valor da entrada. Somente com regra installment e withEntry.
entryPercent Percentual de entrada. Somente com regra installment e withEntry.
remaining Valor restante apos a entrada. Somente com regra installment.
installment Valor de cada parcela. Somente com regra installment.
times Quantidade de parcelas. Somente com regra installment.

Exemplo completo

Request

{
  "checkin": "2026-01-17T03:15:00.000Z",
  "checkout": "2026-01-18T03:00:00.000Z",
  "adults": 2,
  "childrens": 0,
  "ages": "",
  "code": "",
  "rules": {
    "discount": { "value": 50, "category": "discount" },
    "installment": { "times": 4, "withEntry": true, "entryPercent": 30 }
  },
  "template": [
    "*🏨 PARA:* {{adults}} adulto(s){{childrens|if: e {{childrens}} criança(s) com idades {{ages}}:}}\n📅 *PERÍODO:* {{checkin|date}} a {{checkout|date}}\n\n*Check-in:* A partir das 16h\n*Check-out:* Até as 14h\n\n*Acomodação:* _{{name}}_ - {{finalPrice|currency}}\n\n*💳 Forma de pagamento:*\nSinal de {{entryValue|currency}} via Pix no ato da reserva;\nSaldo restante em até {{times}}x de {{installment|currency}} sem juros no check-in.\n\n*⏳ Tarifa válida somente até as 23h59 de hoje!*",
    "Estamos concedendo *{{discount}}% de desconto* e sua reserva sai de {{price|currency}} por apenas *{{finalPrice|currency}}*.\n\nSinal de {{entryPercent}}% no valor de {{entryValue|currency}} e o restante parcelado em {{times}}x de {{installment|currency}} pagos no check-in.\n\n*Oferta exclusiva para fechamento hoje!*"
  ]
}

Response

{
  "status": "available",
  "name": "Superior Casal",
  "price": 687,
  "finalPrice": 343.5,
  "comments": [
    "discount: 50%",
    "installment: entry 30% + 4x 60.11"
  ],
  "entryValue": 103.05,
  "entryPercent": 30,
  "remaining": 240.45,
  "installment": 60.11,
  "times": 4,
  "discount": 50,
  "id": "6605",
  "checkin": "2026-01-17T03:15:00.000Z",
  "period": "weekend",
  "checkout": "2026-01-18T03:00:00.000Z",
  "adults": 2,
  "childrens": 0,
  "ages": "",
  "code": "",
  "omnibeesUrl": "https://book.omnibees.com/hotelresults?q=6605¤cyId=16&lang=pt-BR&hotel_folder=&NRooms=1&version=4&CheckIn=17012026&CheckOut=18012026&ad=2&ch=0&ag=&Code=",
  "rules": {
    "discount": { "value": 50, "category": "discount" },
    "installment": { "times": 4, "withEntry": true, "entryPercent": 30 }
  },
  "template": [
    "*🏨 PARA:* {{adults}} adulto(s){{childrens|if: e {{childrens}} criança(s) com idades {{ages}}:}}\n📅 *PERÍODO:* {{checkin|date}} a {{checkout|date}}\n\n*Check-in:* A partir das 16h\n*Check-out:* Até as 14h\n\n*Acomodação:* _{{name}}_ - {{finalPrice|currency}}\n\n*💳 Forma de pagamento:*\nSinal de {{entryValue|currency}} via Pix no ato da reserva;\nSaldo restante em até {{times}}x de {{installment|currency}} sem juros no check-in.\n\n*⏳ Tarifa válida somente até as 23h59 de hoje!*",
    "Estamos concedendo *{{discount}}% de desconto* e sua reserva sai de {{price|currency}} por apenas *{{finalPrice|currency}}*.\n\nSinal de {{entryPercent}}% no valor de {{entryValue|currency}} e o restante parcelado em {{times}}x de {{installment|currency}} pagos no check-in.\n\n*Oferta exclusiva para fechamento hoje!*"
  ],
  "message_1": "*🏨 PARA:* 2 adulto(s)\n📅 *PERÍODO:* 17/01/2026 a 18/01/2026\n\n*Check-in:* A partir das 16h\n*Check-out:* Até as 14h\n\n*Acomodação:* _Superior Casal_ - R$ 343,50\n\n*💳 Forma de pagamento:*\nSinal de R$ 103,05 via Pix no ato da reserva;\nSaldo restante em até 4x de R$ 60,11 sem juros no check-in.\n\n*⏳ Tarifa válida somente até as 23h59 de hoje!*",
  "message_2": "Estamos concedendo *50% de desconto* e sua reserva sai de R$ 687,00 por apenas *R$ 343,50*.\n\nSinal de 30% no valor de R$ 103,05 e o restante parcelado em 4x de R$ 60,11 pagos no check-in.\n\n*Oferta exclusiva para fechamento hoje!*"
}