Pular para o conteúdo

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ódulovendas — precisa estar habilitado no contrato
Escopossales:read para ler; sales:write para criar, atualizar e cancelar
Operaçõesleitura e escrita
MétodoEndpointEscopoDescrição
GET/v1/salessales:readLista vendas e pedidos com paginação por cursor
GET/v1/sales/{id}sales:readBusca uma venda pelo id, com ?include=items,status_history
POST/v1/salessales:writeCria uma venda com itens e responde 201
PATCH/v1/sales/{id}sales:writeAtualiza status, pagamento, entrega e observações
DELETE/v1/sales/{id}sales:writeCancela a venda (status="cancelled") e responde 204
CampoTipoDescrição
iduuidIdentificador da venda
customer_iduuid | nullCliente associado à venda
transaction_typestringTipo da transação: sale para venda ou order para pedido
transaction_numberstring | nullNúmero sequencial da transação
statusstring | nullSituação da venda, por exemplo pending, completed ou cancelled
sale_datestring (ISO 8601) | nullData da venda
delivery_datestring (YYYY-MM-DD) | nullData de entrega
subtotalnumber | nullSoma dos subtotais dos itens, antes dos descontos
discount_amountnumber | nullDesconto em valor absoluto
discount_percentagenumber | nullDesconto percentual
tax_amountnumber | nullImpostos
total_amountnumber | nullValor total: itens com descontos mais delivery_fee
notesstring | nullObservações
payment_methodstring | nullForma de pagamento, por exemplo pix, credit_card ou cash
payment_statusstring | nullSituação do pagamento, por exemplo pending ou paid
delivery_feenumber | nullTaxa de entrega
order_codestring | nullCódigo do pedido, de uso livre na integração
is_activeboolean | nullSe o registro está ativo
created_atstring (ISO 8601)Data de criação
updated_atstring (ISO 8601) | nullData da última atualização
itemsTransactionItem[]Itens da venda, presentes apenas com ?include=items
status_historyTransactionStatusHistory[]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.

CampoTipoDescrição
iduuidIdentificador do item
catalog_typestringTipo do item do catálogo: product, service ou package
catalog_item_iduuidItem do catálogo, veja Produtos (products)
quantitynumberQuantidade
unit_pricenumberPreço unitário
discount_amountnumber | nullDesconto em valor no item
discount_percentagenumber | nullDesconto percentual no item
subtotalnumberquantity × unit_price, antes dos descontos
total_amountnumberTotal do item depois dos descontos
notesstring | nullObservações do item
created_atstring (ISO 8601)Data de criação
CampoTipoDescrição
iduuidIdentificador da entrada
old_statusstring | nullStatus anterior, null na criação
new_statusstringNovo status
change_reasonstring | nullMotivo da mudança
created_atstring (ISO 8601)Quando a mudança ocorreu
CampoTipoObrigatórioDescrição
itemsarray (1–200)simItens da venda, descritos abaixo
customer_iduuid | nullnãoCliente da venda
transaction_type'sale' | 'order'não, padrão saleVenda ou pedido
sale_datestring (ISO 8601)não, padrão agoraData da venda
delivery_datestring (YYYY-MM-DD) | nullnãoData de entrega
statusstringnão, padrão pendingStatus inicial
payment_methodstring | nullnãoForma de pagamento
payment_statusstring | nullnãoSituação do pagamento
delivery_feenumber ≥ 0 | nullnãoTaxa de entrega
order_codestring | nullnãoCódigo do pedido
notesstring | nullnãoObservações

Cada entrada de items:

CampoTipoObrigatórioDescrição
catalog_type'product' | 'service' | 'package'simTipo do item do catálogo
catalog_item_iduuidsimIdentificador do item do catálogo
quantitynumber > 0simQuantidade
unit_pricenumber ≥ 0simPreço unitário
discount_amountnumber ≥ 0nãoDesconto em valor
discount_percentagenumber 0–100nãoDesconto percentual
notesstring | nullnãoObservações do item

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.

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.

CampoUso típicoExemplo
customer_idvendas de um clientefilter[customer_id][eq]=9c8d7e6f-1a2b-4c3d-8e9f-0a1b2c3d4e5f
statuspor situaçãofilter[status][in]=pending,completed
transaction_typesó vendas ou só pedidosfilter[transaction_type][eq]=order
transaction_numberbusca pelo númerofilter[transaction_number][eq]=000123
payment_statuspagamentos pendentesfilter[payment_status][eq]=pending
payment_methodpor forma de pagamentofilter[payment_method][eq]=pix
sale_datepor períodofilter[sale_date][gte]=2026-07-01
total_amountpor faixa de valorfilter[total_amount][gte]=100
is_activeapenas ativosfilter[is_active][eq]=true
created_atpor data de criaçãofilter[created_at][gte]=2026-07-01T00:00:00Z
updated_atsincronização incrementalfilter[updated_at][gt]=2026-07-09T12:00:00Z
  • Ordenação: sort=created_at, sort=sale_date ou sort=total_amount. O padrão é -created_at, das mais recentes para as mais antigas.
  • Paginação por cursor: ?limit=50&cursor=<next_cursor>. O limit vai 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_date
GET /v1/sales?filter[customer_id][eq]=9c8d7e6f-1a2b-4c3d-8e9f-0a1b2c3d4e5f&filter[payment_status][eq]=pending
GET /v1/sales?filter[sale_date][gte]=2026-07-01&filter[sale_date][lt]=2026-08-01&limit=50

Os detalhes de cada parâmetro estão em Paginação, filtros e ordenação.

GET /v1/sales/{id} aceita o parâmetro include, com valores separados por vírgula:

  • items — itens da venda, ordenados por created_at crescente;
  • status_history — mudanças de status, em ordem cronológica.
GET /v1/sales/3f9a1b7e-2c4d-4e8f-b6a1-5d0c9e8f7a2b?include=items,status_history

Valores desconhecidos em include são ignorados. A listagem GET /v1/sales não aceita include, e a resposta do POST já vem com items.

Terminal window
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.

Terminal window
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.

Terminal window
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" }
}
Terminal window
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.

Terminal window
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.

As respostas de erro usam application/problem+json, com type, title, status e request_id. Os detalhes estão em Erros.

HTTPtypeQuando acontece
401invalid_tokenCabeçalho Authorization ausente ou chave inexistente
401token_revokedA chave foi revogada
401token_expiredA chave passou da data de expiração
403insufficient_scopeA chave não tem sales:read ou sales:write
403module_not_enabledMódulo vendas não habilitado no contrato
404not_foundid inexistente, de outra conta, ou que não é sale nem order
409idempotency_conflictMesma Idempotency-Key reenviada com outro corpo da requisição
422validationCorpo ou filtro inválido, por exemplo items vazio, quantity menor ou igual a zero, ou operador não permitido
429rate-limit-exceededLimite de requisições do plano excedido