Vendas (sales)
O recurso sales expõe as vendas e os pedidos da sua conta, isto é, as
transações com transaction_type igual a sale ou order. É um recurso de
leitura e escrita: você lista, busca por id, cria com itens, atualiza e
cancela vendas pela API.
| Módulo | vendas — precisa estar habilitado no contrato |
| Escopos | sales:read para ler; sales:write para criar, atualizar e cancelar |
| Operações | leitura e escrita |
Endpoints
Seção intitulada “Endpoints”| Método | Endpoint | Escopo | Descrição |
|---|---|---|---|
GET |
/v1/sales |
sales:read |
Lista vendas e pedidos com paginação por cursor |
GET |
/v1/sales/{id} |
sales:read |
Busca uma venda pelo id, com ?include=items,status_history |
POST |
/v1/sales |
sales:write |
Cria uma venda com itens e responde 201 |
PATCH |
/v1/sales/{id} |
sales:write |
Atualiza status, pagamento, entrega e observações |
DELETE |
/v1/sales/{id} |
sales:write |
Cancela a venda (status="cancelled") e responde 204 |
Fluxo operacional: catálogo, parcelas e recebimentos
Seção intitulada “Fluxo operacional: catálogo, parcelas e recebimentos”Use estas rotas para uma venda com itens, parcelas e estoque confirmados juntos.
Todas exigem o módulo vendas; escritas exigem sales:write e leituras,
sales:read.
| Método | Endpoint | Resultado |
|---|---|---|
POST |
/v1/sales/operations |
Cria a venda operacional |
PATCH |
/v1/sales/{id}/operations |
Edita dados ou substitui itens e pagamentos ainda sem histórico de recebimento |
POST |
/v1/sales/{id}/cancel |
Cancela após estornar todos os recebimentos |
GET |
/v1/sales/statuses |
Consulta status ativos e motivos de cancelamento da equipe |
GET |
/v1/sales/{id}/payments |
Consulta pagamentos e suas parcelas |
POST |
/v1/sales/installments/{id}/receipts |
Registra recebimento parcial ou total |
GET |
/v1/sales/{id}/receipts |
Lista recebimentos e estornos |
GET |
/v1/sales/receipts/{id} |
Consulta uma operação financeira |
POST |
/v1/sales/receipts/{id}/reversals |
Estorna um recebimento, parcial ou integralmente |
As três primeiras escritas respondem 200, com data e
meta.request_id, meta.command_id, meta.action. Recebimentos e estornos
respondem 201. Todas exigem Idempotency-Key com UUID: use o mesmo UUID e
o mesmo corpo para recuperar uma resposta perdida. Alterar o conteúdo com o
mesmo UUID resulta em 409 idempotency_conflict.
Criar uma venda operacional
Seção intitulada “Criar uma venda operacional”Corpo de POST /v1/sales/operations, para um item com preço cadastrado de
R$ 100,00:
{ "sale_date": "2026-10-05", "items": [ { "catalog": { "type": "item", "id": "7e53a0d2-5265-4ddd-90ce-a456864b19a1" }, "quantity": 1 } ], "payments": [ { "payment_method": "pix", "amount_cents": 10000, "destination_kind": "bank_account", "destination_id": "84273f63-4ac0-435a-889c-ccde2ed8b9e8", "due_dates": ["2026-10-05", "2026-11-05", "2026-12-05"] } ], "notes": "Pedido do cliente"}Cada referência de catalog usa type igual a item, product,
service ou combo, com o identificador do
catálogo correspondente. Os registros e componentes
precisam estar ativos e pertencer à equipe autenticada. customer_id é opcional;
quando informado, também deve pertencer à equipe.
A quantidade admite até três casas decimais. O servidor consulta o preço fixo do
catálogo; se você enviar unit_price_cents, ele deve coincidir com esse preço.
Para preço variável, unit_price_cents é obrigatório e deve respeitar a faixa
cadastrada. Cada item pode ter discount_cents e notes.
Os campos monetários são centavos inteiros BRL, limitados a 9.999.999.999.
O servidor arredonda cada quantidade × preço para centavos, aplica o desconto
do item e soma os resultados em subtotal_cents. Depois aplica o
discount_cents geral e acrescenta delivery_fee_cents e tax_cents.
O total precisa ser positivo; descontos nunca podem exceder a base correspondente.
Informe de 1 a 100 itens e de 1 a 20 pagamentos. A soma de
payments[].amount_cents deve ser exatamente o total calculado. Cada pagamento
tem de 1 a 120 datas de vencimento em ordem; uma venda à vista usa uma única
data. O servidor reparte o valor em centavos e deixa o resíduo na última parcela:
10000 em três datas resulta em 3333, 3333 e 3334. Todas nascem pendentes,
com paid_amount_cents: 0. Não envie payment_status nem valores recebidos.
destination_kind aceita bank_account ou wallet. O destino deve ser ativo,
em BRL e da mesma equipe. As formas de pagamento são pix, credit_card,
credit_card_installments, debit_card, cash, bank_transfer, bank_slip,
check, barter e wallet. Opcionalmente, card_machine_id vincula uma
maquininha ativa à conta bancária de destino, para PIX ou cartão. A taxa vigente
é capturada na criação e preservada nos recebimentos; o valor bruto da parcela
e o líquido que entra no saldo ficam separados.
Editar e concluir
Seção intitulada “Editar e concluir”GET /v1/sales/statuses informa o pipeline da equipe. Sem configuração,
os estados são created, in_progress, finalized e cancelled.
A criação escolhe o estado marcado como inicial, a menos que você envie outro
estado ativo permitido. Concluir em um estado final exige recebimento integral.
Uma venda finalizada não pode ser editada.
PATCH /v1/sales/{id}/operations aceita notes, sale_date,
customer_id e status. Para mudar itens ou qualquer valor, envie
items e payments completos. Essa substituição só é permitida antes
do primeiro recebimento; mesmo um recebimento totalmente estornado mantém
seu histórico e impede apagar/recriar parcelas. As duas listas e os totais
são substituídos em uma transação, incluindo a correção de estoque.
Essas escritas atendem às vendas criadas pelo fluxo operacional. Uma venda
antiga precisa de tratamento explícito antes de migrar sua composição e seu
estoque; não é convertida automaticamente. Nas vendas já adotadas, os
PATCH e DELETE antigos retornam 409 resource_conflict.
Receber, estornar e cancelar
Seção intitulada “Receber, estornar e cancelar”Depois de consultar GET /v1/sales/{id}/payments, use o id da parcela em
POST /v1/sales/installments/{id}/receipts:
{ "amount_cents": 2000, "destination_kind": "bank_account", "destination_id": "84273f63-4ac0-435a-889c-ccde2ed8b9e8", "effective_date": "2026-10-05"}O valor recebido não pode ultrapassar o restante da parcela. O pagamento parcial
preserva a parcela aberta; a quitação integral define paid. A resposta inclui
o identificador do recebimento. Para estorná-lo, envie ao endpoint de reversão:
{ "amount_cents": 2000, "effective_date": "2026-10-05", "reason": "Cliente desistiu da compra"}Depois de zerar todos os recebimentos, cancele com
POST /v1/sales/{id}/cancel:
{ "reason": "Cliente desistiu da compra", "financial_effects": "require_reversed"}cancellation_reason_id é opcional e deve ser um motivo ativo da equipe.
O cancelamento preserva parcelas e histórico, marca o estado de cancelamento
configurado e restitui o estoque uma única vez. A restituição usa as quantidades
capturadas na venda, mesmo se a composição do produto mudar depois.
Não é permitido desativar o controle de estoque de um item enquanto essas
quantidades ainda estiverem comprometidas.
Essas operações registram movimentos internos do LIGGA. Elas não executam transferências bancárias nem estornos na adquirente. A projeção de caixa depende da abertura explícita da conta ou carteira: consulte Operações financeiras.
Contrato original de vendas
Seção intitulada “Contrato original de vendas”As seções seguintes descrevem as rotas originais e seus campos em reais.
Para o fluxo composto acima, use os campos com sufixo _cents.
| Campo | Tipo | Descrição |
|---|---|---|
id |
uuid |
Identificador da venda |
customer_id |
uuid | null |
Cliente associado à venda |
transaction_type |
string |
Tipo da transação: sale para venda ou order para pedido |
transaction_number |
string | null |
Número sequencial da transação |
status |
string | null |
Situação da venda, por exemplo pending, completed ou cancelled |
sale_date |
string (ISO 8601) | null |
Data da venda |
delivery_date |
string (YYYY-MM-DD) | null |
Data de entrega |
subtotal |
number | null |
Soma dos subtotais dos itens, antes dos descontos |
discount_amount |
number | null |
Desconto em valor absoluto |
discount_percentage |
number | null |
Desconto percentual |
tax_amount |
number | null |
Impostos |
total_amount |
number | null |
Valor total: itens com descontos mais delivery_fee |
notes |
string | null |
Observações |
payment_method |
string | null |
Forma de pagamento, por exemplo pix, credit_card ou cash |
payment_status |
string | null |
Situação do pagamento, por exemplo pending ou paid |
delivery_fee |
number | null |
Taxa de entrega |
order_code |
string | null |
Código do pedido, de uso livre na integração |
is_active |
boolean | null |
Se o registro está ativo |
created_at |
string (ISO 8601) |
Data de criação |
updated_at |
string (ISO 8601) | null |
Data da última atualização |
items |
TransactionItem[] |
Itens da venda, presentes apenas com ?include=items |
status_history |
TransactionStatusHistory[] |
Histórico de status, presente apenas com ?include=status_history |
Campos internos como team_id, contract_id, created_by e internal_notes
nunca aparecem nas respostas.
Itens (TransactionItem)
Seção intitulada “Itens (TransactionItem)”| Campo | Tipo | Descrição |
|---|---|---|
id |
uuid |
Identificador do item |
catalog_type |
string |
Tipo do item do catálogo: product, service ou package |
catalog_item_id |
uuid |
Item do catálogo, veja Produtos (products) |
quantity |
number |
Quantidade |
unit_price |
number |
Preço unitário |
discount_amount |
number | null |
Desconto em valor no item |
discount_percentage |
number | null |
Desconto percentual no item |
subtotal |
number |
quantity × unit_price, antes dos descontos |
total_amount |
number |
Total do item depois dos descontos |
notes |
string | null |
Observações do item |
created_at |
string (ISO 8601) |
Data de criação |
Histórico de status (TransactionStatusHistory)
Seção intitulada “Histórico de status (TransactionStatusHistory)”| Campo | Tipo | Descrição |
|---|---|---|
id |
uuid |
Identificador da entrada |
old_status |
string | null |
Status anterior, null na criação |
new_status |
string |
Novo status |
change_reason |
string | null |
Motivo da mudança |
created_at |
string (ISO 8601) |
Quando a mudança ocorreu |
Corpo da criação (POST /v1/sales)
Seção intitulada “Corpo da criação (POST /v1/sales)”| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
items |
array (1–200) |
sim | Itens da venda, descritos abaixo |
customer_id |
uuid | null |
não | Cliente da venda |
transaction_type |
'sale' | 'order' |
não, padrão sale |
Venda ou pedido |
sale_date |
string (ISO 8601) |
não, padrão agora | Data da venda |
delivery_date |
string (YYYY-MM-DD) | null |
não | Data de entrega |
status |
string |
não, padrão pending |
Status inicial |
payment_method |
string | null |
não | Forma de pagamento |
payment_status |
string | null |
não | Situação do pagamento |
delivery_fee |
number ≥ 0 | null |
não | Taxa de entrega |
order_code |
string | null |
não | Código do pedido |
notes |
string | null |
não | Observações |
Cada entrada de items:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
catalog_type |
'product' | 'service' | 'package' |
sim | Tipo do item do catálogo |
catalog_item_id |
uuid |
sim | Identificador do item do catálogo |
quantity |
number > 0 |
sim | Quantidade |
unit_price |
number ≥ 0 |
sim | Preço unitário |
discount_amount |
number ≥ 0 |
não | Desconto em valor |
discount_percentage |
number 0–100 |
não | Desconto percentual |
notes |
string | null |
não | Observações do item |
Corpo da atualização (PATCH /v1/sales/{id})
Seção intitulada “Corpo da atualização (PATCH /v1/sales/{id})”Só estes campos podem ser alterados: status, payment_status,
payment_method, notes, delivery_date e delivery_fee. Quando status
muda, uma entrada é acrescentada automaticamente ao status_history.
Itens e valores não são editáveis por PATCH. Para corrigir itens, cancele a
venda e crie outra.
Filtros e ordenação
Seção intitulada “Filtros e ordenação”O formato do filtro é ?filter[<campo>][<operador>]=<valor>. Os operadores
disponíveis são eq, neq, gt, gte, lt, lte, in, nin, ilike e
is_null.
| Campo | Uso típico | Exemplo |
|---|---|---|
customer_id |
vendas de um cliente | filter[customer_id][eq]=9c8d7e6f-1a2b-4c3d-8e9f-0a1b2c3d4e5f |
status |
por situação | filter[status][in]=pending,completed |
transaction_type |
só vendas ou só pedidos | filter[transaction_type][eq]=order |
transaction_number |
busca pelo número | filter[transaction_number][eq]=000123 |
payment_status |
pagamentos pendentes | filter[payment_status][eq]=pending |
payment_method |
por forma de pagamento | filter[payment_method][eq]=pix |
sale_date |
por período | filter[sale_date][gte]=2026-07-01 |
total_amount |
por faixa de valor | filter[total_amount][gte]=100 |
is_active |
apenas ativos | filter[is_active][eq]=true |
created_at |
por data de criação | filter[created_at][gte]=2026-07-01T00:00:00Z |
updated_at |
sincronização incremental | filter[updated_at][gt]=2026-07-09T12:00:00Z |
- Ordenação:
sort=created_at,sort=sale_dateousort=total_amount. O padrão é-created_at, das mais recentes para as mais antigas. - Paginação por cursor:
?limit=50&cursor=<next_cursor>. Olimitvai de 1 a 100 e o padrão é 20. - Campos parciais:
?fields=id,transaction_number,status,total_amount.
Filtros combinados:
GET /v1/sales?filter[status][neq]=cancelled&sort=-sale_dateGET /v1/sales?filter[customer_id][eq]=9c8d7e6f-1a2b-4c3d-8e9f-0a1b2c3d4e5f&filter[payment_status][eq]=pendingGET /v1/sales?filter[sale_date][gte]=2026-07-01&filter[sale_date][lt]=2026-08-01&limit=50Os detalhes de cada parâmetro estão em Paginação, filtros e ordenação.
Relações incluídas
Seção intitulada “Relações incluídas”GET /v1/sales/{id} aceita o parâmetro include, com valores separados por
vírgula:
items— itens da venda, ordenados porcreated_atcrescente;status_history— mudanças de status, em ordem cronológica.
GET /v1/sales/3f9a1b7e-2c4d-4e8f-b6a1-5d0c9e8f7a2b?include=items,status_historyValores desconhecidos em include são ignorados. A listagem GET /v1/sales
não aceita include, e a resposta do POST já vem com items.
Exemplos
Seção intitulada “Exemplos”curl "$LIGGA_BASE/v1/sales?filter[status][eq]=pending&limit=2&sort=-sale_date" \ -H "Authorization: Bearer $LIGGA_API_KEY"{ "data": [ { "id": "3f9a1b7e-2c4d-4e8f-b6a1-5d0c9e8f7a2b", "customer_id": "9c8d7e6f-1a2b-4c3d-8e9f-0a1b2c3d4e5f", "transaction_type": "sale", "transaction_number": "000231", "status": "pending", "sale_date": "2026-07-09T18:40:00.000Z", "delivery_date": null, "subtotal": 189.8, "discount_amount": null, "discount_percentage": null, "tax_amount": null, "total_amount": 179.8, "notes": null, "payment_method": "pix", "payment_status": "pending", "delivery_fee": null, "order_code": null, "is_active": true, "created_at": "2026-07-09T18:40:02.000Z", "updated_at": null }, { "id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "customer_id": null, "transaction_type": "order", "transaction_number": "000230", "status": "pending", "sale_date": "2026-07-08T10:12:00.000Z", "delivery_date": "2026-07-15", "subtotal": 250, "discount_amount": null, "discount_percentage": null, "tax_amount": null, "total_amount": 265, "notes": "Entregar no período da manhã", "payment_method": null, "payment_status": null, "delivery_fee": 15, "order_code": "PED-2026-0230", "is_active": true, "created_at": "2026-07-08T10:12:05.000Z", "updated_at": "2026-07-08T10:20:44.000Z" } ], "pagination": { "next_cursor": "eyJpZCI6ImExYjJjM2Q0LWU1ZjYtNGE3Yi04YzlkLTBlMWYyYTNiNGM1ZCIsInYiOiIyMDI2LTA3LTA4VDEwOjEyOjAwLjAwMFoifQ", "has_more": true, "limit": 2 }, "meta": { "request_id": "req_01J9ZXAMPLE" }}O cursor da próxima página está em pagination.next_cursor. Enquanto
pagination.has_more for true, repita a chamada com cursor igual a esse
valor.
Buscar por id
Seção intitulada “Buscar por id”curl "$LIGGA_BASE/v1/sales/3f9a1b7e-2c4d-4e8f-b6a1-5d0c9e8f7a2b?include=items,status_history" \ -H "Authorization: Bearer $LIGGA_API_KEY"{ "data": { "id": "3f9a1b7e-2c4d-4e8f-b6a1-5d0c9e8f7a2b", "customer_id": "9c8d7e6f-1a2b-4c3d-8e9f-0a1b2c3d4e5f", "transaction_type": "sale", "transaction_number": "000231", "status": "pending", "sale_date": "2026-07-09T18:40:00.000Z", "delivery_date": null, "subtotal": 189.8, "discount_amount": null, "discount_percentage": null, "tax_amount": null, "total_amount": 179.8, "notes": null, "payment_method": "pix", "payment_status": "pending", "delivery_fee": null, "order_code": null, "is_active": true, "created_at": "2026-07-09T18:40:02.000Z", "updated_at": null, "items": [ { "id": "6c7d8e9f-0a1b-4c2d-8e3f-4a5b6c7d8e9f", "catalog_type": "product", "catalog_item_id": "b7e1f3a2-8c4d-4e5f-9a6b-1c2d3e4f5a6b", "quantity": 2, "unit_price": 49.9, "discount_amount": null, "discount_percentage": null, "subtotal": 99.8, "total_amount": 99.8, "notes": null, "created_at": "2026-07-09T18:40:02.000Z" }, { "id": "7d8e9f0a-1b2c-4d3e-8f4a-5b6c7d8e9f0a", "catalog_type": "service", "catalog_item_id": "0d9e8f7a-6b5c-4d3e-2f1a-9b8c7d6e5f4a", "quantity": 1, "unit_price": 90, "discount_amount": 10, "discount_percentage": null, "subtotal": 90, "total_amount": 80, "notes": null, "created_at": "2026-07-09T18:40:02.000Z" } ], "status_history": [ { "id": "8e9f0a1b-2c3d-4e4f-8a5b-6c7d8e9f0a1b", "old_status": null, "new_status": "pending", "change_reason": null, "created_at": "2026-07-09T18:40:02.000Z" } ] }, "meta": { "request_id": "req_01J9ZXAMPLE" }}Um id que não existe, que pertence a outra conta ou que não é sale nem
order responde 404 not_found.
curl -X POST "$LIGGA_BASE/v1/sales" \ -H "Authorization: Bearer $LIGGA_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: pedido-loja-8842" \ -d '{ "customer_id": "9c8d7e6f-1a2b-4c3d-8e9f-0a1b2c3d4e5f", "transaction_type": "sale", "payment_method": "pix", "payment_status": "pending", "items": [ { "catalog_type": "product", "catalog_item_id": "b7e1f3a2-8c4d-4e5f-9a6b-1c2d3e4f5a6b", "quantity": 2, "unit_price": 49.9 }, { "catalog_type": "service", "catalog_item_id": "0d9e8f7a-6b5c-4d3e-2f1a-9b8c7d6e5f4a", "quantity": 1, "unit_price": 90, "discount_amount": 10 } ] }'Resposta 201 Created, já com items:
{ "data": { "id": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e", "customer_id": "9c8d7e6f-1a2b-4c3d-8e9f-0a1b2c3d4e5f", "transaction_type": "sale", "transaction_number": "000232", "status": "pending", "sale_date": "2026-07-10T14:05:00.000Z", "delivery_date": null, "subtotal": 189.8, "discount_amount": null, "discount_percentage": null, "tax_amount": null, "total_amount": 179.8, "notes": null, "payment_method": "pix", "payment_status": "pending", "delivery_fee": null, "order_code": null, "is_active": true, "created_at": "2026-07-10T14:05:01.000Z", "updated_at": null, "items": [ { "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "catalog_type": "product", "catalog_item_id": "b7e1f3a2-8c4d-4e5f-9a6b-1c2d3e4f5a6b", "quantity": 2, "unit_price": 49.9, "discount_amount": null, "discount_percentage": null, "subtotal": 99.8, "total_amount": 99.8, "notes": null, "created_at": "2026-07-10T14:05:01.000Z" }, { "id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e", "catalog_type": "service", "catalog_item_id": "0d9e8f7a-6b5c-4d3e-2f1a-9b8c7d6e5f4a", "quantity": 1, "unit_price": 90, "discount_amount": 10, "discount_percentage": null, "subtotal": 90, "total_amount": 80, "notes": null, "created_at": "2026-07-10T14:05:01.000Z" } ] }, "meta": { "request_id": "req_01J9ZXAMPLE" }}Atualizar
Seção intitulada “Atualizar”curl -X PATCH "$LIGGA_BASE/v1/sales/5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e" \ -H "Authorization: Bearer $LIGGA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "status": "completed", "payment_status": "paid" }'A mudança de status acrescenta uma entrada ao status_history, visível em
GET /v1/sales/{id}?include=status_history.
Cancelar
Seção intitulada “Cancelar”curl -X DELETE "$LIGGA_BASE/v1/sales/5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e" \ -H "Authorization: Bearer $LIGGA_API_KEY"A resposta é 204 No Content, sem corpo.
Erros comuns
Seção intitulada “Erros comuns”As respostas de erro usam application/problem+json, com type, title,
status e request_id. Os detalhes estão em Erros.
| HTTP | type |
Quando acontece |
|---|---|---|
| 401 | invalid_token |
Cabeçalho Authorization ausente ou chave inexistente |
| 401 | token_revoked |
A chave foi revogada |
| 401 | token_expired |
A chave passou da data de expiração |
| 403 | insufficient_scope |
A chave não tem sales:read ou sales:write |
| 403 | module_not_enabled |
Módulo vendas não habilitado no contrato |
| 404 | not_found |
id inexistente, de outra conta, ou que não é sale nem order |
| 409 | idempotency_conflict |
Mesma Idempotency-Key reenviada com outro corpo da requisição |
| 409 | resource_conflict |
Venda finalizada, parcela com histórico, recebimentos pendentes de estorno ou uso de escrita antiga em uma venda operacional |
| 503 | service_unavailable |
Disputa concorrente; repita com o mesmo UUID e corpo |
| 422 | validation |
Corpo ou filtro inválido, por exemplo items vazio, quantity menor ou igual a zero, ou operador não permitido |
| 429 | rate-limit-exceeded |
Limite de requisições do plano excedido |
Veja também
Seção intitulada “Veja também”- Clientes (customers) — o cliente indicado em
customer_id - Idempotência — como repetir um
POSTcom segurança - Paginação, filtros e ordenação —
cursor,filter,sortefields - Criar uma venda com itens — a receita completa

