Referência

Clientes

A ficha dos clientes e a sua conta corrente. Um cliente «Especial» tem conta corrente, desconto e limite de crédito; um cliente que não escolher é o «Consumidor Final».

A ficha dos clientes e a sua conta corrente. Um cliente «Especial» tem conta corrente, desconto e limite de crédito; um cliente que não escolher é o «Consumidor Final».

OperaçãoO que faz
GET /api/clientesLista os clientes, por ordem alfabética.
GET /api/clientes/{id}A ficha completa de um cliente.
GET /api/clientes/{id}/extractoO extracto da conta corrente de um cliente: cada débito (factura a crédito) e crédito (recibo, nota de crédito), com o documento e o saldo depois do movimento.
GET /api/clientes/{id}/resumoO resumo de compras de um cliente: o total comprado, o número de documentos e o que está em dívida.
POST /api/clientesCria um cliente.
PUT /api/clientes/{id}Actualiza a ficha de um cliente.
DELETE /api/clientes/{id}Elimina um cliente da lista.
GET /api/clientes/{id}/extracto/pdfO extracto de conta de um cliente em PDF.
POST /api/clientes/{id}/extracto/enviarEnvia o extracto de conta ao cliente por e-mail.
POST /api/clientes/{id}/movimentosRegista um movimento manual na conta corrente de um cliente (um ajuste ou um acerto).
GET/api/clientes#

Lista os clientes, por ordem alfabética.

  • Permissão Clientes.Ler

filtro procura no nome, no número de contribuinte, no telefone, no telemóvel e no e-mail. Os clientes eliminados não aparecem. Com alteradoDesde (data e hora ISO 8601 em UTC) só vêm os criados ou alterados desde esse instante, por ordem de alteração, e os eliminados aparecem marcados (eliminado: true): ver Sincronização incremental.

A resposta é uma página: itens e proximoCursor. Ver Paginação.

Parâmetros

NomeOndeTipoObrigatório
filtrona pesquisatexto
cursorna pesquisatexto
tamanhona pesquisanúmero inteiro
alteradoDesdena pesquisadata e hora (ISO 8601)

Resposta (200 · JSON)

CampoTipoSignificado
itenslista de objectosOs registos desta página.
itens[].ididentificador (UUID)Identificador único (UUID).
itens[].nometextoO nome.
itens[].numeroContribuintetexto ou nuloO número de contribuinte (NIF).
itens[].telefonetexto ou nuloO telefone.
itens[].especialverdadeiro/falsoCliente com conta corrente (desconto e limite de crédito).
itens[].saldoAtualnúmeroA dívida actual do cliente (conta corrente).
itens[].isProtegidoverdadeiro/falsoVerdadeiro no «Consumidor Final», que não se altera nem se elimina.
itens[].alteradoEmUtcdata e hora (ISO 8601)
itens[].eliminadoverdadeiro/falso
proximoCursortexto ou nuloO cursor da página seguinte; nulo quando não há mais. Ver Paginação.

Exemplo

Listar clientes (página de 2)

Pedido
curl 'https://<endereço-da-API>/api/clientes?tamanho=2' \
  -H 'X-Api-Key: assw_v1_<chave>'
Pedido
const resposta = await fetch('https://<endereço-da-API>/api/clientes?tamanho=2', {
  method: 'GET',
  headers: {
    "X-Api-Key": "assw_v1_<chave>"
  },
})
const dados = await resposta.json()
Pedido
import requests

resposta = requests.get(
    'https://<endereço-da-API>/api/clientes?tamanho=2',
    headers={
        'X-Api-Key': 'assw_v1_<chave>'
    },
)
dados = resposta.json()
Pedido
using var cliente = new HttpClient { BaseAddress = new Uri("https://<endereço-da-API>") };
using var pedido = new HttpRequestMessage(HttpMethod.Get, "/api/clientes?tamanho=2");
pedido.Headers.Add("X-Api-Key", "assw_v1_<chave>");
using var resposta = await cliente.SendAsync(pedido);
var texto = await resposta.Content.ReadAsStringAsync();

200 OK Resposta

Resposta
content-type: application/json; charset=utf-8
x-mucanda-api-version: 1

{
  "itens": [
    {
      "id": "01a12201-fa2a-7eec-8bcb-2f0b5e02bb8e",
      "nome": "Ana Beatriz Kiala",
      "numeroContribuinte": "004512987LA041",
      "telefone": "925112233",
      "especial": false,
      "saldoAtual": 0,
      "isProtegido": false
    },
    {
      "id": "01a12201-fa49-7e89-af00-dde77cab4010",
      "nome": "Cantina do Mercado Velho",
      "numeroContribuinte": "5417220318",
      "telefone": "928667788",
      "especial": false,
      "saldoAtual": 0,
      "isProtegido": false
    }
  ],
  "proximoCursor": "Q2FudGluYSBkbyBNZXJjYWRvIFZlbGhvIDAxYTEyMjAxLWZhNDktN2U4OS1hZjAwLWRkZTc3Y2FiNDAxMA=="
}
GET/api/clientes/{id}#

A ficha completa de um cliente.

  • Permissão Clientes.Ler

Parâmetros

NomeOndeTipoObrigatório
idno caminhoidentificador (UUID)sim

Resposta (200 · JSON)

CampoTipoSignificado
ididentificador (UUID)Identificador único (UUID).
nometextoO nome.
enderecotextoA morada.
numeroContribuintetexto ou nuloO número de contribuinte (NIF).
isConsumidorFinalverdadeiro/falsoVerdadeiro no cliente sem identificação fiscal.
telefonetexto ou nuloO telefone.
telemoveltexto ou nuloO telemóvel.
faxtexto ou nulo
emailtexto ou nuloO endereço de e-mail.
websitetexto ou nulo
especialverdadeiro/falsoCliente com conta corrente (desconto e limite de crédito).
pvpPreferidotexto ou nulo
condicaoPagamentoIdidentificador (UUID) ou nulo
descontonúmero ou nuloO desconto habitual do cliente, em percentagem.
limiteCreditonúmero ou nuloO limite de crédito (cliente com conta corrente).
observacaotexto ou nuloO texto livre.
taxaRetencaoIdidentificador (UUID) ou nulo
municipioIdidentificador (UUID) ou nulo
enviarAlertasverdadeiro/falso
enviarDocumentosverdadeiro/falso
saldoAtualnúmeroA dívida actual do cliente (conta corrente).
isProtegidoverdadeiro/falsoVerdadeiro no «Consumidor Final», que não se altera nem se elimina.
pessoaSingularverdadeiro/falso

Erros específicos

NAO_ENCONTRADO — além dos gerais.

Exemplo

Obter um cliente

Pedido
curl 'https://<endereço-da-API>/api/clientes/01a12f69-98f8-7688-85b9-8d829c101c8b' \
  -H 'X-Api-Key: assw_v1_<chave>'
Pedido
const resposta = await fetch('https://<endereço-da-API>/api/clientes/01a12f69-98f8-7688-85b9-8d829c101c8b', {
  method: 'GET',
  headers: {
    "X-Api-Key": "assw_v1_<chave>"
  },
})
const dados = await resposta.json()
Pedido
import requests

resposta = requests.get(
    'https://<endereço-da-API>/api/clientes/01a12f69-98f8-7688-85b9-8d829c101c8b',
    headers={
        'X-Api-Key': 'assw_v1_<chave>'
    },
)
dados = resposta.json()
Pedido
using var cliente = new HttpClient { BaseAddress = new Uri("https://<endereço-da-API>") };
using var pedido = new HttpRequestMessage(HttpMethod.Get, "/api/clientes/01a12f69-98f8-7688-85b9-8d829c101c8b");
pedido.Headers.Add("X-Api-Key", "assw_v1_<chave>");
using var resposta = await cliente.SendAsync(pedido);
var texto = await resposta.Content.ReadAsStringAsync();

200 OK Resposta

Resposta
content-type: application/json; charset=utf-8
x-mucanda-api-version: 1

{
  "id": "01a12f69-98f8-7688-85b9-8d829c101c8b",
  "nome": "Mercearia Cazenga Nova",
  "endereco": "Rua 5, Cazenga, Luanda",
  "numeroContribuinte": "5520879633",
  "isConsumidorFinal": false,
  "telefone": null,
  "telemovel": "926000111",
  "fax": null,
  "email": "compras@mercearia-cazenga.example",
  "website": null,
  "especial": false,
  "pvpPreferido": null,
  "condicaoPagamentoId": null,
  "desconto": null,
  "limiteCredito": null,
  "observacao": null,
  "taxaRetencaoId": null,
  "municipioId": null,
  "enviarAlertas": false,
  "enviarDocumentos": true,
  "saldoAtual": 0,
  "isProtegido": false
}
GET/api/clientes/{id}/extracto#

O extracto da conta corrente de um cliente: cada débito (factura a crédito) e crédito (recibo, nota de crédito), com o documento e o saldo depois do movimento.

  • Permissão Clientes.Ler

A resposta é uma página: itens e proximoCursor. Ver Paginação.

Parâmetros

NomeOndeTipoObrigatório
idno caminhoidentificador (UUID)sim
cursorna pesquisatexto
tamanhona pesquisanúmero inteiro

Resposta (200 · JSON)

CampoTipoSignificado
itenslista de objectosOs registos desta página.
itens[].ididentificador (UUID)Identificador único (UUID).
itens[].datadata e hora (ISO 8601)A data e hora (UTC).
itens[].valornúmeroO valor.
itens[].tipotexto
itens[].documentotexto ou nulo
itens[].saldoAposMovimentonúmeroO saldo depois deste movimento.
proximoCursortexto ou nuloO cursor da página seguinte; nulo quando não há mais. Ver Paginação.

Pedido

curl
curl 'https://<endereço-da-API>/api/clientes/<id>/extracto' \
  -H 'X-Api-Key: <a-sua-chave>'
GET/api/clientes/{id}/resumo#

O resumo de compras de um cliente: o total comprado, o número de documentos e o que está em dívida.

  • Permissão Clientes.Ler

Parâmetros

NomeOndeTipoObrigatório
idno caminhoidentificador (UUID)sim

Resposta (200 · JSON)

CampoTipo
totalCompradonúmero
documentosnúmero inteiro
emDividanúmero

Pedido

curl
curl 'https://<endereço-da-API>/api/clientes/<id>/resumo' \
  -H 'X-Api-Key: <a-sua-chave>'
POST/api/clientes#

Cria um cliente.

  • Permissão Clientes.Editar
  • Idempotência aceita Idempotency-Key

nome e endereco são obrigatórios. numeroContribuinte não pode repetir-se na empresa (erro DUPLICADO).

Para um cliente com conta corrente envie especial: true com limiteCredito (e, se quiser, desconto).

Aceita Idempotency-Key: repetir o pedido com a mesma chave devolve o cliente já criado, sem o duplicar.

Corpo do pedido (JSON · CreateClienteCommand)

CampoTipoObrigatórioSignificado
nometextosimO nome.
enderecotextosimA morada.
numeroContribuintetexto ou nuloO número de contribuinte (NIF).
isConsumidorFinalverdadeiro/falsosimVerdadeiro no cliente sem identificação fiscal.
emailtexto ou nuloO endereço de e-mail.
telefonetexto ou nuloO telefone.
telemoveltexto ou nuloO telemóvel.
faxtexto ou nulo
websitetexto ou nulo
municipioIdidentificador (UUID) ou nulo
taxaRetencaoIdidentificador (UUID) ou nulo
enviarAlertasverdadeiro/falsosim
enviarDocumentosverdadeiro/falsosim
observacaotexto ou nuloO texto livre.
especialverdadeiro/falsosimCliente com conta corrente (desconto e limite de crédito).
pvpPreferidouma de: «Pvp1», «Pvp2», «Pvp3», «Pvp4», «null» ou nulo
condicaoPagamentoIdidentificador (UUID) ou nulo
descontonúmero ou nuloO desconto habitual do cliente, em percentagem.
limiteCreditonúmero ou nuloO limite de crédito (cliente com conta corrente).
pessoaSingularverdadeiro/falso

Resposta

Devolve 201 com o identificador do cliente criado: { "id": "…" }.

Erros específicos

DUPLICADO · ERRO_DE_VALIDACAO · IDEMPOTENCIA_CONFLITO — além dos gerais.

Exemplo

Criar um cliente (com Idempotency-Key)

Pedido
curl -X POST 'https://<endereço-da-API>/api/clientes' \
  -H 'Idempotency-Key: b2a756b8-b776-4fd1-9af3-ba4e60f115f3' \
  -H 'X-Api-Key: assw_v1_<chave>' \
  -H 'Content-Type: application/json' \
  -d '{
  "nome": "Mercearia Cazenga Nova",
  "endereco": "Rua 5, Cazenga, Luanda",
  "numeroContribuinte": "5520879633",
  "isConsumidorFinal": false,
  "email": "compras@mercearia-cazenga.example",
  "telefone": null,
  "telemovel": "926000111",
  "fax": null,
  "website": null,
  "municipioId": null,
  "taxaRetencaoId": null,
  "enviarAlertas": false,
  "enviarDocumentos": true,
  "observacao": null,
  "especial": false,
  "pvpPreferido": "Pvp1",
  "condicaoPagamentoId": null,
  "desconto": null,
  "limiteCredito": null
}'
Pedido
const resposta = await fetch('https://<endereço-da-API>/api/clientes', {
  method: 'POST',
  headers: {
    "Idempotency-Key": "b2a756b8-b776-4fd1-9af3-ba4e60f115f3",
    "X-Api-Key": "assw_v1_<chave>",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "nome": "Mercearia Cazenga Nova",
    "endereco": "Rua 5, Cazenga, Luanda",
    "numeroContribuinte": "5520879633",
    "isConsumidorFinal": false,
    "email": "compras@mercearia-cazenga.example",
    "telefone": null,
    "telemovel": "926000111",
    "fax": null,
    "website": null,
    "municipioId": null,
    "taxaRetencaoId": null,
    "enviarAlertas": false,
    "enviarDocumentos": true,
    "observacao": null,
    "especial": false,
    "pvpPreferido": "Pvp1",
    "condicaoPagamentoId": null,
    "desconto": null,
    "limiteCredito": null
  }),
})
const dados = await resposta.json()
Pedido
import requests

resposta = requests.post(
    'https://<endereço-da-API>/api/clientes',
    headers={
        'Idempotency-Key': 'b2a756b8-b776-4fd1-9af3-ba4e60f115f3',
        'X-Api-Key': 'assw_v1_<chave>',
        'Content-Type': 'application/json'
    },
    json={
        'nome': 'Mercearia Cazenga Nova',
        'endereco': 'Rua 5, Cazenga, Luanda',
        'numeroContribuinte': '5520879633',
        'isConsumidorFinal': False,
        'email': 'compras@mercearia-cazenga.example',
        'telefone': None,
        'telemovel': '926000111',
        'fax': None,
        'website': None,
        'municipioId': None,
        'taxaRetencaoId': None,
        'enviarAlertas': False,
        'enviarDocumentos': True,
        'observacao': None,
        'especial': False,
        'pvpPreferido': 'Pvp1',
        'condicaoPagamentoId': None,
        'desconto': None,
        'limiteCredito': None
    },
)
dados = resposta.json()
Pedido
using var cliente = new HttpClient { BaseAddress = new Uri("https://<endereço-da-API>") };
using var pedido = new HttpRequestMessage(HttpMethod.Post, "/api/clientes");
pedido.Headers.Add("Idempotency-Key", "b2a756b8-b776-4fd1-9af3-ba4e60f115f3");
pedido.Headers.Add("X-Api-Key", "assw_v1_<chave>");
pedido.Content = new StringContent("""
{
  "nome": "Mercearia Cazenga Nova",
  "endereco": "Rua 5, Cazenga, Luanda",
  "numeroContribuinte": "5520879633",
  "isConsumidorFinal": false,
  "email": "compras@mercearia-cazenga.example",
  "telefone": null,
  "telemovel": "926000111",
  "fax": null,
  "website": null,
  "municipioId": null,
  "taxaRetencaoId": null,
  "enviarAlertas": false,
  "enviarDocumentos": true,
  "observacao": null,
  "especial": false,
  "pvpPreferido": "Pvp1",
  "condicaoPagamentoId": null,
  "desconto": null,
  "limiteCredito": null
}
""", Encoding.UTF8, "application/json");
using var resposta = await cliente.SendAsync(pedido);
var texto = await resposta.Content.ReadAsStringAsync();

201 Created Resposta

Resposta
content-type: application/json; charset=utf-8
x-mucanda-api-version: 1
location: /api/clientes/01a12f69-98f8-7688-85b9-8d829c101c8b

{
  "id": "01a12f69-98f8-7688-85b9-8d829c101c8b"
}
PUT/api/clientes/{id}#

Actualiza a ficha de um cliente.

  • Permissão Clientes.Editar

Substitui a ficha inteira: o que não for enviado fica sem valor. O caminho certo é ler o cliente (GET), alterar o que precisa e enviar todos os campos.

O cliente «Consumidor Final» é protegido e não se altera.

Parâmetros

NomeOndeTipoObrigatório
idno caminhoidentificador (UUID)sim

Corpo do pedido (JSON · UpdateClienteRequest)

CampoTipoObrigatórioSignificado
nometextosimO nome.
enderecotextosimA morada.
numeroContribuintetexto ou nuloO número de contribuinte (NIF).
isConsumidorFinalverdadeiro/falsosimVerdadeiro no cliente sem identificação fiscal.
emailtexto ou nuloO endereço de e-mail.
telefonetexto ou nuloO telefone.
telemoveltexto ou nuloO telemóvel.
faxtexto ou nulo
websitetexto ou nulo
municipioIdidentificador (UUID) ou nulo
taxaRetencaoIdidentificador (UUID) ou nulo
enviarAlertasverdadeiro/falsosim
enviarDocumentosverdadeiro/falsosim
observacaotexto ou nuloO texto livre.
especialverdadeiro/falsosimCliente com conta corrente (desconto e limite de crédito).
pvpPreferidouma de: «Pvp1», «Pvp2», «Pvp3», «Pvp4», «null» ou nulo
condicaoPagamentoIdidentificador (UUID) ou nulo
descontonúmero ou nuloO desconto habitual do cliente, em percentagem.
limiteCreditonúmero ou nuloO limite de crédito (cliente com conta corrente).
pessoaSingularverdadeiro/falso

Resposta

Devolve 204 sem corpo.

Erros específicos

DUPLICADO · NAO_ENCONTRADO — além dos gerais.

Pedido

curl
curl -X PUT 'https://<endereço-da-API>/api/clientes/<id>' \
  -H 'X-Api-Key: <a-sua-chave>' \
  -H 'Content-Type: application/json' \
  -d '{
  "nome": "texto",
  "endereco": "texto",
  "isConsumidorFinal": false,
  "enviarAlertas": false,
  "enviarDocumentos": false,
  "especial": false
}'
DELETE/api/clientes/{id}#

Elimina um cliente da lista.

  • Permissão Clientes.Editar

O cliente deixa de aparecer, mas o histórico não se apaga: os documentos já emitidos mantêm o cliente tal como estava.

O «Consumidor Final» não se elimina.

Parâmetros

NomeOndeTipoObrigatório
idno caminhoidentificador (UUID)sim

Resposta

Devolve 204 sem corpo.

Pedido

curl
curl -X DELETE 'https://<endereço-da-API>/api/clientes/<id>' \
  -H 'X-Api-Key: <a-sua-chave>'
GET/api/clientes/{id}/extracto/pdf#

O extracto de conta de um cliente em PDF.

  • Permissão Clientes.Ler

de e ate (dias, hora legal de Angola) limitam o período. É o extracto do ledger do cliente.

Parâmetros

NomeOndeTipoObrigatório
idno caminhoidentificador (UUID)sim
dena pesquisadata (AAAA-MM-DD)
atena pesquisadata (AAAA-MM-DD)

Resposta

Devolve 200 com o ficheiro PDF (application/pdf).

Pedido

curl
curl 'https://<endereço-da-API>/api/clientes/<id>/extracto/pdf' \
  -H 'X-Api-Key: <a-sua-chave>'
POST/api/clientes/{id}/extracto/enviar#

Envia o extracto de conta ao cliente por e-mail.

  • Permissão Documentos.Emitir
  • Idempotência aceita Idempotency-Key

Não é idempotente: repetir envia outro e-mail.

Parâmetros

NomeOndeTipoObrigatório
idno caminhoidentificador (UUID)sim

Corpo do pedido (JSON · EnviarExtractoRequest)

CampoTipoObrigatório
dedata (AAAA-MM-DD) ou nulo
atedata (AAAA-MM-DD) ou nulo
destinatariotexto ou nulo

Pedido

curl
curl -X POST 'https://<endereço-da-API>/api/clientes/<id>/extracto/enviar' \
  -H 'X-Api-Key: <a-sua-chave>' \
  -H 'Idempotency-Key: <um-GUID-novo>' \
  -H 'Content-Type: application/json' \
  -d '{}'
POST/api/clientes/{id}/movimentos#

Regista um movimento manual na conta corrente de um cliente (um ajuste ou um acerto).

  • Permissão Clientes.Editar
  • Idempotência aceita Idempotency-Key

O extracto só se acrescenta: um erro corrige-se com um movimento contrário.

Parâmetros

NomeOndeTipoObrigatório
idno caminhoidentificador (UUID)sim

Corpo do pedido (JSON · RegistarMovimentoRequest)

CampoTipoObrigatórioSignificado
datadata e hora (ISO 8601)simA data e hora (UTC).
valornúmerosimO valor.
tipouma de: «Debito», «Credito»sim
documentotexto ou nulo

Pedido

curl
curl -X POST 'https://<endereço-da-API>/api/clientes/<id>/movimentos' \
  -H 'X-Api-Key: <a-sua-chave>' \
  -H 'Idempotency-Key: <um-GUID-novo>' \
  -H 'Content-Type: application/json' \
  -d '{
  "data": "2026-10-12T09:00:00Z",
  "valor": 0,
  "tipo": "Debito"
}'