Pular para o conteúdo principal

Webhooks

Nas outras páginas, o seu sistema chama a Enjoy.it. Aqui é o contrário: a Enjoy.it chama o seu sistema quando algo acontece na loja.

Nesta API os webhooks também são chamados de IPN — é a razão de os campos se chamarem consumptionIpn, balanceIpn e openTapIpn. São a mesma coisa.

Pré-requisito

Webhook só funciona se o seu sistema tiver um endereço público na internet, com HTTPS, ligado 24 horas por dia. Um PDV instalado dentro da loja, sem endereço público, não consegue receber webhooks — nesse caso use consulta na API.

A explicação está em Escolha sua integração.

Eventos disponíveis

CampoDireçãoPara que serveMétodo
consumptionIpnEnjoy.it → vocêAvisar que um consumo foi concluídoPOST
balanceIpnEnjoy.it → vocêPerguntar o saldo antes de liberar consumoGET
openTapIpnEnjoy.it → vocêAvisar que o estado da torneira mudouPOST

As URLs podem ser configuradas no cadastro do parceiro ou enviadas no check-in de cada sessão.

Notificação de consumo

O evento principal. A Enjoy.it faz um POST na URL de consumptionIpn depois de cada servida:

{
"createdAt": "2026-08-02T19:43:29.416Z",
"transactionReference": "pedido-987",
"idPlace": "P-EXEMPLO",
"idTap": "T-01",
"idTab": "006",
"rfid": "4623227593",
"sku": "IPA-001",
"consumerReference": "cliente-123",
"product": "IPA da Casa",
"mlServed": 320,
"total": 12.8,
"uid": "5FS6DS0BDERIWG9QL6ojfuLedg23",
"type": "D"
}

O que o seu sistema faz com isso:

CampoUso
idTab, rfid ou consumerReferenceAchar de quem é a conta
totalO valor a lançar. Já vem calculado
product e mlServedA descrição do item para o cliente
uid + createdAtA identificação da transação. Use para não lançar duas vezes

A ordem correta do seu lado:

1. Recebe o POST
2. Verifica se uid + createdAt já foram gravados
- Já gravou? Responda 2xx e pare aqui
3. Lança na conta do cliente
4. Grava o identificador
5. Só agora responde 2xx

A sua resposta de sucesso também dá a baixa da transação (o ack): ela deixa de aparecer na lista de transações não confirmadas. Em integrações por webhook não é preciso chamar o endpoint de confirmação — ele existe para quem importa por consulta.

aviso

Responder 2xx antes de gravar dá baixa em um consumo que você ainda não lançou. Se o seu sistema cair em seguida, o evento não será reenviado e não aparecerá nas pendências: aquele consumo não será cobrado do cliente.

Reentregas

Quando o seu sistema não responde com sucesso, a Enjoy.it tenta de novo:

Número de tentativasAté 5
Intervalo entre tentativas15 minutos
Quando paraAssim que receber uma resposta de sucesso
Depois da 5ª tentativaO evento não é mais reenviado

Isso cobre bem uma indisponibilidade curta — um deploy, um reinício —, mas repare no intervalo: a primeira reentrega só acontece 15 minutos depois. Uma falha durante o atendimento pode não se recuperar antes de o cliente ir embora.

Por isso a reentrega não elimina a conferência final nem a rotina de recuperação descritas no fim desta página.

E, como o mesmo consumo pode chegar mais de uma vez, a verificação de uid + createdAt antes de lançar é obrigatória: é ela que impede a cobrança em dobro quando a sua resposta se perde mas o lançamento foi feito.

Consulta de saldo

Antes de liberar a torneira em um fluxo com limite, a Enjoy.it faz um GET na URL de balanceIpn para perguntar quanto o cliente ainda tem. A URL pode conter variáveis, substituídas no momento da chamada:

https://parceiro.exemplo.com/saldos/{consumerReference}?place={idPlace}&tab={idTab}&rfid={rfid}

Variáveis disponíveis: {idPlace}, {idTab}, {rfid} e {consumerReference}.

Resposta esperada, 200:

{
"balance": 80
}

O valor é em reais e deve representar o saldo disponível naquele instante. Este endereço fica no caminho crítico do atendimento: se demorar a responder, o cliente espera na torneira.

Estado da torneira

A Enjoy.it faz um POST na URL de openTapIpn quando o estado da abertura muda:

{
"idPlace": "P-EXEMPLO",
"idTap": "T-01",
"status": "serving",
"consumerReference": "cliente-123",
"transactionReference": "pedido-987"
}

Responda 2xx para confirmar o recebimento.

Requisitos do seu endereço

  • Aceite HTTPS com certificado público válido — certificado autoassinado não serve.
  • Responda rápido. Processe tarefas demoradas de forma assíncrona, depois de responder.
  • Trate cada evento de forma idempotente, usando uid + createdAt.
  • Guarde log com idPlace, consumerReference e transactionReference.
  • Não dependa da ordem de chegada. Dois consumos seguidos podem chegar fora de ordem.
  • Valide a credencial combinada na homologação, quando houver.

Problemas comuns

SintomaCausa provável
Nenhum webhook chegaconsumptionIpn não foi informado no check-in, ou o endereço não é acessível de fora
Chegam alguns e outros nãoSeu endereço está lento ou instável e as chamadas expiram
Cliente cobrado em dobroFalta a verificação de uid + createdAt antes de lançar
Consumo sumiuVocê respondeu 2xx antes de gravar
Só funciona na rede da lojaO endereço é interno; não é alcançável pela internet

Recuperação: o webhook não basta sozinho

Mesmo com tudo certo, um evento pode se perder — queda de rede, deploy, servidor reiniciando. Por isso, mantenha sempre uma rotina de conferência com transações não confirmadas.

Como a baixa é dada pela sua resposta de sucesso, essa lista contém exatamente os consumos que não chegaram a ser processados — os que falharam e os que esgotaram as 5 tentativas. Não é preciso varrer o extrato inteiro nem comparar com o seu banco: o que está lá é o que falta lançar.

Se você lançar algum consumo a partir dessa lista, dê baixa nele pelo endpoint de confirmação. Fora do webhook a baixa não é automática, e sem ela o mesmo consumo reaparece na próxima verificação.

E, na hora de fechar a conta, faça uma consulta final ao extrato do cliente. É a rede de segurança mais simples que existe.