Skip to main content

Antes de começar

Este guia descreve o fluxo que um PDV deve implementar para:
  • consultar benefícios usando o cliente e o carrinho atual;
  • validar a identidade do consumidor quando solicitado pela BonifiQ;
  • resgatar desconto, cashback, produto ou brinde;
  • registrar a venda concluída;
  • estornar um resgate abandonado e cancelar um pedido total ou parcialmente.
Raiz da API privada: https://api.bonifiq.com.br/v1/pvtOs caminhos deste guia são mostrados completos a partir de /v1/pvt. A maioria começa com /POS, mas o resgate de produto ou brinde usa /RewardConfigurations.
A API privada usa Basic Auth e foi criada para comunicação entre sistemas. Mantenha as credenciais em um backend, serviço local seguro do PDV ou cofre de segredos.Nunca coloque usuário e senha em frontend/browser, aplicativo distribuído ao consumidor, repositório, log ou cURL compartilhado.
Use sempre JSON em PascalCase, como nos exemplos desta página.

Fluxo completo

O PDV deve tratar resgate e cadastro do pedido como operações distintas. Um resgate bem-sucedido consome o benefício; o pedido concluído registra a compra e gera a bonificação.

1. Consultar benefícios

Chame POST /v1/pvt/POS/rewards/available quando:
  • o cliente for identificado ou alterado;
  • um produto ou quantidade mudar;
  • um desconto que não seja da BonifiQ mudar;
  • o PDV precisar revalidar a seleção antes do resgate.

Valores do pedido

PurchaseValue é o valor bruto, antes de descontos, cupons e promoções.DiscountValue contém somente descontos que já existiam no PDV e não vieram da BonifiQ.
Exemplo: A BonifiQ usa PurchaseValue para regras de valor mínimo, limites e cashback. Ela usa DiscountValue separadamente para avaliar cumulatividade. Não envie o valor líquido em PurchaseValue.

Request

string
required
Identificador do cliente. Pode ser documento ou e-mail. Para CPF/CNPJ, envie apenas números.
decimal
required
Valor bruto atual do carrinho.
decimal
Desconto já aplicado pelo PDV e que não pertence à BonifiQ. Envie 0 ou null quando não houver.
array
Carrinho atual. Embora o contrato preserve compatibilidade sem esta lista, envie-a para considerar restrições por produto e benefícios RewardType = 5.
Cada produto pode conter:
  • OriginalId: SKU ou identificador estável no PDV;
  • LineId: identificador da linha, útil quando o mesmo SKU aparece com preços diferentes;
  • Title, Quantity e IsActive;
  • ProductPrice: preço unitário regular;
  • ProductDiscountPrice: preço unitário promocional, quando houver;
  • ProductBrand e ProductCategory, ambas com OriginalId e Name;
  • ProductCategory.ParentCategory para hierarquia de categorias.
cURL

Response

Rewards[].CanUse é a fonte autoritativa para habilitar uma opção. Não recalcule elegibilidade usando apenas saldo, preço ou Requirements.Algumas variantes antigas ou respostas internas podem trazer CanUseReward como resumo. A integração POS não deve depender desse campo: use Rewards[].CanUse.
Use Requirements como explicação amigável e CannotUseReason para comportamento estruturado:

Tipos de recompensa

Se HasRewards=false, prossiga com a venda sem benefício. Se houver recompensas com CanUse=false, elas podem ser exibidas desabilitadas com o motivo retornado.

2. Validar o cliente

Execute o challenge quando:
Se ambas as flags forem falsas, pule diretamente para o resgate.

Criar challenge

cURL
  • Gere TransactionId uma vez por tentativa de validação e mantenha-o até concluir ou abandonar o fluxo.
  • Quando ShouldValidateCustomerSignup=true, envie Document e Name, além dos contatos disponíveis.
  • Se a resposta retornar ShouldInformPhone=true ou ShouldInformEmail=true, repita com o contato solicitado, o mesmo TransactionId e os dados cadastrais originais.
O código pode não ser devolvido ao PDV em produção: normalmente o consumidor o recebe pelo canal configurado.

Validar código

cURL
Se Success=false, não resgate. Permita nova digitação ou solicite outro código. Não hardcode o tempo de validade do PIN; trate a resposta da API.

3. Resgatar o benefício

Antes da primeira chamada:
  1. gere uma OriginalKey única para a operação;
  2. persista essa chave junto à venda pendente;
  3. reutilize exatamente a mesma chave em timeout ou retry.

Desconto ou cashback

Use POST /v1/pvt/POS/rewards/{id}/redeem para os tipos comuns.
cURL
Para cashback, acrescente Value com o valor decimal escolhido, maior que zero e limitado por MaxCashbackForCurrentPurchase. Não envie Value para desconto fixo ou percentual.
Persista:
  • Result.RewardId para um eventual estorno;
  • Result.ExternalCode para enviar como Coupon no pedido;
  • Result.OriginalKey para conciliação.

Produto, desconto em SKU ou brinde

Quando RewardType=5, use:
O id da rota é Rewards[].Id. O Product.ExternalProductId deve corresponder ao identificador offline retornado na consulta.
cURL
Para os modos que não são brinde, informe ProductPrice ou ProductDiscountPrice. Se a linha já possui promoção, envie o preço promocional e HasPromotion=true para que a API aplique as regras de cumulatividade.
Adicione o produto resgatado como linha separada do carrinho. Para desconto em produto, use ProductDiscountTotal retornado para calcular o preço líquido. Para brinde, o preço final da linha é zero.

4. Registrar o pedido

Envie todos os pedidos concluídos, mesmo quando não houver benefício. Use:
OrderTotal é o valor líquido efetivamente pago, sem frete, depois de descontos, cashback, cupons e promoções. Continuando o exemplo:
PurchaseValue da consulta e OrderTotal do pedido representam valores diferentes. Não reutilize um no lugar do outro.
cURL

Regras do payload

  • OriginalId deve permanecer igual em retries. Não gere um novo ID após timeout.
  • Coupon recebe o ExternalCode escalar retornado pelo resgate.
  • Customer é um DTO de criação. Não copie o objeto da consulta inteiro e não envie campos como Id ou CurrentTier.
  • Products[] usa Title, ProductPrice e IsActive. O contrato não possui Quantity, Price nem ProductDiscountPrice.
  • ProductPrice representa o valor líquido atribuído à linha. Distribua descontos em centavos para a soma dos produtos fechar com OrderTotal.
  • Prefira PaymentMethods[]. O campo singular PaymentMethod existe apenas por compatibilidade.
  • A soma de PaymentMethods[].PaidAmount deve representar o valor efetivamente pago.

Cashback e pontos estimados

A resposta inclui EstimatedBonus:
Se GenerateBonus=true, o PDV pode informar ao consumidor quanto ganhou. Para cashback, exiba diretamente EstimatedCashbackFormatted; não refaça formatação ou conversão local.

5. Estornos e cancelamentos

Abandono antes do resgate

Se ainda não existe RewardId, não há resgate para estornar. Limpe apenas o estado local.

Resgate realizado, venda ainda não concluída

Antes de permitir edição de cliente, carrinho ou benefício, estorne:
cURL
Use o RewardId retornado pelo resgate, não o ID da configuração. Remova a linha resgatada somente depois de confirmar Result.IsCanceled=true. Também existe cancelamento por OriginalKey em DELETE /v1/pvt/POS/rewards, com a chave no body.

Cancelamento total do pedido

cURL
O orderId da rota é o OriginalId enviado no cadastro. O cancelamento remove a bonificação da compra e trata o resgate associado segundo as regras da BonifiQ.

Cancelamento parcial

Use POST /v1/pvt/POS/{orderId}/partialcancel quando apenas parte do valor pago for devolvida.
cURL
  • ValueToRefund é o valor líquido devolvido.
  • A soma de Products[].ValueToRefund deve ser exatamente igual a ValueToRefund após arredondamento monetário.
  • Cada Products[].OriginalId deve existir no pedido original.
  • Omita ShouldRefundRedeem ou envie null para seguir a configuração do tenant; true força e false impede o estorno do resgate.
  • Gere e persista CancelKey antes da primeira tentativa.
  • Em timeout, repita a mesma chave com o mesmo payload.
  • Nunca reutilize a chave com valor, produtos ou ShouldRefundRedeem diferentes.
Resposta aceita:
Resposta de validação, normalmente com HTTP 400:
Não atualize o pedido local quando HasError=true, Result.IsCanceled=false ou RefundErrorDetails estiver preenchido.

6. Erros, warnings e retries

As respostas envelopadas podem conter: Não assuma que todo HTTP 200 é sucesso: verifique HasError e Severity. Um warning com HasWarning=true e HasError=false continua sendo um resultado válido. Os endpoints de challenge têm resposta própria com Success e FriendlyErrorMessage. Não aplique cegamente o envelope genérico a eles. Implemente timeout explícito, correlação e backoff para falhas transitórias. Em 429 Too Many Requests, respeite Retry-After quando disponível. Não dependa de limites numéricos fixos no cliente.

7. Segurança e operação

  • Envie somente campos aceitos pelo contrato. Não reaproveite respostas inteiras como requests.
  • Nunca registre o header Authorization.
  • Em ambientes reais, aplique política de proteção de PII a documentos, e-mails e telefones.
  • Ferramentas de teste podem exibir dados fictícios completos, mas cURLs compartilhados devem manter a credencial como placeholder.
  • Persista OriginalKey, RewardId, ExternalCode, OriginalId do pedido e CancelKey de forma durável.
  • Concilie operações cujo resultado ficou incerto antes de criar novas chaves.
  • Envie pedidos sem benefício; eles também geram pontos e cashback conforme a configuração.

Projeto de referência

PDV BonifiQ Integration Example

Projeto educacional com modo mock, fluxo visual e linha do tempo de requests e responses.
O projeto demonstra os fluxos desta página, mas não é uma implementação pronta para produção:
  • o acesso direto pelo navegador existe apenas para facilitar o aprendizado;
  • pedidos e chaves são mantidos em memória;
  • o exemplo de produto usa uma unidade e preço simplificado;
  • persistência, timeout, recuperação após reinício e proteção de credenciais pertencem ao PDV integrador.
O suporte a RewardType=5 deve ser publicado junto com a versão da API que disponibiliza /RewardConfigurations/{id}/product-discount/redeem no ambiente alvo.

Checklist de implementação

  • Credenciais mantidas fora do frontend e dos logs
  • JSON enviado em PascalCase
  • PurchaseValue bruto e DiscountValue separado
  • Carrinho completo enviado em Products
  • CanUse e CannotUseReason respeitados
  • Challenge executado para qualquer uma das duas flags de validação
  • OriginalKey persistida e reutilizada
  • Fluxo específico de RewardType=5 implementado
  • ExternalCode enviado em Coupon
  • OrderTotal e PaidAmount líquidos
  • EstimatedCashbackFormatted exibido sem recálculo
  • Estorno obrigatório antes de editar uma venda já resgatada
  • Cancelamentos total e parcial testados
  • OriginalId e CancelKey estáveis em retries
  • Timeout, backoff, correlação e recuperação após reinício testados

Perguntas frequentes

Líquido. Envie o valor efetivamente pago depois de descontos, cashback, cupons e promoções, sem frete.
Não necessariamente. PurchaseValue é bruto e serve para consultar elegibilidade; OrderTotal é o total líquido da venda concluída.
O fluxo POS vincula um ExternalCode escalar ao campo Coupon. Apresente as opções e permita que o consumidor escolha uma recompensa.
Sim. Todos os pedidos concluídos devem ser enviados para que a BonifiQ calcule a bonificação.
Não. Reutilize a chave persistida até descobrir o resultado da operação original.

Suporte