Customers API

Gestão de clientes - pessoas ou empresas a quem emites documentos fiscais.

Criar Cliente

POST/v1/organisations/:orgId/customers

É preciso indicar pelo menos um de: name, taxId, ou marcar isConsumidorFinal. Se enviares só taxId sem name, o Vero tenta preencher o nome automaticamente a partir do NIF junto da AGT.

Request Body

JSON
{
  "name": "Cliente de Teste",
  "taxId": "5000123456",
  "email": "cliente@teste.ao",
  "phone": "923456789",
  "addressLine1": "Rua Amílcar Cabral, 45",
  "addressLine2": "2º andar",
  "city": "Luanda",
  "province": "Luanda",
  "country": "AO"
}
namestring?Nome do cliente - obrigatório se taxId não for enviado
taxIdstring?NIF - obrigatório se name não for enviado
emailstring?Usado para enviar documentos por email
phonestring?
addressLine1 / addressLine2string?Morada
city / provincestring?
countrystring?Default 'AO'
externalIdstring?ID único na tua base de dados - útil para sincronizar sem duplicar
isConsumidorFinalboolean?Marca como Consumidor Final - usa o NIF genérico 999999999 nas facturas

Resposta (201 Created)

JSON
{
  "id": "b2c3d4e5-...",
  "orgId": "779b90ce-...",
  "name": "Cliente de Teste",
  "taxId": "5000123456",
  "email": "cliente@teste.ao",
  "phone": "923456789",
  "addressLine1": "Rua Amílcar Cabral, 45",
  "addressLine2": "2º andar",
  "city": "Luanda",
  "province": "Luanda",
  "country": "AO",
  "externalId": null,
  "isConsumidorFinal": false,
  "createdAt": "2026-05-12T10:00:00.000Z",
  "updatedAt": "2026-05-12T10:00:00.000Z"
}

Garantir Cliente (ensure)

POST/v1/organisations/:orgId/customers/ensure

Cria o cliente se não existir, ou devolve o existente com o mesmo externalId - evita duplicados quando sincronizas a partir de um sistema externo (ex: o utilizador da tua loja). externalId e name são obrigatórios aqui.

Com uma chave test, o cliente nunca é gravado na base de dados - a resposta devolve um id efémero (formato sandbox_cus_..., não é UUID) reconstruído a partir do próprio pedido. Usa-o normalmente como customerId ao criar a factura, mas não vai aparecer num GET /customers a seguir.

Listar / Ver / Actualizar / Remover

GET/v1/organisations/:orgId/customersLista clientes - paginado ({data, meta}), aceita ?search= e ?debt=true. Cada cliente traz balance e overdue; meta.receivables tem o total em dívida
GET/v1/organisations/:orgId/customers/:idDetalhes de um cliente
PATCH/v1/organisations/:orgId/customers/:idActualiza campos (mesma forma do corpo de criação)
DELETE/v1/organisations/:orgId/customers/:idRemove o cliente

Extrato de conta corrente

O saldo de cada cliente é calculado a partir dos documentos, por isso está sempre actualizado: facturas e notas de débito a débito, recibos e notas de crédito a crédito, factura-recibo nos dois lados. Um recibo emitido entra logo no saldo - não há nada para actualizar. Valores em cêntimos. É informativo: não é comunicado à AGT.

GET/v1/organisations/:orgId/customers/:id/statementExtrato (JSON). ?from=AAAA-MM-DD&to=AAAA-MM-DD; sem from = desde o início
GET/v1/organisations/:orgId/customers/:id/statement?format=pdfO mesmo em PDF (ou format=xlsx para Excel)
POST/v1/organisations/:orgId/customers/:id/statement/sendEnvia o PDF por email ao cliente. Corpo: { to?, from?, until?, message? }
GET .../statement?from=2026-01-01
{
  "period": { "from": "2026-01-01T00:00:00.000Z", "to": "2026-10-09T22:59:59.999Z" },
  "openingBalance": 0,
  "movements": [
    { "date": "2026-08-05T10:00:00Z", "type": "FT", "number": "FT A/2026/57", "description": "Factura", "debit": 32000000, "credit": 0, "balance": 32000000 },
    { "date": "2026-08-28T10:00:00Z", "type": "RC", "number": "RC A/2026/24", "description": "Pagamento parcial · FT A/2026/57", "debit": 0, "credit": 12000000, "balance": 20000000 }
  ],
  "totals": { "debit": 32000000, "credit": 12000000 },
  "closingBalance": 20000000,
  "balance": 20000000,
  "aging": { "d0_30": 0, "d31_60": 20000000, "d61_90": 0, "d90": 0 },
  "openItems": [{ "type": "FT", "number": "FT A/2026/57", "days": 56, "total": 32000000, "paid": 12000000, "remaining": 20000000 }],
  "lastPayment": { "date": "2026-08-28T10:00:00Z", "amount": 12000000, "number": "RC A/2026/24" }
}

As notas de débito aparecem com pending: true: o Vero ainda não regista o pagamento de notas de débito. Uma factura anulada sem nota de crédito não entra no extrato.

Contas a receber e dívida anterior

Visão de toda a empresa: quanto devem, antiguidade e clientes com saldo. A dívida anterior é o que o cliente já devia antes do Vero (facturas de outro programa): entra no extrato como DA e os pagamentos dela como PG. Não são documentos fiscais: o recibo de uma dívida anterior emite-se no programa de origem. As facturas do Vero pagam-se sempre com recibo. Valores em cêntimos; datas AAAA-MM-DD, nunca no futuro.

GET/v1/organisations/:orgId/receivablesResumo (total, +30 dias, clientes, recebido em 30 dias), antiguidade e clientes por saldo
GET/v1/organisations/:orgId/customers/:id/prior-debtsDívidas anteriores do cliente, com os pagamentos registados
POST/v1/organisations/:orgId/customers/:id/prior-debtsRegista. Corpo: { items: [{ reference, date, amount, notes? }] } (até 200)
DELETE/v1/organisations/:orgId/prior-debts/:debtIdApaga uma registada por engano (409 se já tiver pagamentos)
POST/v1/organisations/:orgId/prior-debts/:debtId/paymentsRegista um pagamento. Corpo: { amount, date, notes? }; amount ≤ em falta
DELETE/v1/organisations/:orgId/prior-debt-payments/:paymentIdApaga um pagamento registado por engano
POST/v1/organisations/:orgId/prior-debts/importExcel/CSV (multipart, campo file): NIF ou Cliente, Documento, Data, Valor em dívida. Sem commit só analisa; ?commit=true grava e cria os clientes em falta
POST .../customers/:id/prior-debts
{
  "items": [
    { "reference": "FT 2026/0341 (Primavera)", "date": "2026-07-15", "amount": 25000000 },
    { "reference": "FT 2026/0399", "date": "2026-08-30", "amount": 5000000, "notes": "Saldo em aberto à data da migração" }
  ]
}