Bunne Docs

Hotelaria (reservas)

Informe a reserva na cobrança e no link: campos, pré-requisitos de permissão e o que muda no recebimento.

Se você vende hospedagem, pode informar a reserva na cobrança: check-in, check-out, número da reserva e canal de venda. Com isso a venda deixa de ser uma cobrança anônima e passa a carregar a estadia que ela paga.

Antes de integrar: dois pré-requisitos

O objeto reservation só é aceito quando as duas condições abaixo valem. Elas são configuradas pela plataforma, não pela API — peça ao seu contato comercial antes de começar.

  1. O token tem a permissão. Enviar reservation exige charges:create na chave usada (e payment_links:create para links de pagamento). Sem a permissão a requisição volta 403 insufficient_permissions, antes de qualquer validação da reserva.
  2. O estabelecimento está habilitado para hotelaria. Cada seller é habilitado individualmente. Com o módulo desligado, a requisição volta 422 reservation_not_supported e nenhuma cobrança é criada.

Enquanto os dois não estiverem prontos, envie a cobrança sem o objeto reservation: ela funciona normalmente. Você pode integrar o resto do fluxo e ligar a reserva depois, sem mudar mais nada.

O que a reserva muda no seu recebimento

Dependendo da condição comercial contratada pelo estabelecimento, o dinheiro de uma venda com reserva pode ser liberado em função da data da estadia, e não da data do pagamento — por exemplo, um dia após o check-in.

Duas garantias que valem sempre, independentemente da condição contratada:

  • A reserva nunca antecipa o recebimento. Ela só pode adiar. Uma reserva com check-in próximo recebe exatamente no prazo normal do plano.
  • Cobrança sem reservation não é afetada. Diária avulsa, consumo, restaurante: tudo segue o prazo normal, mesmo num estabelecimento habilitado para hotelaria.

A data efetiva de cada recebível continua sendo a que a API de recebíveis e o painel já mostram — você não precisa calcular nada.

Campos

  • check_in e check_out obrigatórios os dois, no formato AAAA-MM-DD (data, sem hora). check_out tem que ser igual ou posterior ao check_in; iguais significam day use.
  • code — o número da reserva no seu PMS ou na OTA. Não precisa ser único: depósito e saldo da mesma reserva são duas cobranças com o mesmo código, e é assim que elas se reencontram.
  • channel — de onde veio a venda. O catálogo é da sua plataforma; um código desconhecido é recusado e a resposta lista os válidos.
  • rate_type, guarantee_nights, guest_name — opcionais e informativos. Ver "O que a plataforma NÃO faz" abaixo.

Cobrança com reserva

curl -X POST $API_BASE_URL/charges \  -H "Authorization: Bearer sk_live_xxx" \  -H "Idempotency-Key: reserva_BK-4471902_deposito" \  -H "Content-Type: application/json" \  -d '{    "amount": 125000,    "payment_method": "CREDIT_CARD",    "installments": 1,    "card_token": "tok_xxx",    "buyer": {      "name": "Ada Lovelace",      "email": "ada@example.com",      "phone": "5511999990000",      "document": "12345678909",      "address": {        "line_1": "Av. Paulista, 1000",        "zip_code": "01310-100",        "city": "Sao Paulo",        "state": "SP",        "country": "BR"      }    },    "reservation": {      "check_in": "2026-11-20",      "check_out": "2026-11-23",      "code": "BK-4471902",      "channel": "BOOKING",      "rate_type": "non_refundable",      "guarantee_nights": 2,      "guest_name": "Ada Lovelace"    }  }'

Resposta

A cobrança devolve a reserva de volta, com nights calculado. Uma cobrança sem reserva não ganha a chave reservation — a resposta continua idêntica à de sempre.

{  "object": "charge",  "id": "ch_xxx",  "status": "paid",  "amount_cents": 125000,  "currency": "BRL",  "payment_method": "credit_card",  "installments": 1,  "reservation": {    "id": "resv_xxx",    "object": "reservation",    "check_in": "2026-11-20",    "check_out": "2026-11-23",    "nights": 3,    "code": "BK-4471902",    "channel": "BOOKING",    "status": "confirmed",    "rate_type": "non_refundable",    "guarantee_nights": 2,    "guest_name": "Ada Lovelace"  },  "request_id": "req_xxx"}

Link de pagamento com reserva

Se a sua central de reservas cobra por link, o mesmo objeto vale em POST /payment-links. A reserva vira o produto: a página de pagamento e o comprovante mostram a estadia e o número da reserva no lugar de um nome genérico.

curl -X POST $API_BASE_URL/payment-links \  -H "Authorization: Bearer sk_live_xxx" \  -H "Content-Type: application/json" \  -d '{    "name": "Reserva BK-4471902 — Suite Master",    "amount_cents": 125000,    "payment_methods": ["CREDIT_CARD", "PIX"],    "max_installments": 3,    "reservation": {      "check_in": "2026-11-20",      "check_out": "2026-11-23",      "code": "BK-4471902",      "channel": "CENTRAL_RESERVAS"    }  }'

Quando o link é pago, a reserva é copiada para a cobrança gerada. A validação acontece na criação do link: mudanças de catálogo depois disso nunca derrubam o checkout de um hóspede.

Quando a reserva muda

Remarcação, cancelamento ou no-show: informe pela API e a plataforma reprograma o que ainda não foi liberado.

curl -X PATCH $API_BASE_URL/charges/ch_xxx/reservation \  -H "Authorization: Bearer sk_live_xxx" \  -H "Content-Type: application/json" \  -d '{    "check_in": "2026-12-05",    "check_out": "2026-12-08"  }'
{  "object": "reservation_update",  "charge_id": "ch_xxx",  "reservation_id": "resv_xxx",  "rescheduled_receivables": 2,  "already_released_receivables": 1,  "request_id": "req_xxx"}

already_released_receivables conta os recebíveis que já tinham sido liberados e por isso não foram tocados: dinheiro já disponível para o estabelecimento não volta atrás. Se esse número vier maior que zero, a informação chegou depois da liberação — e é isso que a resposta está te dizendo.

Envie só o que mudou. Os campos ausentes ficam como estão.

O que a plataforma NÃO faz

Status da reserva é informação, não dinheiro

Enviar status: "canceled" ou "no_show" não estorna nada e não antecipa nenhuma liberação. rate_type e guarantee_nights também não disparam nada sozinhos.

A política de tarifa é sua: se a reserva cancelada tem que devolver dinheiro (todo ou em parte), faça o estorno pelo fluxo normal — POST /charges/{id}/refund, total ou parcial. A plataforma não decide por você quanto devolver.

Erros

reservation_not_supported (422) — o estabelecimento não está habilitado para hotelaria. Nenhuma cobrança é criada.

{  "error": {    "type": "validation_error",    "code": "reservation_not_supported",    "message": "This seller is not enabled for hospitality reservations.",    "param": "reservation"  },  "request_id": "req_xxx"}

unknown_reservation_channel (422) — canal fora do catálogo, ou desativado. Os códigos válidos vêm em details.valid_channels.

{  "error": {    "type": "validation_error",    "code": "unknown_reservation_channel",    "message": "Unknown reservation channel for this white label.",    "param": "reservation.channel",    "details": {      "valid_channels": [        "BOOKING",        "DECOLAR",        "EXPEDIA",        "CENTRAL_RESERVAS",        "IA",        "MOTOR_RESERVAS"      ]    }  },  "request_id": "req_xxx"}

reservation_horizon_exceeded (422) — check-in longe demais no futuro. Quase sempre é o ano trocado no PMS. O limite vem em details.max_horizon_days.

invalid_request (422) — data que não existe no calendário, check_out antes do check_in, ou campo desconhecido dentro de reservation.

Onde a reserva aparece depois

  • No detalhe da transação, no painel — número, estadia, canal e situação.
  • Na busca de transações: procure pelo número da reserva, não só pelo id da cobrança.
  • No recebível, com a explicação da data de liberação quando ela vem da reserva.