Registrar Venda¶
Registra a venda finalizada. É a terceira operação do fluxo de PDV, chamada ao
fechar a compra. Responde 202 Accepted imediatamente; a gravação é assíncrona.
Processamento assíncrono
O 202 Accepted significa que a venda foi recebida (status = RECEIVED), não
necessariamente processada. O PDV não deve esperar por processamento síncrono.
| Item | Valor |
|---|---|
| URL | POST /api/v1/tenants/{tenantId}/sales |
| Método | POST |
| Autenticação | Basic Auth |
| Content-Type | application/json |
Request¶
{
"protocol": "ROCK_V1",
"customer": { "id": "10098075012", "type": "CPF" },
"sale": {
"id": 45821,
"store": { "id": "LOJA-001", "posId": "PDV-01", "employeeId": "OP001", "sellerId": "VEND01" },
"channel": "1",
"posProvider": "ROCK",
"date": "2024-06-15T14:30:00Z",
"amount": 45.90,
"amountPayable": 40.90,
"discountAmount": 5.00,
"items": [
{
"id": "1",
"gtin": "7891234567890",
"description": "Leite Integral 1L",
"unitPrice": 7.50,
"quantity": 2,
"unitMeasure": "UN",
"discounts": [
{ "promotionId": "100", "partnerPromotionId": "PROMO-EXT-001", "quantity": 2, "unitDiscount": 2.50 }
]
},
{
"id": "2",
"gtin": "7899876543210",
"description": "Arroz 5kg",
"unitPrice": 30.90,
"quantity": 1
}
],
"payments": [
{ "id": 1, "amount": 40.90, "method": "PIX", "bin": "411111", "nsu": "123456789", "installments": 1 }
],
"fiscalDocument": {
"number": "000123456",
"serialNumber": "001",
"model": "65",
"type": "NFC-e",
"url": "https://nfce.fazenda.gov.br/consulta?chave=123"
}
}
}
{
"protocol": "ROCK_V1",
"sale": {
"id": 45822,
"store": { "id": "LOJA-001", "posId": "PDV-01" },
"channel": "LOJA",
"date": "2024-06-15T15:00:00Z",
"amount": 30.90,
"amountPayable": 30.90,
"items": [
{ "id": "1", "gtin": "7899876543210", "description": "Arroz 5kg", "unitPrice": 30.90, "quantity": 1 }
],
"payments": [ { "id": 1, "amount": 30.90, "method": "DINHEIRO" } ]
}
}
Venda sem cliente
Quando customer é omitido/null, a venda é registrada para o cliente padrão
(00000000000), sem reserva de descontos.
Campos do request¶
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
protocol |
string | Sim | Protocolo (ex: ROCK_V1) |
customer |
object | Não | Omitido/null → cliente não identificado (00000000000) |
customer.id |
string | Não | CPF/CNPJ. Null/vazio → não identificado |
customer.type |
string | Não | CPF ou CNPJ |
sale.id |
number (Long) | Sim | Número do cupom/recibo |
sale.store.id |
string | Sim | Código externo da loja |
sale.store.posId |
string | Sim | Identificador do PDV |
sale.channel |
string | Sim | Canal de venda |
sale.date |
Instant | Sim | Data/hora da venda (ISO 8601) |
sale.amount |
number | Sim | Valor bruto total (positivo) |
sale.amountPayable |
number | Sim | Valor a pagar após descontos (positivo) |
sale.discountAmount |
number | Não | Valor total de desconto |
sale.items |
array | Sim (não vazio) | Itens da venda |
sale.items[].id |
string | Sim | ID sequencial do item |
sale.items[].gtin |
string | Sim | GTIN/EAN |
sale.items[].description |
string | Sim | Descrição do produto |
sale.items[].unitPrice |
number | Sim | Preço unitário (positivo) |
sale.items[].quantity |
number | Sim | Quantidade (positiva) |
sale.items[].discounts[].promotionId |
string | Sim (se houver desconto) | ID do desconto Rock |
sale.items[].discounts[].quantity |
number | Sim (se houver desconto) | Quantidade com desconto |
sale.items[].discounts[].unitDiscount |
number | Sim (se houver desconto) | Valor do desconto por unidade |
sale.payments |
array | Sim (não vazio) | Pagamentos |
sale.payments[].id |
number (Long) | Sim | ID do pagamento |
sale.payments[].amount |
number | Sim | Valor pago (positivo) |
sale.payments[].method |
string | Sim | Forma de pagamento |
sale.fiscalDocument |
object | Não | Documento fiscal (opcional) |
Preserve os descontos autorizados
Reenvie os descontos obtidos na Operação 2 mantendo o
promotionId, para que a venda seja registrada com os benefícios corretos.
Response 202 Accepted¶
{
"customer": { "id": "10098075012", "type": "CPF" },
"sale": { "id": 45821, "status": "RECEIVED" },
"messages": [ { "type": "SUCCESS", "content": "Venda registrada com sucesso." } ]
}
| Campo | Descrição |
|---|---|
customer.id |
CPF/CNPJ do cliente. 00000000000 quando não identificado |
customer.type |
CPF/CNPJ, ou null quando não identificado |
sale.id |
Ecoado do request |
sale.status |
RECEIVED — venda recebida para processamento assíncrono |
messages |
Mensagens de retorno da operação |
Status codes¶
| HTTP | Tipo | Causa |
|---|---|---|
202 |
— | Venda recebida com sucesso |
400 |
validation-error |
Campos obrigatórios ausentes/inválidos, ou CPF 00000000000 enviado com descontos |
401 |
unauthorized |
Credenciais inválidas |
404 |
resource-not-found |
Loja não encontrada pelo código externo |
422 |
sale-value-inconsistency |
Divergência entre total dos itens e valor da venda além da tolerância |
503 |
sale-notification-disabled |
Recurso de registro de venda desativado para o tenant |
Detalhes do formato de erro em Tratamento de Erros.
Exemplo — curl¶
curl -X POST "https://<BASE_URL>/api/v1/tenants/<TENANT_ID>/sales" \
-u "<CLIENT_ID>:<CLIENT_SECRET>" \
-H "Content-Type: application/json" \
-d '{ "protocol": "ROCK_V1", "customer": { "id": "10098075012", "type": "CPF" }, "sale": { "id": 45821, "store": { "id": "LOJA-001", "posId": "PDV-01" }, "channel": "1", "date": "2024-06-15T14:30:00Z", "amount": 25.00, "amountPayable": 25.00, "items": [ { "id": "1", "gtin": "7891234567890", "description": "Produto", "unitPrice": 25.00, "quantity": 1 } ], "payments": [ { "id": 1, "amount": 25.00, "method": "PIX" } ] } }'
Referências¶
- Identificar Cliente — Operação 1
- Autorizar Descontos — Operação 2
- Tratamento de Erros